在vs环境中跑动sift特征提取(代码部分)
因为在前两天的学习中发现。在opencv环境中跑动sift特征点提取还是比较困难的。
所以在此,进行记述。
遇到的问题分别有,csdn不愿意花费积分、配置gtk困难、教程海量然而能跑者鲜。描述不详尽等。
【然后我却是发现这个borwhess实在是不知道叫先生何名为好。】
话归正题。
以下跑动具体过程:
首先去:
http://blog.csdn.net/masibuaa/article/details/9246493
发现main.cpp
也就是:检测sift的部分。
这个回头慢慢凿。先跑起来:
sift主体:
- img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
- img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
- //默认提取的是LOWE格式的SIFT特征点
- //提取并显示第1幅图片上的特征点
- n1 = sift_features( img1, &feat1 );//检测图1中的SIFT特征点,n1是图1的特征点个数
- export_features("feature1.txt",feat1,n1);//将特征向量数据写入到文件
- draw_features( img1_Feat, feat1, n1 );//画出特征点
- cvNamedWindow(IMG1_FEAT);//创建窗口
- cvShowImage(IMG1_FEAT,img1_Feat);//显示
- //提取并显示第2幅图片上的特征点
- n2 = sift_features( img2, &feat2 );//检测图2中的SIFT特征点,n2是图2的特征点个数
- export_features("feature2.txt",feat2,n2);//将特征向量数据写入到文件
- draw_features( img2_Feat, feat2, n2 );//画出特征点
- cvNamedWindow(IMG2_FEAT);//创建窗口
- 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:
- /**@file
- Functions for detecting SIFT image features.
- For more information, refer to:
- Lowe, D. Distinctive image features from scale-invariant keypoints.
- <EM>International Journal of Computer Vision, 60</EM>, 2 (2004),
- pp.91--110.
- Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
- Note: The SIFT algorithm is patented in the United States and cannot be
- used in commercial products without a license from the University of
- British Columbia. For more information, refer to the file LICENSE.ubc
- that accompanied this distribution.
- @version 1.1.2-20100521
- */
- #ifndef SIFT_H
- #define SIFT_H
- #include "cxcore.h"
- /******************************** Structures *********************************/
- /** holds feature data relevant to detection */
- struct detection_data
- {
- int r;
- int c;
- int octv;
- int intvl;
- double subintvl;
- double scl_octv;
- };
- struct feature;
- /******************************* Defs and macros *****************************/
- /** default number of sampled intervals per octave */
- #define SIFT_INTVLS 3
- /** default sigma for initial gaussian smoothing */
- #define SIFT_SIGMA 1.6
- /** default threshold on keypoint contrast |D(x)| */
- #define SIFT_CONTR_THR 0.04
- /** default threshold on keypoint ratio of principle curvatures */
- #define SIFT_CURV_THR 10
- /** double image size before pyramid construction? */
- #define SIFT_IMG_DBL 1
- /** default width of descriptor histogram array */
- #define SIFT_DESCR_WIDTH 4
- /** default number of bins per histogram in descriptor array */
- #define SIFT_DESCR_HIST_BINS 8
- /* assumed gaussian blur for input image */
- #define SIFT_INIT_SIGMA 0.5
- /* width of border in which to ignore keypoints */
- #define SIFT_IMG_BORDER 5
- /* maximum steps of keypoint interpolation before failure */
- #define SIFT_MAX_INTERP_STEPS 5
- /* default number of bins in histogram for orientation assignment */
- #define SIFT_ORI_HIST_BINS 36
- /* determines gaussian sigma for orientation assignment */
- #define SIFT_ORI_SIG_FCTR 1.5
- /* determines the radius of the region used in orientation assignment */
- #define SIFT_ORI_RADIUS 3.0 * SIFT_ORI_SIG_FCTR
- /* number of passes of orientation histogram smoothing */
- #define SIFT_ORI_SMOOTH_PASSES 2
- /* orientation magnitude relative to max that results in new feature */
- #define SIFT_ORI_PEAK_RATIO 0.8
- /* determines the size of a single descriptor orientation histogram */
- #define SIFT_DESCR_SCL_FCTR 3.0
- /* threshold on magnitude of elements of descriptor vector */
- #define SIFT_DESCR_MAG_THR 0.2
- /* factor used to convert floating-point descriptor to unsigned char */
- #define SIFT_INT_DESCR_FCTR 512.0
- /* returns a feature's detection data */
- #define feat_detection_data(f) ( (struct detection_data*)(f->feature_data) )
- /*************************** Function Prototypes *****************************/
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**
- Finds SIFT features in an image using default parameter values. All
- detected features are stored in the array pointed to by \a feat.
- @param img the image in which to detect features
- @param feat a pointer to an array in which to store detected features; memory
- for this array is allocated by this function and must be freed by the caller
- using free(*feat)
- @return Returns the number of features stored in \a feat or -1 on failure
- @see _sift_features()
- */
- extern int sift_features(IplImage* img, struct feature** feat);
- /**
- Finda SIFT features in an image using user-specified parameter values. All
- detected features are stored in the array pointed to by \a feat.
- @param img the image in which to detect features
- @param feat a pointer to an array in which to store detected features; memory
- for this array is allocated by this function and must be freed by the caller
- using free(*feat)
- @param intvls the number of intervals sampled per octave of scale space
- @param sigma the amount of Gaussian smoothing applied to each image level
- before building the scale space representation for an octave
- @param contr_thr a threshold on the value of the scale space function
- \f$\left|D(\hat{x})\right|\f$, where \f$\hat{x}\f$ is a vector specifying
- feature location and scale, used to reject unstable features; assumes
- pixel values in the range [0, 1]
- @param curv_thr threshold on a feature's ratio of principle curvatures
- used to reject features that are too edge-like
- @param img_dbl should be 1 if image doubling prior to scale space
- construction is desired or 0 if not
- @param descr_width the width, \f$n\f$, of the \f$n \times n\f$ array of
- orientation histograms used to compute a feature's descriptor
- @param descr_hist_bins the number of orientations in each of the
- histograms in the array used to compute a feature's descriptor
- @return Returns the number of keypoints stored in \a feat or -1 on failure
- @see sift_features()
- */
- extern int _sift_features(IplImage* img, struct feature** feat, int intvls,
- double sigma, double contr_thr, int curv_thr,
- int img_dbl, int descr_width, int descr_hist_bins);
- #ifdef __cplusplus
- }
- #endif
- #endif
imgfeatures.h
- /**@file
- Functions and structures for dealing with image features
- Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
- @version 1.1.2-20100521
- */
- #ifndef IMGFEATURES_H
- #define IMGFEATURES_H
- #include "cxcore.h"
- /** FEATURE_OXFD <BR> FEATURE_LOWE */
- enum feature_type
- {
- FEATURE_OXFD,
- FEATURE_LOWE,
- };
- /** FEATURE_FWD_MATCH <BR> FEATURE_BCK_MATCH <BR> FEATURE_MDL_MATCH */
- enum feature_match_type
- {
- FEATURE_FWD_MATCH,
- FEATURE_BCK_MATCH,
- FEATURE_MDL_MATCH,
- };
- /* colors in which to display different feature types */
- #define FEATURE_OXFD_COLOR CV_RGB(255,255,0)
- #define FEATURE_LOWE_COLOR CV_RGB(255,0,255)
- /** max feature descriptor length */
- #define FEATURE_MAX_D 128
- /**
- Structure to represent an affine invariant image feature. The fields
- x, y, a, b, c represent the affine region around the feature:
- a(x-u)(x-u) + 2b(x-u)(y-v) + c(y-v)(y-v) = 1
- */
- struct feature
- {
- double x; /**< x coord */
- double y; /**< y coord */
- double a; /**< Oxford-type affine region parameter */
- double b; /**< Oxford-type affine region parameter */
- double c; /**< Oxford-type affine region parameter */
- double scl; /**< scale of a Lowe-style feature */
- double ori; /**< orientation of a Lowe-style feature */
- int d; /**< descriptor length */
- double descr[FEATURE_MAX_D]; /**< descriptor */
- int type; /**< feature type, OXFD or LOWE */
- int category; /**< all-purpose feature category */
- struct feature* fwd_match; /**< matching feature from forward image */
- struct feature* bck_match; /**< matching feature from backmward image */
- struct feature* mdl_match; /**< matching feature from model */
- CvPoint2D64f img_pt; /**< location in image */
- CvPoint2D64f mdl_pt; /**< location in model */
- void* feature_data; /**< user-definable data */
- };
- #ifdef __cplusplus
- extern "C" {
- #endif
- /**
- Reads image features from file. The file should be formatted as from
- the code provided by the Visual Geometry Group at Oxford or from the
- code provided by David Lowe.
- @param filename location of a file containing image features
- @param type determines how features are input. If \a type is FEATURE_OXFD,
- the input file is treated as if it is from the code provided by the VGG
- at Oxford: http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
- <BR><BR>
- If \a type is FEATURE_LOWE, the input file is treated as if it is from
- David Lowe's SIFT code: http://www.cs.ubc.ca/~lowe/keypoints
- @param feat pointer to an array in which to store imported features; memory for
- this array is allocated by this function and must be freed by the caller using
- free(*feat)
- @return Returns the number of features imported from filename or -1 on error
- */
- extern int import_features(char* filename, int type, struct feature** feat);
- /**
- Exports a feature set to a file formatted depending on the type of
- features, as specified in the feature struct's type field.
- @param filename name of file to which to export features
- @param feat feature array
- @param n number of features
- @return Returns 0 on success or 1 on error
- */
- extern int export_features(char* filename, struct feature* feat, int n);
- /**
- Displays a set of features on an image
- @param img image on which to display features
- @param feat array of Oxford-type features
- @param n number of features
- */
- extern void draw_features(IplImage* img, struct feature* feat, int n);
- /**
- Calculates the squared Euclidian distance between two feature descriptors.
- @param f1 first feature
- @param f2 second feature
- @return Returns the squared Euclidian distance between the descriptors of
- \a f1 and \a f2.
- */
- extern double descr_dist_sq(struct feature* f1, struct feature* f2);
- #ifdef __cplusplus
- }
- #endif
- #endif
utils.h
- /**@file
- Miscellaneous utility functions.
- Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
- @version 1.1.2-20100521
- */
- #ifndef UTILS_H
- #define UTILS_H
- #include "cxcore.h"
- #include <stdio.h>
- /* absolute value */
- #ifndef ABS
- #define ABS(x) ( ( (x) < 0 )? -(x) : (x) )
- #endif
- /***************************** Inline Functions ******************************/
- /**
- A function to get a pixel value from an 8-bit unsigned image.
- @param img an image
- @param r row
- @param c column
- @return Returns the value of the pixel at (\a r, \a c) in \a img
- */
- static __inline int pixval8(IplImage* img, int r, int c)
- {
- return (int)(((uchar*)(img->imageData + img->widthStep*r))[c]);
- }
- /**
- A function to set a pixel value in an 8-bit unsigned image.
- @param img an image
- @param r row
- @param c column
- @param val pixel value
- */
- static __inline void setpix8(IplImage* img, int r, int c, uchar val)
- {
- ((uchar*)(img->imageData + img->widthStep*r))[c] = val;
- }
- /**
- A function to get a pixel value from a 32-bit floating-point image.
- @param img an image
- @param r row
- @param c column
- @return Returns the value of the pixel at (\a r, \a c) in \a img
- */
- static __inline float pixval32f(IplImage* img, int r, int c)
- {
- return ((float*)(img->imageData + img->widthStep*r))[c];
- }
- /**
- A function to set a pixel value in a 32-bit floating-point image.
- @param img an image
- @param r row
- @param c column
- @param val pixel value
- */
- static __inline void setpix32f(IplImage* img, int r, int c, float val)
- {
- ((float*)(img->imageData + img->widthStep*r))[c] = val;
- }
- /**
- A function to get a pixel value from a 64-bit floating-point image.
- @param img an image
- @param r row
- @param c column
- @return Returns the value of the pixel at (\a r, \a c) in \a img
- */
- static __inline double pixval64f(IplImage* img, int r, int c)
- {
- return (double)(((double*)(img->imageData + img->widthStep*r))[c]);
- }
- /**
- A function to set a pixel value in a 64-bit floating-point image.
- @param img an image
- @param r row
- @param c column
- @param val pixel value
- */
- static __inline void setpix64f(IplImage* img, int r, int c, double val)
- {
- ((double*)(img->imageData + img->widthStep*r))[c] = val;
- }
- /**************************** Function Prototypes ****************************/
- /**
- 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)).
- */
- extern void fatal_error(char* format, ...);
- /**
- 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.
- */
- extern char* replace_extension(const char* file, const char* extn);
- /**
- 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.
- */
- extern char* basename(const char* pathname);
- /**
- 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"
- */
- extern void progress(int done);
- /**
- 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
- */
- extern void erase_from_stream(FILE* stream, int n);
- /**
- 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.
- */
- extern int array_double(void** array, int n, int size);
- /**
- Calculates the squared distance between two points.
- @param p1 a point
- @param p2 another point
- */
- extern double dist_sq_2D(CvPoint2D64f p1, CvPoint2D64f p2);
- /**
- 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
- */
- extern void draw_x(IplImage* img, CvPoint pt, int r, int w, CvScalar color);
- /**
- 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);
- /**
- 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 Up - skip forward 10 frames</li>
- <li>Page Down - 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
- */
- extern void vid_view(IplImage** imgs, int n, char* win_name);
- /**
- 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
- */
- extern int win_closed(char* name);
- #endif
imgfeatures.c
- /*
- Functions and structures for dealing with image features
- Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
- @version 1.1.2-20100521
- */
- #include "utils.h"
- #include "imgfeatures.h"
- #include <cxcore.h>
- #include <math.h>
- static int import_oxfd_features(char*, struct feature**);
- static int export_oxfd_features(char*, struct feature*, int);
- static void draw_oxfd_features(IplImage*, struct feature*, int);
- static void draw_oxfd_feature(IplImage*, struct feature*, CvScalar);
- static int import_lowe_features(char*, struct feature**);
- static int export_lowe_features(char*, struct feature*, int);
- static void draw_lowe_features(IplImage*, struct feature*, int);
- static void draw_lowe_feature(IplImage*, struct feature*, CvScalar);
- /*
- Reads image features from file. The file should be formatted as from
- the code provided by the Visual Geometry Group at Oxford:
- @param filename location of a file containing image features
- @param type determines how features are input. If \a type is FEATURE_OXFD,
- the input file is treated as if it is from the code provided by the VGG
- at Oxford:
- http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
- If \a type is FEATURE_LOWE, the input file is treated as if it is from
- David Lowe's SIFT code:
- http://www.cs.ubc.ca/~lowe/keypoints
- @param features pointer to an array in which to store features
- @return Returns the number of features imported from filename or -1 on error
- */
- int import_features(char* filename, int type, struct feature** feat)
- {
- int n;
- switch (type)
- {
- case FEATURE_OXFD:
- n = import_oxfd_features(filename, feat);
- break;
- case FEATURE_LOWE:
- n = import_lowe_features(filename, feat);
- break;
- default:
- fprintf(stderr, "Warning: import_features(): unrecognized feature" \
- "type, %s, line %d\n", __FILE__, __LINE__);
- return -;
- }
- if (n == -)
- fprintf(stderr, "Warning: unable to import features from %s," \
- " %s, line %d\n", filename, __FILE__, __LINE__);
- return n;
- }
- /*
- Exports a feature set to a file formatted depending on the type of
- features, as specified in the feature struct's type field.
- @param filename name of file to which to export features
- @param feat feature array
- @param n number of features
- @return Returns 0 on success or 1 on error
- */
- int export_features(char* filename, struct feature* feat, int n)
- {
- int r, type;
- if (n <= || !feat)
- {
- fprintf(stderr, "Warning: no features to export, %s line %d\n",
- __FILE__, __LINE__);
- return ;
- }
- type = feat[].type;
- switch (type)
- {
- case FEATURE_OXFD:
- r = export_oxfd_features(filename, feat, n);
- break;
- case FEATURE_LOWE:
- r = export_lowe_features(filename, feat, n);
- break;
- default:
- fprintf(stderr, "Warning: export_features(): unrecognized feature" \
- "type, %s, line %d\n", __FILE__, __LINE__);
- return -;
- }
- if (r)
- fprintf(stderr, "Warning: unable to export features to %s," \
- " %s, line %d\n", filename, __FILE__, __LINE__);
- return r;
- }
- /*
- Draws a set of features on an image
- @param img image on which to draw features
- @param feat array of Oxford-type features
- @param n number of features
- */
- void draw_features(IplImage* img, struct feature* feat, int n)
- {
- int type;
- if (n <= || !feat)
- {
- fprintf(stderr, "Warning: no features to draw, %s line %d\n",
- __FILE__, __LINE__);
- return;
- }
- type = feat[].type;
- switch (type)
- {
- case FEATURE_OXFD:
- draw_oxfd_features(img, feat, n);
- break;
- case FEATURE_LOWE:
- draw_lowe_features(img, feat, n);
- break;
- default:
- fprintf(stderr, "Warning: draw_features(): unrecognized feature" \
- " type, %s, line %d\n", __FILE__, __LINE__);
- break;
- }
- }
- /*
- Calculates the squared Euclidian distance between two feature descriptors.
- @param f1 first feature
- @param f2 second feature
- @return Returns the squared Euclidian distance between the descriptors of
- f1 and f2.
- */
- double descr_dist_sq(struct feature* f1, struct feature* f2)
- {
- double diff, dsq = ;
- double* descr1, *descr2;
- int i, d;
- d = f1->d;
- if (f2->d != d)
- return DBL_MAX;
- descr1 = f1->descr;
- descr2 = f2->descr;
- for (i = ; i < d; i++)
- {
- diff = descr1[i] - descr2[i];
- dsq += diff*diff;
- }
- return dsq;
- }
- /***************************** Local Functions *******************************/
- /*
- Reads image features from file. The file should be formatted as from
- the code provided by the Visual Geometry Group at Oxford:
- http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
- @param filename location of a file containing image features
- @param features pointer to an array in which to store features
- @return Returns the number of features imported from filename or -1 on error
- */
- static int import_oxfd_features(char* filename, struct feature** features)
- {
- struct feature* f;
- int i, j, n, d;
- double x, y, a, b, c, dv;
- FILE* file;
- if (!features)
- fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
- if (!(file = fopen(filename, "r")))
- {
- fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
- filename, __FILE__, __LINE__);
- return -;
- }
- /* read dimension and number of features */
- if (fscanf(file, " %d %d ", &d, &n) != )
- {
- fprintf(stderr, "Warning: file read error, %s, line %d\n",
- __FILE__, __LINE__);
- return -;
- }
- if (d > FEATURE_MAX_D)
- {
- fprintf(stderr, "Warning: descriptor too long, %s, line %d\n",
- __FILE__, __LINE__);
- return -;
- }
- f = calloc(n, sizeof(struct feature));
- for (i = ; i < n; i++)
- {
- /* read affine region parameters */
- if (fscanf(file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c) != )
- {
- fprintf(stderr, "Warning: error reading feature #%d, %s, line %d\n",
- i + , __FILE__, __LINE__);
- free(f);
- return -;
- }
- f[i].img_pt.x = f[i].x = x;
- f[i].img_pt.y = f[i].y = y;
- f[i].a = a;
- f[i].b = b;
- f[i].c = c;
- f[i].d = d;
- f[i].type = FEATURE_OXFD;
- /* read descriptor */
- for (j = ; j < d; j++)
- {
- if (!fscanf(file, " %lf ", &dv))
- {
- fprintf(stderr, "Warning: error reading feature descriptor" \
- " #%d, %s, line %d\n", i + , __FILE__, __LINE__);
- free(f);
- return -;
- }
- f[i].descr[j] = dv;
- }
- f[i].scl = f[i].ori = ;
- f[i].category = ;
- f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
- f[i].mdl_pt.x = f[i].mdl_pt.y = -;
- f[i].feature_data = NULL;
- }
- if (fclose(file))
- {
- fprintf(stderr, "Warning: file close error, %s, line %d\n",
- __FILE__, __LINE__);
- free(f);
- return -;
- }
- *features = f;
- return n;
- }
- /*
- Exports a feature set to a file formatted as one from the code provided
- by the Visual Geometry Group at Oxford:
- http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
- @param filename name of file to which to export features
- @param feat feature array
- @param n number of features
- @return Returns 0 on success or 1 on error
- */
- static int export_oxfd_features(char* filename, struct feature* feat, int n)
- {
- FILE* file;
- int i, j, d;
- if (n <= )
- {
- fprintf(stderr, "Warning: feature count %d, %s, line %s\n",
- n, __FILE__, __LINE__);
- return ;
- }
- if (!(file = fopen(filename, "w")))
- {
- fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
- filename, __FILE__, __LINE__);
- return ;
- }
- d = feat[].d;
- fprintf(file, "%d\n%d\n", d, n);
- for (i = ; i < n; i++)
- {
- fprintf(file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,
- feat[i].b, feat[i].c);
- for (j = ; j < d; j++)
- fprintf(file, " %f", feat[i].descr[j]);
- fprintf(file, "\n");
- }
- if (fclose(file))
- {
- fprintf(stderr, "Warning: file close error, %s, line %d\n",
- __FILE__, __LINE__);
- return ;
- }
- return ;
- }
- /*
- Draws Oxford-type affine features
- @param img image on which to draw features
- @param feat array of Oxford-type features
- @param n number of features
- */
- static void draw_oxfd_features(IplImage* img, struct feature* feat, int n)
- {
- CvScalar color = CV_RGB(, , );
- int i;
- if (img->nChannels > )
- color = FEATURE_OXFD_COLOR;
- for (i = ; i < n; i++)
- draw_oxfd_feature(img, feat + i, color);
- }
- /*
- Draws a single Oxford-type feature
- @param img image on which to draw
- @param feat feature to be drawn
- @param color color in which to draw
- */
- static void draw_oxfd_feature(IplImage* img, struct feature* feat, CvScalar color)
- {
- double m[] = { feat->a, feat->b, feat->b, feat->c };
- double v[] = { };
- double e[] = { };
- CvMat M, V, E;
- double alpha, l1, l2;
- /* compute axes and orientation of ellipse surrounding affine region */
- cvInitMatHeader(&M, , , CV_64FC1, m, CV_AUTOSTEP);
- cvInitMatHeader(&V, , , CV_64FC1, v, CV_AUTOSTEP);
- cvInitMatHeader(&E, , , CV_64FC1, e, CV_AUTOSTEP);
- cvEigenVV(&M, &V, &E, DBL_EPSILON, , );
- l1 = / sqrt(e[]);
- l2 = / sqrt(e[]);
- alpha = -atan2(v[], v[]);
- alpha *= / CV_PI;
- cvEllipse(img, cvPoint(feat->x, feat->y), cvSize(l2, l1), alpha,
- , , CV_RGB(, , ), , , );
- cvEllipse(img, cvPoint(feat->x, feat->y), cvSize(l2, l1), alpha,
- , , color, , , );
- cvLine(img, cvPoint(feat->x + , feat->y), cvPoint(feat->x - , feat->y),
- color, , , );
- cvLine(img, cvPoint(feat->x, feat->y + ), cvPoint(feat->x, feat->y - ),
- color, , , );
- }
- /*
- Reads image features from file. The file should be formatted as from
- the code provided by David Lowe:
- http://www.cs.ubc.ca/~lowe/keypoints/
- @param filename location of a file containing image features
- @param features pointer to an array in which to store features
- @return Returns the number of features imported from filename or -1 on error
- */
- static int import_lowe_features(char* filename, struct feature** features)
- {
- struct feature* f;
- int i, j, n, d;
- double x, y, s, o, dv;
- FILE* file;
- if (!features)
- fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
- if (!(file = fopen(filename, "r")))
- {
- fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
- filename, __FILE__, __LINE__);
- return -;
- }
- /* read number of features and dimension */
- if (fscanf(file, " %d %d ", &n, &d) != )
- {
- fprintf(stderr, "Warning: file read error, %s, line %d\n",
- __FILE__, __LINE__);
- return -;
- }
- if (d > FEATURE_MAX_D)
- {
- fprintf(stderr, "Warning: descriptor too long, %s, line %d\n",
- __FILE__, __LINE__);
- return -;
- }
- f = calloc(n, sizeof(struct feature));
- for (i = ; i < n; i++)
- {
- /* read affine region parameters */
- if (fscanf(file, " %lf %lf %lf %lf ", &y, &x, &s, &o) != )
- {
- fprintf(stderr, "Warning: error reading feature #%d, %s, line %d\n",
- i + , __FILE__, __LINE__);
- free(f);
- return -;
- }
- f[i].img_pt.x = f[i].x = x;
- f[i].img_pt.y = f[i].y = y;
- f[i].scl = s;
- f[i].ori = o;
- f[i].d = d;
- f[i].type = FEATURE_LOWE;
- /* read descriptor */
- for (j = ; j < d; j++)
- {
- if (!fscanf(file, " %lf ", &dv))
- {
- fprintf(stderr, "Warning: error reading feature descriptor" \
- " #%d, %s, line %d\n", i + , __FILE__, __LINE__);
- free(f);
- return -;
- }
- f[i].descr[j] = dv;
- }
- f[i].a = f[i].b = f[i].c = ;
- f[i].category = ;
- f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
- f[i].mdl_pt.x = f[i].mdl_pt.y = -;
- }
- if (fclose(file))
- {
- fprintf(stderr, "Warning: file close error, %s, line %d\n",
- __FILE__, __LINE__);
- free(f);
- return -;
- }
- *features = f;
- return n;
- }
- /*
- Exports a feature set to a file formatted as one from the code provided
- by David Lowe:
- http://www.cs.ubc.ca/~lowe/keypoints/
- @param filename name of file to which to export features
- @param feat feature array
- @param n number of features
- @return Returns 0 on success or 1 on error
- */
- static int export_lowe_features(char* filename, struct feature* feat, int n)
- {
- FILE* file;
- int i, j, d;
- if (n <= )
- {
- fprintf(stderr, "Warning: feature count %d, %s, line %s\n",
- n, __FILE__, __LINE__);
- return ;
- }
- if (!(file = fopen(filename, "w")))
- {
- fprintf(stderr, "Warning: error opening %s, %s, line %d\n",
- filename, __FILE__, __LINE__);
- return ;
- }
- d = feat[].d;
- fprintf(file, "%d %d\n", n, d);
- for (i = ; i < n; i++)
- {
- fprintf(file, "%f %f %f %f", feat[i].y, feat[i].x,
- feat[i].scl, feat[i].ori);
- for (j = ; j < d; j++)
- {
- /* write 20 descriptor values per line */
- if (j % == )
- fprintf(file, "\n");
- fprintf(file, " %d", (int)(feat[i].descr[j]));
- }
- fprintf(file, "\n");
- }
- if (fclose(file))
- {
- fprintf(stderr, "Warning: file close error, %s, line %d\n",
- __FILE__, __LINE__);
- return ;
- }
- return ;
- }
- /*
- Draws Lowe-type features
- @param img image on which to draw features
- @param feat array of Oxford-type features
- @param n number of features
- */
- static void draw_lowe_features(IplImage* img, struct feature* feat, int n)
- {
- CvScalar color = CV_RGB(, , );
- int i;
- if (img->nChannels > )
- color = FEATURE_LOWE_COLOR;
- for (i = ; i < n; i++)
- draw_lowe_feature(img, feat + i, color);
- }
- /*
- Draws a single Lowe-type feature
- @param img image on which to draw
- @param feat feature to be drawn
- @param color color in which to draw
- */
- static void draw_lowe_feature(IplImage* img, struct feature* feat, CvScalar color)
- {
- int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;
- double scl, ori;
- double scale = 5.0;
- double hscale = 0.75;
- CvPoint start, end, h1, h2;
- /* compute points for an arrow scaled and rotated by feat's scl and ori */
- start_x = cvRound(feat->x);
- start_y = cvRound(feat->y);
- scl = feat->scl;
- ori = feat->ori;
- len = cvRound(scl * scale);
- hlen = cvRound(scl * hscale);
- blen = len - hlen;
- end_x = cvRound(len * cos(ori)) + start_x;
- end_y = cvRound(len * -sin(ori)) + start_y;
- h1_x = cvRound(blen * cos(ori + CV_PI / 18.0)) + start_x;
- h1_y = cvRound(blen * -sin(ori + CV_PI / 18.0)) + start_y;
- h2_x = cvRound(blen * cos(ori - CV_PI / 18.0)) + start_x;
- h2_y = cvRound(blen * -sin(ori - CV_PI / 18.0)) + start_y;
- start = cvPoint(start_x, start_y);
- end = cvPoint(end_x, end_y);
- h1 = cvPoint(h1_x, h1_y);
- h2 = cvPoint(h2_x, h2_y);
- cvLine(img, start, end, color, , , );
- cvLine(img, end, h1, color, , , );
- cvLine(img, end, h2, color, , , );
- }
main.cpp
- #include "opencv2/highgui/highgui.hpp"//这个是基本类库,高级图形用户接口,必须要引入
- #include "sift.h"//解决了没有sift_features函数的问题
- #include "imgfeatures.h"//解决了找不到export_features 和draw_features 的问题
- #include "utils.h"
- int main(){
- IplImage * img1 = cvLoadImage("a.png");
- IplImage * img2 = cvLoadImage("b.png");
- IplImage *img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
- IplImage *img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
- img1_Feat = cvCloneImage(img1);//复制图1,深拷贝,用来画特征点
- img2_Feat = cvCloneImage(img2);//复制图2,深拷贝,用来画特征点
- //默认提取的是LOWE格式的SIFT特征点
- //提取并显示第1幅图片上的特征点
- feature *feat1, *feat2;
- int n1 = sift_features(img1, &feat1);//检测图1中的SIFT特征点,n1是图1的特征点个数
- export_features("feature1.txt", feat1, n1);//将特征向量数据写入到文件
- draw_features(img1_Feat, feat1, n1);//画出特征点
- cvNamedWindow("IMG1_FEAT");//创建窗口
- cvShowImage("IMG1_FEAT", img1_Feat);//显示
- //提取并显示第2幅图片上的特征点
- int n2 = sift_features(img2, &feat2);//检测图2中的SIFT特征点,n2是图2的特征点个数
- export_features("feature2.txt", feat2, n2);//将特征向量数据写入到文件
- draw_features(img2_Feat, feat2, n2);//画出特征点
- cvNamedWindow("IMG2_FEAT");//创建窗口
- cvShowImage("IMG2_FEAT", img2_Feat);//显示
- cvWaitKey();
- }
sift.c
- /*
- Functions for detecting SIFT image features.
- For more information, refer to:
- Lowe, D. Distinctive image features from scale-invariant keypoints.
- <EM>International Journal of Computer Vision, 60</EM>, 2 (2004),
- pp.91--110.
- Copyright (C) 2006-2010 Rob Hess <hess@eecs.oregonstate.edu>
- Note: The SIFT algorithm is patented in the United States and cannot be
- used in commercial products without a license from the University of
- British Columbia. For more information, refer to the file LICENSE.ubc
- that accompanied this distribution.
- @version 1.1.2-20100521
- */
- #include "sift.h"
- #include "imgfeatures.h"
- #include "utils.h"
- #include <cxcore.h>
- #include <cv.h>
- /************************* Local Function Prototypes *************************/
- static IplImage* create_init_img(IplImage*, int, double);
- static IplImage* convert_to_gray32(IplImage*);
- static IplImage*** build_gauss_pyr(IplImage*, int, int, double);
- static IplImage* downsample(IplImage*);
- static IplImage*** build_dog_pyr(IplImage***, int, int);
- static CvSeq* scale_space_extrema(IplImage***, int, int, double, int, CvMemStorage*);
- static int is_extremum(IplImage***, int, int, int, int);
- static struct feature* interp_extremum(IplImage***, int, int, int, int, int, double);
- static void interp_step(IplImage***, int, int, int, int, double*, double*, double*);
- static CvMat* deriv_3D(IplImage***, int, int, int, int);
- static CvMat* hessian_3D(IplImage***, int, int, int, int);
- static double interp_contr(IplImage***, int, int, int, int, double, double, double);
- static struct feature* new_feature(void);
- static int is_too_edge_like(IplImage*, int, int, int);
- static void calc_feature_scales(CvSeq*, double, int);
- static void adjust_for_img_dbl(CvSeq*);
- static void calc_feature_oris(CvSeq*, IplImage***);
- static double* ori_hist(IplImage*, int, int, int, int, double);
- static int calc_grad_mag_ori(IplImage*, int, int, double*, double*);
- static void smooth_ori_hist(double*, int);
- static double dominant_ori(double*, int);
- static void add_good_ori_features(CvSeq*, double*, int, double, struct feature*);
- static struct feature* clone_feature(struct feature*);
- static void compute_descriptors(CvSeq*, IplImage***, int, int);
- static double*** descr_hist(IplImage*, int, int, double, double, int, int);
- static void interp_hist_entry(double***, double, double, double, double, int, int);
- static void hist_to_descr(double***, int, int, struct feature*);
- static void normalize_descr(struct feature*);
- static int feature_cmp(void*, void*, void*);
- static void release_descr_hist(double****, int);
- static void release_pyr(IplImage****, int, int);
- /*********************** Functions prototyped in sift.h **********************/
- /**
- Finds SIFT features in an image using default parameter values. All
- detected features are stored in the array pointed to by \a feat.
- @param img the image in which to detect features
- @param feat a pointer to an array in which to store detected features
- @return Returns the number of features stored in \a feat or -1 on failure
- @see _sift_features()
- */
- int sift_features(IplImage* img, struct feature** feat)
- {
- return _sift_features(img, feat, SIFT_INTVLS, SIFT_SIGMA, SIFT_CONTR_THR,
- SIFT_CURV_THR, SIFT_IMG_DBL, SIFT_DESCR_WIDTH,
- SIFT_DESCR_HIST_BINS);
- }
- /**
- Finds SIFT features in an image using user-specified parameter values. All
- detected features are stored in the array pointed to by \a feat.
- @param img the image in which to detect features
- @param fea a pointer to an array in which to store detected features
- @param intvls the number of intervals sampled per octave of scale space
- @param sigma the amount of Gaussian smoothing applied to each image level
- before building the scale space representation for an octave
- @param cont_thr a threshold on the value of the scale space function
- \f$\left|D(\hat{x})\right|\f$, where \f$\hat{x}\f$ is a vector specifying
- feature location and scale, used to reject unstable features; assumes
- pixel values in the range [0, 1]
- @param curv_thr threshold on a feature's ratio of principle curvatures
- used to reject features that are too edge-like
- @param img_dbl should be 1 if image doubling prior to scale space
- construction is desired or 0 if not
- @param descr_width the width, \f$n\f$, of the \f$n \times n\f$ array of
- orientation histograms used to compute a feature's descriptor
- @param descr_hist_bins the number of orientations in each of the
- histograms in the array used to compute a feature's descriptor
- @return Returns the number of keypoints stored in \a feat or -1 on failure
- @see sift_keypoints()
- */
- int _sift_features(IplImage* img, struct feature** feat, int intvls,
- double sigma, double contr_thr, int curv_thr,
- int img_dbl, int descr_width, int descr_hist_bins)
- {
- IplImage* init_img;
- IplImage*** gauss_pyr, *** dog_pyr;
- CvMemStorage* storage;
- CvSeq* features;
- int octvs, i, n = ;
- /* check arguments */
- if (!img)
- fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
- if (!feat)
- fatal_error("NULL pointer error, %s, line %d", __FILE__, __LINE__);
- /* build scale space pyramid; smallest dimension of top level is ~4 pixels */
- init_img = create_init_img(img, img_dbl, sigma);
- octvs = log(MIN(init_img->width, init_img->height)) / log() - ;
- gauss_pyr = build_gauss_pyr(init_img, octvs, intvls, sigma);
- dog_pyr = build_dog_pyr(gauss_pyr, octvs, intvls);
- storage = cvCreateMemStorage();
- features = scale_space_extrema(dog_pyr, octvs, intvls, contr_thr,
- curv_thr, storage);
- calc_feature_scales(features, sigma, intvls);
- if (img_dbl)
- adjust_for_img_dbl(features);
- calc_feature_oris(features, gauss_pyr);
- compute_descriptors(features, gauss_pyr, descr_width, descr_hist_bins);
- /* sort features by decreasing scale and move from CvSeq to array */
- cvSeqSort(features, (CvCmpFunc)feature_cmp, NULL);
- n = features->total;
- *feat = calloc(n, sizeof(struct feature));
- *feat = cvCvtSeqToArray(features, *feat, CV_WHOLE_SEQ);
- for (i = ; i < n; i++)
- {
- free((*feat)[i].feature_data);
- (*feat)[i].feature_data = NULL;
- }
- cvReleaseMemStorage(&storage);
- cvReleaseImage(&init_img);
- release_pyr(&gauss_pyr, octvs, intvls + );
- release_pyr(&dog_pyr, octvs, intvls + );
- return n;
- }
- /************************ Functions prototyped here **************************/
- /*
- Converts an image to 8-bit grayscale and Gaussian-smooths it. The image is
- optionally doubled in size prior to smoothing.
- @param img input image
- @param img_dbl if true, image is doubled in size prior to smoothing
- @param sigma total std of Gaussian smoothing
- */
- static IplImage* create_init_img(IplImage* img, int img_dbl, double sigma)
- {
- IplImage* gray, *dbl;
- float sig_diff;
- gray = convert_to_gray32(img);
- if (img_dbl)
- {
- sig_diff = sqrt(sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA * );
- dbl = cvCreateImage(cvSize(img->width * , img->height * ),
- IPL_DEPTH_32F, );
- cvResize(gray, dbl, CV_INTER_CUBIC);
- cvSmooth(dbl, dbl, CV_GAUSSIAN, , , sig_diff, sig_diff);
- cvReleaseImage(&gray);
- return dbl;
- }
- else
- {
- sig_diff = sqrt(sigma * sigma - SIFT_INIT_SIGMA * SIFT_INIT_SIGMA);
- cvSmooth(gray, gray, CV_GAUSSIAN, , , sig_diff, sig_diff);
- return gray;
- }
- }
- /*
- Converts an image to 32-bit grayscale
- @param img a 3-channel 8-bit color (BGR) or 8-bit gray image
- @return Returns a 32-bit grayscale image
- */
- static IplImage* convert_to_gray32(IplImage* img)
- {
- IplImage* gray8, *gray32;
- gray32 = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, );
- if (img->nChannels == )
- gray8 = cvClone(img);
- else
- {
- gray8 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, );
- cvCvtColor(img, gray8, CV_BGR2GRAY);
- }
- cvConvertScale(gray8, gray32, 1.0 / 255.0, );
- cvReleaseImage(&gray8);
- return gray32;
- }
- /*
- Builds Gaussian scale space pyramid from an image
- @param base base image of the pyramid
- @param octvs number of octaves of scale space
- @param intvls number of intervals per octave
- @param sigma amount of Gaussian smoothing per octave
- @return Returns a Gaussian scale space pyramid as an octvs x (intvls + 3) array
- */
- static IplImage*** build_gauss_pyr(IplImage* base, int octvs,
- int intvls, double sigma)
- {
- IplImage*** gauss_pyr;
- double* sig = calloc(intvls + , sizeof(double));
- double sig_total, sig_prev, k;
- int i, o;
- gauss_pyr = calloc(octvs, sizeof(IplImage**));
- for (i = ; i < octvs; i++)
- gauss_pyr[i] = calloc(intvls + , sizeof(IplImage*));
- /*
- precompute Gaussian sigmas using the following formula:
- \sigma_{total}^2 = \sigma_{i}^2 + \sigma_{i-1}^2
- */
- sig[] = sigma;
- k = pow(2.0, 1.0 / intvls);
- for (i = ; i < intvls + ; i++)
- {
- sig_prev = pow(k, i - ) * sigma;
- sig_total = sig_prev * k;
- sig[i] = sqrt(sig_total * sig_total - sig_prev * sig_prev);
- }
- for (o = ; o < octvs; o++)
- for (i = ; i < intvls + ; i++)
- {
- if (o == && i == )
- gauss_pyr[o][i] = cvCloneImage(base);
- /* base of new octvave is halved image from end of previous octave */
- else if (i == )
- gauss_pyr[o][i] = downsample(gauss_pyr[o - ][intvls]);
- /* blur the current octave's last image to create the next one */
- else
- {
- gauss_pyr[o][i] = cvCreateImage(cvGetSize(gauss_pyr[o][i - ]),
- IPL_DEPTH_32F, );
- cvSmooth(gauss_pyr[o][i - ], gauss_pyr[o][i],
- CV_GAUSSIAN, , , sig[i], sig[i]);
- }
- }
- free(sig);
- return gauss_pyr;
- }
- /*
- Downsamples an image to a quarter of its size (half in each dimension)
- using nearest-neighbor interpolation
- @param img an image
- @return Returns an image whose dimensions are half those of img
- */
- static IplImage* downsample(IplImage* img)
- {
- IplImage* smaller = cvCreateImage(cvSize(img->width / , img->height / ),
- img->depth, img->nChannels);
- cvResize(img, smaller, CV_INTER_NN);
- return smaller;
- }
- /*
- Builds a difference of Gaussians scale space pyramid by subtracting adjacent
- intervals of a Gaussian pyramid
- @param gauss_pyr Gaussian scale-space pyramid
- @param octvs number of octaves of scale space
- @param intvls number of intervals per octave
- @return Returns a difference of Gaussians scale space pyramid as an
- octvs x (intvls + 2) array
- */
- static IplImage*** build_dog_pyr(IplImage*** gauss_pyr, int octvs, int intvls)
- {
- IplImage*** dog_pyr;
- int i, o;
- dog_pyr = calloc(octvs, sizeof(IplImage**));
- for (i = ; i < octvs; i++)
- dog_pyr[i] = calloc(intvls + , sizeof(IplImage*));
- for (o = ; o < octvs; o++)
- for (i = ; i < intvls + ; i++)
- {
- dog_pyr[o][i] = cvCreateImage(cvGetSize(gauss_pyr[o][i]),
- IPL_DEPTH_32F, );
- cvSub(gauss_pyr[o][i + ], gauss_pyr[o][i], dog_pyr[o][i], NULL);
- }
- return dog_pyr;
- }
- /*
- Detects features at extrema in DoG scale space. Bad features are discarded
- based on contrast and ratio of principal curvatures.
- @param dog_pyr DoG scale space pyramid
- @param octvs octaves of scale space represented by dog_pyr
- @param intvls intervals per octave
- @param contr_thr low threshold on feature contrast
- @param curv_thr high threshold on feature ratio of principal curvatures
- @param storage memory storage in which to store detected features
- @return Returns an array of detected features whose scales, orientations,
- and descriptors are yet to be determined.
- */
- static CvSeq* scale_space_extrema(IplImage*** dog_pyr, int octvs, int intvls,
- double contr_thr, int curv_thr,
- CvMemStorage* storage)
- {
- CvSeq* features;
- double prelim_contr_thr = 0.5 * contr_thr / intvls;
- struct feature* feat;
- struct detection_data* ddata;
- int o, i, r, c;
- features = cvCreateSeq(, sizeof(CvSeq), sizeof(struct feature), storage);
- for (o = ; o < octvs; o++)
- for (i = ; i <= intvls; i++)
- for (r = SIFT_IMG_BORDER; r < dog_pyr[o][]->height - SIFT_IMG_BORDER; r++)
- for (c = SIFT_IMG_BORDER; c < dog_pyr[o][]->width - SIFT_IMG_BORDER; c++)
- /* perform preliminary check on contrast */
- if (ABS(pixval32f(dog_pyr[o][i], r, c)) > prelim_contr_thr)
- if (is_extremum(dog_pyr, o, i, r, c))
- {
- feat = interp_extremum(dog_pyr, o, i, r, c, intvls, contr_thr);
- if (feat)
- {
- ddata = feat_detection_data(feat);
- if (!is_too_edge_like(dog_pyr[ddata->octv][ddata->intvl],
- ddata->r, ddata->c, curv_thr))
- {
- cvSeqPush(features, feat);
- }
- else
- free(ddata);
- free(feat);
- }
- }
- return features;
- }
- /*
- Determines whether a pixel is a scale-space extremum by comparing it to it's
- 3x3x3 pixel neighborhood.
- @param dog_pyr DoG scale space pyramid
- @param octv pixel's scale space octave
- @param intvl pixel's within-octave interval
- @param r pixel's image row
- @param c pixel's image col
- @return Returns 1 if the specified pixel is an extremum (max or min) among
- it's 3x3x3 pixel neighborhood.
- */
- static int is_extremum(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
- {
- float val = pixval32f(dog_pyr[octv][intvl], r, c);
- int i, j, k;
- /* check for maximum */
- if (val > )
- {
- for (i = -; i <= ; i++)
- for (j = -; j <= ; j++)
- for (k = -; k <= ; k++)
- if (val < pixval32f(dog_pyr[octv][intvl + i], r + j, c + k))
- return ;
- }
- /* check for minimum */
- else
- {
- for (i = -; i <= ; i++)
- for (j = -; j <= ; j++)
- for (k = -; k <= ; k++)
- if (val > pixval32f(dog_pyr[octv][intvl + i], r + j, c + k))
- return ;
- }
- return ;
- }
- /*
- Interpolates a scale-space extremum's location and scale to subpixel
- accuracy to form an image feature. Rejects features with low contrast.
- Based on Section 4 of Lowe's paper.
- @param dog_pyr DoG scale space pyramid
- @param octv feature's octave of scale space
- @param intvl feature's within-octave interval
- @param r feature's image row
- @param c feature's image column
- @param intvls total intervals per octave
- @param contr_thr threshold on feature contrast
- @return Returns the feature resulting from interpolation of the given
- parameters or NULL if the given location could not be interpolated or
- if contrast at the interpolated loation was too low. If a feature is
- returned, its scale, orientation, and descriptor are yet to be determined.
- */
- static struct feature* interp_extremum(IplImage*** dog_pyr, int octv, int intvl,
- int r, int c, int intvls, double contr_thr)
- {
- struct feature* feat;
- struct detection_data* ddata;
- double xi, xr, xc, contr;
- int i = ;
- while (i < SIFT_MAX_INTERP_STEPS)
- {
- interp_step(dog_pyr, octv, intvl, r, c, &xi, &xr, &xc);
- if (ABS(xi) < 0.5 && ABS(xr) < 0.5 && ABS(xc) < 0.5)
- break;
- c += cvRound(xc);
- r += cvRound(xr);
- intvl += cvRound(xi);
- if (intvl < ||
- intvl > intvls ||
- c < SIFT_IMG_BORDER ||
- r < SIFT_IMG_BORDER ||
- c >= dog_pyr[octv][]->width - SIFT_IMG_BORDER ||
- r >= dog_pyr[octv][]->height - SIFT_IMG_BORDER)
- {
- return NULL;
- }
- i++;
- }
- /* ensure convergence of interpolation */
- if (i >= SIFT_MAX_INTERP_STEPS)
- return NULL;
- contr = interp_contr(dog_pyr, octv, intvl, r, c, xi, xr, xc);
- if (ABS(contr) < contr_thr / intvls)
- return NULL;
- feat = new_feature();
- ddata = feat_detection_data(feat);
- feat->img_pt.x = feat->x = (c + xc) * pow(2.0, octv);
- feat->img_pt.y = feat->y = (r + xr) * pow(2.0, octv);
- ddata->r = r;
- ddata->c = c;
- ddata->octv = octv;
- ddata->intvl = intvl;
- ddata->subintvl = xi;
- return feat;
- }
- /*
- Performs one step of extremum interpolation. Based on Eqn. (3) in Lowe's
- paper.
- @param dog_pyr difference of Gaussians scale space pyramid
- @param octv octave of scale space
- @param intvl interval being interpolated
- @param r row being interpolated
- @param c column being interpolated
- @param xi output as interpolated subpixel increment to interval
- @param xr output as interpolated subpixel increment to row
- @param xc output as interpolated subpixel increment to col
- */
- static void interp_step(IplImage*** dog_pyr, int octv, int intvl, int r, int c,
- double* xi, double* xr, double* xc)
- {
- CvMat* dD, *H, *H_inv, X;
- double x[] = { };
- dD = deriv_3D(dog_pyr, octv, intvl, r, c);
- H = hessian_3D(dog_pyr, octv, intvl, r, c);
- H_inv = cvCreateMat(, , CV_64FC1);
- cvInvert(H, H_inv, CV_SVD);
- cvInitMatHeader(&X, , , CV_64FC1, x, CV_AUTOSTEP);
- cvGEMM(H_inv, dD, -, NULL, , &X, );
- cvReleaseMat(&dD);
- cvReleaseMat(&H);
- cvReleaseMat(&H_inv);
- *xi = x[];
- *xr = x[];
- *xc = x[];
- }
- /*
- Computes the partial derivatives in x, y, and scale of a pixel in the DoG
- scale space pyramid.
- @param dog_pyr DoG scale space pyramid
- @param octv pixel's octave in dog_pyr
- @param intvl pixel's interval in octv
- @param r pixel's image row
- @param c pixel's image col
- @return Returns the vector of partial derivatives for pixel I
- { dI/dx, dI/dy, dI/ds }^T as a CvMat*
- */
- static CvMat* deriv_3D(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
- {
- CvMat* dI;
- double dx, dy, ds;
- dx = (pixval32f(dog_pyr[octv][intvl], r, c + ) -
- pixval32f(dog_pyr[octv][intvl], r, c - )) / 2.0;
- dy = (pixval32f(dog_pyr[octv][intvl], r + , c) -
- pixval32f(dog_pyr[octv][intvl], r - , c)) / 2.0;
- ds = (pixval32f(dog_pyr[octv][intvl + ], r, c) -
- pixval32f(dog_pyr[octv][intvl - ], r, c)) / 2.0;
- dI = cvCreateMat(, , CV_64FC1);
- cvmSet(dI, , , dx);
- cvmSet(dI, , , dy);
- cvmSet(dI, , , ds);
- return dI;
- }
- /*
- Computes the 3D Hessian matrix for a pixel in the DoG scale space pyramid.
- @param dog_pyr DoG scale space pyramid
- @param octv pixel's octave in dog_pyr
- @param intvl pixel's interval in octv
- @param r pixel's image row
- @param c pixel's image col
- @return Returns the Hessian matrix (below) for pixel I as a CvMat*
- / Ixx Ixy Ixs \ <BR>
- | Ixy Iyy Iys | <BR>
- \ Ixs Iys Iss /
- */
- static CvMat* hessian_3D(IplImage*** dog_pyr, int octv, int intvl, int r, int c)
- {
- CvMat* H;
- double v, dxx, dyy, dss, dxy, dxs, dys;
- v = pixval32f(dog_pyr[octv][intvl], r, c);
- dxx = (pixval32f(dog_pyr[octv][intvl], r, c + ) +
- pixval32f(dog_pyr[octv][intvl], r, c - ) - * v);
- dyy = (pixval32f(dog_pyr[octv][intvl], r + , c) +
- pixval32f(dog_pyr[octv][intvl], r - , c) - * v);
- dss = (pixval32f(dog_pyr[octv][intvl + ], r, c) +
- pixval32f(dog_pyr[octv][intvl - ], r, c) - * v);
- dxy = (pixval32f(dog_pyr[octv][intvl], r + , c + ) -
- pixval32f(dog_pyr[octv][intvl], r + , c - ) -
- pixval32f(dog_pyr[octv][intvl], r - , c + ) +
- pixval32f(dog_pyr[octv][intvl], r - , c - )) / 4.0;
- dxs = (pixval32f(dog_pyr[octv][intvl + ], r, c + ) -
- pixval32f(dog_pyr[octv][intvl + ], r, c - ) -
- pixval32f(dog_pyr[octv][intvl - ], r, c + ) +
- pixval32f(dog_pyr[octv][intvl - ], r, c - )) / 4.0;
- dys = (pixval32f(dog_pyr[octv][intvl + ], r + , c) -
- pixval32f(dog_pyr[octv][intvl + ], r - , c) -
- pixval32f(dog_pyr[octv][intvl - ], r + , c) +
- pixval32f(dog_pyr[octv][intvl - ], r - , c)) / 4.0;
- H = cvCreateMat(, , CV_64FC1);
- cvmSet(H, , , dxx);
- cvmSet(H, , , dxy);
- cvmSet(H, , , dxs);
- cvmSet(H, , , dxy);
- cvmSet(H, , , dyy);
- cvmSet(H, , , dys);
- cvmSet(H, , , dxs);
- cvmSet(H, , , dys);
- cvmSet(H, , , dss);
- return H;
- }
- /*
- Calculates interpolated pixel contrast. Based on Eqn. (3) in Lowe's paper.
- @param dog_pyr difference of Gaussians scale space pyramid
- @param octv octave of scale space
- @param intvl within-octave interval
- @param r pixel row
- @param c pixel column
- @param xi interpolated subpixel increment to interval
- @param xr interpolated subpixel increment to row
- @param xc interpolated subpixel increment to col
- @param Returns interpolated contrast.
- */
- static double interp_contr(IplImage*** dog_pyr, int octv, int intvl, int r,
- int c, double xi, double xr, double xc)
- {
- CvMat* dD, X, T;
- double t[], x[] = { xc, xr, xi };
- cvInitMatHeader(&X, , , CV_64FC1, x, CV_AUTOSTEP);
- cvInitMatHeader(&T, , , CV_64FC1, t, CV_AUTOSTEP);
- dD = deriv_3D(dog_pyr, octv, intvl, r, c);
- cvGEMM(dD, &X, , NULL, , &T, CV_GEMM_A_T);
- cvReleaseMat(&dD);
- return pixval32f(dog_pyr[octv][intvl], r, c) + t[] * 0.5;
- }
- /*
- Allocates and initializes a new feature
- @return Returns a pointer to the new feature
- */
- static struct feature* new_feature(void)
- {
- struct feature* feat;
- struct detection_data* ddata;
- feat = malloc(sizeof(struct feature));
- memset(feat, , sizeof(struct feature));
- ddata = malloc(sizeof(struct detection_data));
- memset(ddata, , sizeof(struct detection_data));
- feat->feature_data = ddata;
- feat->type = FEATURE_LOWE;
- return feat;
- }
- /*
- Determines whether a feature is too edge like to be stable by computing the
- ratio of principal curvatures at that feature. Based on Section 4.1 of
- Lowe's paper.
- @param dog_img image from the DoG pyramid in which feature was detected
- @param r feature row
- @param c feature col
- @param curv_thr high threshold on ratio of principal curvatures
- @return Returns 0 if the feature at (r,c) in dog_img is sufficiently
- corner-like or 1 otherwise.
- */
- static int is_too_edge_like(IplImage* dog_img, int r, int c, int curv_thr)
- {
- double d, dxx, dyy, dxy, tr, det;
- /* principal curvatures are computed using the trace and det of Hessian */
- d = pixval32f(dog_img, r, c);
- dxx = pixval32f(dog_img, r, c + ) + pixval32f(dog_img, r, c - ) - * d;
- dyy = pixval32f(dog_img, r + , c) + pixval32f(dog_img, r - , c) - * d;
- dxy = (pixval32f(dog_img, r + , c + ) - pixval32f(dog_img, r + , c - ) -
- pixval32f(dog_img, r - , c + ) + pixval32f(dog_img, r - , c - )) / 4.0;
- tr = dxx + dyy;
- det = dxx * dyy - dxy * dxy;
- /* negative determinant -> curvatures have different signs; reject feature */
- if (det <= )
- return ;
- if (tr * tr / det < (curv_thr + 1.0)*(curv_thr + 1.0) / curv_thr)
- return ;
- return ;
- }
- /*
- Calculates characteristic scale for each feature in an array.
- @param features array of features
- @param sigma amount of Gaussian smoothing per octave of scale space
- @param intvls intervals per octave of scale space
- */
- static void calc_feature_scales(CvSeq* features, double sigma, int intvls)
- {
- struct feature* feat;
- struct detection_data* ddata;
- double intvl;
- int i, n;
- n = features->total;
- for (i = ; i < n; i++)
- {
- feat = CV_GET_SEQ_ELEM(struct feature, features, i);
- ddata = feat_detection_data(feat);
- intvl = ddata->intvl + ddata->subintvl;
- feat->scl = sigma * pow(2.0, ddata->octv + intvl / intvls);
- ddata->scl_octv = sigma * pow(2.0, intvl / intvls);
- }
- }
- /*
- Halves feature coordinates and scale in case the input image was doubled
- prior to scale space construction.
- @param features array of features
- */
- static void adjust_for_img_dbl(CvSeq* features)
- {
- struct feature* feat;
- int i, n;
- n = features->total;
- for (i = ; i < n; i++)
- {
- feat = CV_GET_SEQ_ELEM(struct feature, features, i);
- feat->x /= 2.0;
- feat->y /= 2.0;
- feat->scl /= 2.0;
- feat->img_pt.x /= 2.0;
- feat->img_pt.y /= 2.0;
- }
- }
- /*
- Computes a canonical orientation for each image feature in an array. Based
- on Section 5 of Lowe's paper. This function adds features to the array when
- there is more than one dominant orientation at a given feature location.
- @param features an array of image features
- @param gauss_pyr Gaussian scale space pyramid
- */
- static void calc_feature_oris(CvSeq* features, IplImage*** gauss_pyr)
- {
- struct feature* feat;
- struct detection_data* ddata;
- double* hist;
- double omax;
- int i, j, n = features->total;
- for (i = ; i < n; i++)
- {
- feat = malloc(sizeof(struct feature));
- cvSeqPopFront(features, feat);
- ddata = feat_detection_data(feat);
- hist = ori_hist(gauss_pyr[ddata->octv][ddata->intvl],
- ddata->r, ddata->c, SIFT_ORI_HIST_BINS,
- cvRound(SIFT_ORI_RADIUS * ddata->scl_octv),
- SIFT_ORI_SIG_FCTR * ddata->scl_octv);
- for (j = ; j < SIFT_ORI_SMOOTH_PASSES; j++)
- smooth_ori_hist(hist, SIFT_ORI_HIST_BINS);
- omax = dominant_ori(hist, SIFT_ORI_HIST_BINS);
- add_good_ori_features(features, hist, SIFT_ORI_HIST_BINS,
- omax * SIFT_ORI_PEAK_RATIO, feat);
- free(ddata);
- free(feat);
- free(hist);
- }
- }
- /*
- Computes a gradient orientation histogram at a specified pixel.
- @param img image
- @param r pixel row
- @param c pixel col
- @param n number of histogram bins
- @param rad radius of region over which histogram is computed
- @param sigma std for Gaussian weighting of histogram entries
- @return Returns an n-element array containing an orientation histogram
- representing orientations between 0 and 2 PI.
- */
- static double* ori_hist(IplImage* img, int r, int c, int n, int rad, double sigma)
- {
- double* hist;
- double mag, ori, w, exp_denom, PI2 = CV_PI * 2.0;
- int bin, i, j;
- hist = calloc(n, sizeof(double));
- exp_denom = 2.0 * sigma * sigma;
- for (i = -rad; i <= rad; i++)
- for (j = -rad; j <= rad; j++)
- if (calc_grad_mag_ori(img, r + i, c + j, &mag, &ori))
- {
- w = exp(-(i*i + j*j) / exp_denom);
- bin = cvRound(n * (ori + CV_PI) / PI2);
- bin = (bin < n) ? bin : ;
- hist[bin] += w * mag;
- }
- return hist;
- }
- /*
- Calculates the gradient magnitude and orientation at a given pixel.
- @param img image
- @param r pixel row
- @param c pixel col
- @param mag output as gradient magnitude at pixel (r,c)
- @param ori output as gradient orientation at pixel (r,c)
- @return Returns 1 if the specified pixel is a valid one and sets mag and
- ori accordingly; otherwise returns 0
- */
- static int calc_grad_mag_ori(IplImage* img, int r, int c, double* mag, double* ori)
- {
- double dx, dy;
- if (r > && r < img->height - && c > && c < img->width - )
- {
- dx = pixval32f(img, r, c + ) - pixval32f(img, r, c - );
- dy = pixval32f(img, r - , c) - pixval32f(img, r + , c);
- *mag = sqrt(dx*dx + dy*dy);
- *ori = atan2(dy, dx);
- return ;
- }
- else
- return ;
- }
- /*
- Gaussian smooths an orientation histogram.
- @param hist an orientation histogram
- @param n number of bins
- */
- static void smooth_ori_hist(double* hist, int n)
- {
- double prev, tmp, h0 = hist[];
- int i;
- prev = hist[n - ];
- for (i = ; i < n; i++)
- {
- tmp = hist[i];
- hist[i] = 0.25 * prev + 0.5 * hist[i] +
- 0.25 * ((i + == n) ? h0 : hist[i + ]);
- prev = tmp;
- }
- }
- /*
- Finds the magnitude of the dominant orientation in a histogram
- @param hist an orientation histogram
- @param n number of bins
- @return Returns the value of the largest bin in hist
- */
- static double dominant_ori(double* hist, int n)
- {
- double omax;
- int maxbin, i;
- omax = hist[];
- maxbin = ;
- for (i = ; i < n; i++)
- if (hist[i] > omax)
- {
- omax = hist[i];
- maxbin = i;
- }
- return omax;
- }
- /*
- Interpolates a histogram peak from left, center, and right values
- */
- #define interp_hist_peak( l, c, r ) ( 0.5 * ((l)-(r)) / ((l) - 2.0*(c) + (r)) )
- /*
- Adds features to an array for every orientation in a histogram greater than
- a specified threshold.
- @param features new features are added to the end of this array
- @param hist orientation histogram
- @param n number of bins in hist
- @param mag_thr new features are added for entries in hist greater than this
- @param feat new features are clones of this with different orientations
- */
- static void add_good_ori_features(CvSeq* features, double* hist, int n,
- double mag_thr, struct feature* feat)
- {
- struct feature* new_feat;
- double bin, PI2 = CV_PI * 2.0;
- int l, r, i;
- for (i = ; i < n; i++)
- {
- l = (i == ) ? n - : i - ;
- r = (i + ) % n;
- if (hist[i] > hist[l] && hist[i] > hist[r] && hist[i] >= mag_thr)
- {
- bin = i + interp_hist_peak(hist[l], hist[i], hist[r]);
- bin = (bin < ) ? n + bin : (bin >= n) ? bin - n : bin;
- new_feat = clone_feature(feat);
- new_feat->ori = ((PI2 * bin) / n) - CV_PI;
- cvSeqPush(features, new_feat);
- free(new_feat);
- }
- }
- }
- /*
- Makes a deep copy of a feature
- @param feat feature to be cloned
- @return Returns a deep copy of feat
- */
- static struct feature* clone_feature(struct feature* feat)
- {
- struct feature* new_feat;
- struct detection_data* ddata;
- new_feat = new_feature();
- ddata = feat_detection_data(new_feat);
- memcpy(new_feat, feat, sizeof(struct feature));
- memcpy(ddata, feat_detection_data(feat), sizeof(struct detection_data));
- new_feat->feature_data = ddata;
- return new_feat;
- }
- /*
- Computes feature descriptors for features in an array. Based on Section 6
- of Lowe's paper.
- @param features array of features
- @param gauss_pyr Gaussian scale space pyramid
- @param d width of 2D array of orientation histograms
- @param n number of bins per orientation histogram
- */
- static void compute_descriptors(CvSeq* features, IplImage*** gauss_pyr, int d, int n)
- {
- struct feature* feat;
- struct detection_data* ddata;
- double*** hist;
- int i, k = features->total;
- for (i = ; i < k; i++)
- {
- feat = CV_GET_SEQ_ELEM(struct feature, features, i);
- ddata = feat_detection_data(feat);
- hist = descr_hist(gauss_pyr[ddata->octv][ddata->intvl], ddata->r,
- ddata->c, feat->ori, ddata->scl_octv, d, n);
- hist_to_descr(hist, d, n, feat);
- release_descr_hist(&hist, d);
- }
- }
- /*
- Computes the 2D array of orientation histograms that form the feature
- descriptor. Based on Section 6.1 of Lowe's paper.
- @param img image used in descriptor computation
- @param r row coord of center of orientation histogram array
- @param c column coord of center of orientation histogram array
- @param ori canonical orientation of feature whose descr is being computed
- @param scl scale relative to img of feature whose descr is being computed
- @param d width of 2d array of orientation histograms
- @param n bins per orientation histogram
- @return Returns a d x d array of n-bin orientation histograms.
- */
- static double*** descr_hist(IplImage* img, int r, int c, double ori,
- double scl, int d, int n)
- {
- double*** hist;
- double cos_t, sin_t, hist_width, exp_denom, r_rot, c_rot, grad_mag,
- grad_ori, w, rbin, cbin, obin, bins_per_rad, PI2 = 2.0 * CV_PI;
- int radius, i, j;
- hist = calloc(d, sizeof(double**));
- for (i = ; i < d; i++)
- {
- hist[i] = calloc(d, sizeof(double*));
- for (j = ; j < d; j++)
- hist[i][j] = calloc(n, sizeof(double));
- }
- cos_t = cos(ori);
- sin_t = sin(ori);
- bins_per_rad = n / PI2;
- exp_denom = d * d * 0.5;
- hist_width = SIFT_DESCR_SCL_FCTR * scl;
- radius = hist_width * sqrt() * (d + 1.0) * 0.5 + 0.5;
- for (i = -radius; i <= radius; i++)
- for (j = -radius; j <= radius; j++)
- {
- /*
- Calculate sample's histogram array coords rotated relative to ori.
- Subtract 0.5 so samples that fall e.g. in the center of row 1 (i.e.
- r_rot = 1.5) have full weight placed in row 1 after interpolation.
- */
- c_rot = (j * cos_t - i * sin_t) / hist_width;
- r_rot = (j * sin_t + i * cos_t) / hist_width;
- rbin = r_rot + d / - 0.5;
- cbin = c_rot + d / - 0.5;
- if (rbin > -1.0 && rbin < d && cbin > -1.0 && cbin < d)
- if (calc_grad_mag_ori(img, r + i, c + j, &grad_mag, &grad_ori))
- {
- grad_ori -= ori;
- while (grad_ori < 0.0)
- grad_ori += PI2;
- while (grad_ori >= PI2)
- grad_ori -= PI2;
- obin = grad_ori * bins_per_rad;
- w = exp(-(c_rot * c_rot + r_rot * r_rot) / exp_denom);
- interp_hist_entry(hist, rbin, cbin, obin, grad_mag * w, d, n);
- }
- }
- return hist;
- }
- /*
- Interpolates an entry into the array of orientation histograms that form
- the feature descriptor.
- @param hist 2D array of orientation histograms
- @param rbin sub-bin row coordinate of entry
- @param cbin sub-bin column coordinate of entry
- @param obin sub-bin orientation coordinate of entry
- @param mag size of entry
- @param d width of 2D array of orientation histograms
- @param n number of bins per orientation histogram
- */
- static void interp_hist_entry(double*** hist, double rbin, double cbin,
- double obin, double mag, int d, int n)
- {
- double d_r, d_c, d_o, v_r, v_c, v_o;
- double** row, *h;
- int r0, c0, o0, rb, cb, ob, r, c, o;
- r0 = cvFloor(rbin);
- c0 = cvFloor(cbin);
- o0 = cvFloor(obin);
- d_r = rbin - r0;
- d_c = cbin - c0;
- d_o = obin - o0;
- /*
- The entry is distributed into up to 8 bins. Each entry into a bin
- is multiplied by a weight of 1 - d for each dimension, where d is the
- distance from the center value of the bin measured in bin units.
- */
- for (r = ; r <= ; r++)
- {
- rb = r0 + r;
- if (rb >= && rb < d)
- {
- v_r = mag * ((r == ) ? 1.0 - d_r : d_r);
- row = hist[rb];
- for (c = ; c <= ; c++)
- {
- cb = c0 + c;
- if (cb >= && cb < d)
- {
- v_c = v_r * ((c == ) ? 1.0 - d_c : d_c);
- h = row[cb];
- for (o = ; o <= ; o++)
- {
- ob = (o0 + o) % n;
- v_o = v_c * ((o == ) ? 1.0 - d_o : d_o);
- h[ob] += v_o;
- }
- }
- }
- }
- }
- }
- /*
- Converts the 2D array of orientation histograms into a feature's descriptor
- vector.
- @param hist 2D array of orientation histograms
- @param d width of hist
- @param n bins per histogram
- @param feat feature into which to store descriptor
- */
- static void hist_to_descr(double*** hist, int d, int n, struct feature* feat)
- {
- int int_val, i, r, c, o, k = ;
- for (r = ; r < d; r++)
- for (c = ; c < d; c++)
- for (o = ; o < n; o++)
- feat->descr[k++] = hist[r][c][o];
- feat->d = k;
- normalize_descr(feat);
- for (i = ; i < k; i++)
- if (feat->descr[i] > SIFT_DESCR_MAG_THR)
- feat->descr[i] = SIFT_DESCR_MAG_THR;
- normalize_descr(feat);
- /* convert floating-point descriptor to integer valued descriptor */
- for (i = ; i < k; i++)
- {
- int_val = SIFT_INT_DESCR_FCTR * feat->descr[i];
- feat->descr[i] = MIN(, int_val);
- }
- }
- /*
- Normalizes a feature's descriptor vector to unitl length
- @param feat feature
- */
- static void normalize_descr(struct feature* feat)
- {
- double cur, len_inv, len_sq = 0.0;
- int i, d = feat->d;
- for (i = ; i < d; i++)
- {
- cur = feat->descr[i];
- len_sq += cur*cur;
- }
- len_inv = 1.0 / sqrt(len_sq);
- for (i = ; i < d; i++)
- feat->descr[i] *= len_inv;
- }
- /*
- Compares features for a decreasing-scale ordering. Intended for use with
- CvSeqSort
- @param feat1 first feature
- @param feat2 second feature
- @param param unused
- @return Returns 1 if feat1's scale is greater than feat2's, -1 if vice versa,
- and 0 if their scales are equal
- */
- static int feature_cmp(void* feat1, void* feat2, void* param)
- {
- struct feature* f1 = (struct feature*) feat1;
- struct feature* f2 = (struct feature*) feat2;
- if (f1->scl < f2->scl)
- return ;
- if (f1->scl > f2->scl)
- return -;
- return ;
- }
- /*
- De-allocates memory held by a descriptor histogram
- @param hist pointer to a 2D array of orientation histograms
- @param d width of hist
- */
- static void release_descr_hist(double**** hist, int d)
- {
- int i, j;
- for (i = ; i < d; i++)
- {
- for (j = ; j < d; j++)
- free((*hist)[i][j]);
- free((*hist)[i]);
- }
- free(*hist);
- *hist = NULL;
- }
- /*
- De-allocates memory held by a scale space pyramid
- @param pyr scale space pyramid
- @param octvs number of octaves of scale space
- @param n number of images per octave
- */
- static void release_pyr(IplImage**** pyr, int octvs, int n)
- {
- int i, j;
- for (i = ; i < octvs; i++)
- {
- for (j = ; j < n; j++)
- cvReleaseImage(&(*pyr)[i][j]);
- free((*pyr)[i]);
- }
- free(*pyr);
- *pyr = NULL;
- }
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特征提取(代码部分)的更多相关文章
- 在vs环境中跑动sift特征提取(原理部分)
/* 如果给两张图片,中间有相似点.要求做匹配.怎么做.我现在能讲么? 比如给了两幅图片,先求出sift点. 尺度空间极值检测.高斯模糊 关键点定位 关键点方向确定 关键点描述 kdtre ...
- 开发环境中biztalk项目设置注意事项(转)
适用版本:biztalk 2006 适用环境:开发测试环境 在开发过程中,在开发环境中,一定会是一个对项目不断的修改.编译.部署.测试,查看测试结果,发现有问题,然后回到开发环境再修改.编译.部署 ...
- 计算机视觉-sift(2)代码理解
之前结合不同人的资料理解了sift的原理,这里通过opencv中的代码来加深对sift的实现的理解. 使得能够从原理性理解到源码级的理解.不过该博文还是大量基于<赵春江, opencv2.4.9 ...
- 如何在交互式环境中执行Python程序
相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行.命令行窗口运行.开发工具上运行等,其中在不同的操作平台上还互不相同.今天,小编讲些Pyth ...
- 转:【Java并发编程】之八:多线程环境中安全使用集合API(含代码)
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200509 在集合API中,最初设计的Vector和Hashtable是多线程安 ...
- macOS 下 PHPStorm + Xdebug 调试 Docker 环境中的代码
0x00 描述 宿主机是 mac mini,构建的项目在 docker 中,所以需要在 PHPStorm 上配置 Xdebug 进行远程代码调试. 0x01 环境 宿主机:macOS High Sie ...
- 多线程环境中安全使用集合API(含代码)
转自: http://blog.csdn.net/ns_code/article/details/17200509 在集合API中,最初设计的Vector和Hashtable是多线程安全的.例如:对于 ...
- 痞子衡嵌入式:在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是在IAR开发环境下将整个源文件代码重定向到任意RAM中的方法. 痞子衡旧文 <在IAR下将关键函数重定向到RAM中执行的方法> ...
- SIFT特征提取分析
SIFT特征提取分析 sift 关键点,关键点检测 读'D. G. Lowe. Distinctive Image Features from Scale-Invariant Keypoints[J] ...
随机推荐
- 总结的Ubuntu的若干小知识
一.默认开机直接进入到Ubuntu命令行界面 安装Ubuntu后,开机会默认进入到图形界面,如果不喜欢图形界面,可以通过修改配置,直接进入命令行界面,还行节省100多兆的内存空间.具体方法如下: 修改 ...
- work_6
这次的作业是阅读C++11的新特性并提出问题,作为一个大部分代码都是用C++的基本语法并没有特别关注C++一代又一代新特性的学生来说,首先我阅读了一些关于新特性的文章.为了更快的理解,我首先选择了阅读 ...
- MSGPACK(一)
MSGPACK跨平台的数据序列规范,为多种语言所支持.用它序列还是还原数据都异常方便. 而且它支持序列的数据格式非常之多,因为它支持的数据格式多,所以MSGPACK的第二功用:缓存. DELPHI的M ...
- WebForm 回传后如何保持页面的滚动位置
转载自 http://www.cnblogs.com/renjuwht/archive/2009/06/17/1505000.html 默认情况下,ASP.NET页面回传到服务器后,页面会跳回顶部.对 ...
- HDU 3265 Posters (线段树+扫描线)(面积并)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3265 给你n个中间被挖空了一个矩形的中空矩形,让你求他们的面积并. 其实一个中空矩形可以分成4个小的矩 ...
- dll开发中遇到的问题
刚碰到个问题,我的一个项目中引用了一个dll,这个dll又引用了另一个dll,我把这俩个都放在bin文件夹下,但是会报错,说第二个dll找不到.把它放到系统文件夹system32下就没事了. 但是遇到 ...
- C#中的强制类型转换与as转换的区别
C#中的强制类型转换 例如有ClassA与ClassB两个类创建两个类的对象进行转换 1 2 ClassA a = new ClassA(); ClassB b = new ClassB(); 如果 ...
- setbuf和freopen
看memcached代码的时候学习了一个api,setbuf,可以设置文件流的缓冲区. #include <stdio.h> void setbuf(FILE *stream ...
- 在Java中super和this的区别
摘要:在Java中我们会时常用到super及this的用法,现在我主要来区分一下super.和this.及superL()及this()之间的区别,来对它们的认识和了解: 1.this的用法在Java ...
- 一,彻底理解第一个C语言程序 Hello World
对于初学者来说,第一个程序一般都是hello world,而且是照着书上一点一点敲的.所以,在初学者眼中,敲出来的第一个程序代码不过是一堆看不懂的英语.而事实上,C语言作为一门语言,是有语法的.所以这 ...