sift是图像匹配的非常经典的算法

sift是图像匹配的非常经典的算法,但是很复杂,要想自己拿C或C++实现很麻烦,如果只是使用的话,有国外某高人维护的sift库,前期只要自己能够调用即可,关键是要熟悉大致的流程,对sift库有个了解,具体的工作只要调用其中的函数即可。匹配效果:


sift是图像匹配的非常经典的算法,但是很复杂,要想自己拿C或C++实现很麻烦,如果只是使用的话,有国外某高人维护的sift库,前期只要自己能够调用即可,关键是要熟悉大致的流程,对sift库有个了解,具体的工作只要调用其中的函数即可。

一、sift简介

1、sift算法应用典型场合:

  物体识别

  机器人定位与导航

  图像拼接

  三维建模

  手势识别

  视频跟踪

  笔记鉴定

  指纹与人脸识别

  犯罪现场特征提取

2、sift算法解决的问题

  目标的旋转、缩放、平移(RST)

  图像仿射/投影变换(视点viewpoint)

  光照影响(illumination)

  目标遮挡(occlusion)

  杂物场景(clutter)

  噪声

二、sift基本概念

1、SIFT匹配的定义

  SIFT匹配(Scale-invariant feature transform,尺度不变特征转换)是一种电脑视觉的算法用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量,此算法由 David Lowe 在1999年所发表,2004年完善总结。其应用范围包含物体辨识、机器人地图感知与导航、影像缝合、3D模型建立、手势辨识、影像追踪和动作比对。

  局部影像特征的描述与侦测可以帮助辨识物体,SIFT 特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高。基于这些特性,它们是高度显著而且相对容易撷取,在母数庞大的特征数据库中,很容易辨识物体而且鲜有误认。使用 SIFT特征描述对于部分物体遮蔽的侦测率也相当高,甚至只需要3个以上的SIFT物体特征就足以计算出位置与方位。在现今的电脑硬件速度下和小型的特征数据库条件下,辨识速度可接近即时运算。SIFT特征的信息量大,适合在海量数据库中快速准确匹配。

2、SIFT特征的主要特点

  从理论上说,SIFT是一种相似不变量,即对图像尺度变化和旋转是不变量。然而,由于构造SIFT特征时,在很多细节上进行了特殊处理,使得SIFT对图像的复杂变形和光照变化具有了较强的适应性,同时运算速度比较快,定位精度比较高。如:

  在多尺度空间采用DOG算子检测关键点,相比传统的基于LOG算子的检测方法,运算速度大大加快;

  关键点的精确定位不仅提高了精度,而且大大提高了关键点的稳定性;

  在构造描述子时,以子区域的统计特性,而不是以单个像素作为研究对象,提高了对图像局部变形的适应能力;

  对于16*16的关键点邻域和4*4的子区域,在处理梯度幅度时都进行了类似于高斯函数的加权处理,强化了中心区域,淡化了边缘区域的影响,从而提高了算法对几何变形的适应性;

  该方法不仅对通用的线性光照模型具有不变性,而且对复杂的光照变化亦具有一定的适应性。关于这部分内容的细节,可参看文献“Distinctive Image Features from Scale-Invariant Keypoints”

  SIFT算法的特点:

         a.SIFT特征是图像的局部特征,其对旋转、尺度缩放、亮度变化保持不变性,对视角变化、仿射变换、噪声也保持一定程     度的稳定性;

         b.独特性(Distinctiveness)好,信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配;

         c.多量性,即使少数的几    个物体也可以产生大量的SIFT特征向量;

         d.高速性,经优化的SIFT匹配算法甚至可以达到实时的要求;

         e.可扩展性,可以很方便的与其他形式   的特征向量进行联合。

三、sift算法的应用

1、sift的main函数

  1. #include "sift.h"  
  2. #include "imgfeatures.h"  
  3. #include "kdtree.h"  
  4. #include "utils.h"  
  5. #include "xform.h"  
  6.   
  7. #include <cv.h>  
  8. #include <cxcore.h>  
  9. #include <highgui.h>  
  10.   
  11. #include <stdio.h>  
  12.   
  13.   
  14. /* the maximum number of keypoint NN candidates to check during BBF search */  
  15. #define KDTREE_BBF_MAX_NN_CHKS 200  
  16.   
  17. /* threshold on squared ratio of distances between NN and 2nd NN */  
  18. #define NN_SQ_DIST_RATIO_THR 0.49  
  19.   
  20. /******************************** Globals ************************************/  
  21.   
  22. char img1_file[] = "beaver.png";  
  23. char img2_file[] = "beaver_xform.png";  
  24.   
  25. /********************************** Main *************************************/  
  26.   
  27.   
  28. int main( int argc, char** argv )  
  29. {  
  30.     IplImage* img1, * img2, * stacked;  
  31.     struct feature* feat1, * feat2, * feat;  
  32.     struct feature** nbrs;  
  33.     struct kd_node* kd_root;  
  34.     CvPoint pt1, pt2;  
  35.     double d0, d1;  
  36.     int n1, n2, k, i, m = 0;  
  37.   
  38.     img1 = cvLoadImage( img1_file, 1 );  
  39.     if( ! img1 )  
  40.         fatal_error( "unable to load image from %s", img1_file );  
  41.     img2 = cvLoadImage( img2_file, 1 );  
  42.     if( ! img2 )  
  43.         fatal_error( "unable to load image from %s", img2_file );  
  44.     stacked = stack_imgs( img1, img2 );  
  45.   
  46.     fprintf( stderr, "Finding features in %s...\n", img1_file );  
  47.     n1 = sift_features( img1, &feat1 );  
  48.     fprintf( stderr, "Finding features in %s...\n", img2_file );  
  49.     n2 = sift_features( img2, &feat2 );  
  50.   
  51.   
  52.     kd_root = kdtree_build( feat2, n2 );  
  53.     for( i = 0; i < n1; i++ )  
  54.     {  
  55.         feat = feat1 + i;  
  56.         k = kdtree_bbf_knn( kd_root, feat, 2, &nbrs, KDTREE_BBF_MAX_NN_CHKS );  
  57.         if( k == 2 )  
  58.         {  
  59.             d0 = descr_dist_sq( feat, nbrs[0] );  
  60.             d1 = descr_dist_sq( feat, nbrs[1] );  
  61.             if( d0 < d1 * NN_SQ_DIST_RATIO_THR )  
  62.             {  
  63.                 pt1 = cvPoint( cvRound( feat->x ), cvRound( feat->y ) );  
  64.                 pt2 = cvPoint( cvRound( nbrs[0]->x ), cvRound( nbrs[0]->y ) );  
  65.                 pt2.y += img1->height;  
  66.                 cvLine( stacked, pt1, pt2, CV_RGB(255,0,255), 1, 8, 0 );  
  67.                 m++;  
  68.                 feat1[i].fwd_match = nbrs[0];  
  69.             }  
  70.         }  
  71.         free( nbrs );  
  72.     }  
  73.   
  74.     fprintf( stderr, "Found %d total matches\n", m );  
  75.     cvNamedWindow( "Matches", 1 );  
  76.     cvShowImage( "Matches", stacked );  
  77.     cvSaveImage("1.bmp",stacked,0);  
  78.     cvWaitKey( 0 );  
  79.   
  80.     cvReleaseImage( &stacked );  
  81.     cvReleaseImage( &img1 );  
  82.     cvReleaseImage( &img2 );  
  83.     kdtree_release( kd_root );  
  84.     free( feat1 );  
  85.     free( feat2 );  
  86.     return 0;  
  87. }  


Sift(Scale InvariantFeature Transform)是一个很好的图像匹配算法,同时能处理亮度、平移、旋转、尺度的变化,利用特征点来提取特征描述符,最后在特征描述符之间寻找匹配。

sift库分析:

总共包含6 个文件再加上一个main.c文件。

untils.c

minpq.c

imgfeature.c

sift.c

xform.c

kdtree.c

以及其对应的.h文件

最核心的文件是sift.c 和 kdtree.c

1 sift.c 寻找图片中的特征点

主要步骤:

a、构建尺度空间,检测极值点,获得尺度不变性;

b、特征点过滤并进行精确定位,剔除不稳定的特征点;

c、在特征点处提取特征描述符,为特征点分配方向值;

d、生成特征描述子,利用特征描述符寻找匹配点;

以特征点为中心取16*16的邻域作为采样窗口,

将采样点与特征点的相对方向通过高斯加权后归入包含8个bin的方向直方图,

最后获得4*4*8的128维特征描述子。

2 kdtree.c 对两幅图像进行匹配

    主要步骤:

    当两幅图像的Sift特征向量生成以后,下一步就可以采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。

取图1的某个关键点,通过遍历找到图像2中的距离最近的两个关键点。在这两个关键点中,如果次近距离除以最近距离小于某个阙值,则判定为一对匹配点。

3 imgfeature.c在以上图片中画上标记。连接对应的匹配的点。

 

四、具体文件分析

1、utils.h

         utils是sift算法的一个比较基础的头文件,主要是对图像的基本操纵:

         获取某位置的像素点

         设置某位置的像素点(8位,32位和64位),

         计算两点之间的距离的平方

         在图片某一点画一个“X”

         将两张图片合成为一个,高是二者之和,宽是二者的较大者。img1 在左上角,img2在右下角。

函数的解释如下:

static int pixval8 (IplImage *img, int r,int c)

         从灰度图像中获取某点像素

static void setpix8 (IplImage *img, int r,int c, uchar val)

         设置灰度图像中某点的像素

 

static float pixval32f (IplImage *img, intr, int c)  

static void setpix32f (IplImage *img, intr, int c, float val)     

static double pixval64f (IplImage *img, intr, int c)

static void setpix64f (IplImage *img, intr, int c, double val)

         在32位和64位图像中获取和设置某点的像素值

 

void fatal_error (char *format,...)

         错误处理,用VS2010+opencv2.3报错,直接把内部实现注释掉即可,无影响。

 

char * replace_extension (const char *file,const char *extn)

        获取一个文件全名,将文件名和扩展名连接到一起如 traffic + jpg => traffic.jpg

char * prepend_path (const char *path,const char *file)

        获取一个文件的全路径,将路径名添加到文件名之前 C:\\ + traffic.jpg => c:\\traffic.jpg

char * basename (const char *pathname)

        文件名中去掉路径c:\\traffic.jpg => traffic.jpg

void  progress (int done)

        显示程序进展,用|/-\表示

int   array_double(void **array, int n, int size)

        数组长度加倍

double     dist_sq_2D(CvPoint2D64f p1, CvPoint2D64f p2)

        计算两点的对角线距离

void          draw_x(IplImage *img, CvPoint pt, int r, int w, CvScalar color)

        在点pt画个叉,本质就是在那个点画四条线

IplImage * stack_imgs (IplImage *img1,IplImage *img2)

        两张图片生成一张图片,高是二者之和,宽是二者的较大者       

int   win_closed(char *name)

        查看某个窗口是否已经关闭

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.   
  22. /***************************** Inline Functions ******************************/  
  23.   
  24.   
  25. /** 
  26. A function to get a pixel value from an 8-bit unsigned image. 
  27.  
  28. @param img an image 
  29. @param r row 
  30. @param c column 
  31. @return Returns the value of the pixel at (\a r, \a c) in \a img 
  32. */  
  33. static __inline int pixval8( IplImage* img, int r, int c )  
  34. {  
  35.     return (int)( ( (uchar*)(img->imageData + img->widthStep*r) )[c] );  
  36. }  
  37.   
  38.   
  39. /** 
  40. A function to set a pixel value in an 8-bit unsigned image. 
  41.  
  42. @param img an image 
  43. @param r row 
  44. @param c column 
  45. @param val pixel value 
  46. */  
  47. static __inline void setpix8( IplImage* img, int r, int c, uchar val)  
  48. {  
  49.     ( (uchar*)(img->imageData + img->widthStep*r) )[c] = val;  
  50. }  
  51.   
  52.   
  53. /** 
  54. A function to get a pixel value from a 32-bit floating-point image. 
  55.  
  56. @param img an image 
  57. @param r row 
  58. @param c column 
  59. @return Returns the value of the pixel at (\a r, \a c) in \a img 
  60. */  
  61. static __inline float pixval32f( IplImage* img, int r, int c )  
  62. {  
  63.     return ( (float*)(img->imageData + img->widthStep*r) )[c];  
  64. }  
  65.   
  66.   
  67. /** 
  68. A function to set a pixel value in a 32-bit floating-point image. 
  69.  
  70. @param img an image 
  71. @param r row 
  72. @param c column 
  73. @param val pixel value 
  74. */  
  75. static __inline void setpix32f( IplImage* img, int r, int c, float val )  
  76. {  
  77.     ( (float*)(img->imageData + img->widthStep*r) )[c] = val;  
  78. }  
  79.   
  80.   
  81. /** 
  82. A function to get a pixel value from a 64-bit floating-point image. 
  83.  
  84. @param img an image 
  85. @param r row 
  86. @param c column 
  87. @return Returns the value of the pixel at (\a r, \a c) in \a img 
  88. */  
  89. static __inline double pixval64f( IplImage* img, int r, int c )  
  90. {  
  91.     return (double)( ( (double*)(img->imageData + img->widthStep*r) )[c] );  
  92. }  
  93.   
  94.   
  95. /** 
  96. A function to set a pixel value in a 64-bit floating-point image. 
  97.  
  98. @param img an image 
  99. @param r row 
  100. @param c column 
  101. @param val pixel value 
  102. */  
  103. static __inline void setpix64f( IplImage* img, int r, int c, double val )  
  104. {  
  105.     ( (double*)(img->imageData + img->widthStep*r) )[c] = val;  
  106. }  
  107.   
  108.   
  109. /**************************** Function Prototypes ****************************/  
  110.   
  111.   
  112. /** 
  113. Prints an error message and aborts the program.  The error message is 
  114. of the form "Error: ...", where the ... is specified by the \a format 
  115. argument 
  116.  
  117. @param format an error message format string (as with \c printf(3)). 
  118. */  
  119. extern void fatal_error( char* format, ... );  
  120.   
  121.   
  122. /** 
  123. Replaces a file's extension, which is assumed to be everything after the 
  124. last dot ('.') character. 
  125.  
  126. @param file the name of a file 
  127.  
  128. @param extn a new extension for \a file; should not include a dot (i.e. 
  129.     \c "jpg", not \c ".jpg") unless the new file extension should contain 
  130.     two dots. 
  131.  
  132. @return Returns a new string formed as described above.  If \a file does 
  133.     not have an extension, this function simply adds one. 
  134. */  
  135. extern char* replace_extension( const char* file, const char* extn );  
  136.   
  137.   
  138. /** 
  139. A function that removes the path from a filename.  Similar to the Unix 
  140. basename command. 
  141.  
  142. @param pathname a (full) path name 
  143.  
  144. @return Returns the basename of \a pathname. 
  145. */  
  146. extern char* basename( const char* pathname );  
  147.   
  148.   
  149. /** 
  150. Displays progress in the console with a spinning pinwheel.  Every time this 
  151. function is called, the state of the pinwheel is incremented.  The pinwheel 
  152. has four states that loop indefinitely: '|', '/', '-', '\'. 
  153.  
  154. @param done if 0, this function simply increments the state of the pinwheel; 
  155.     otherwise it prints "done" 
  156. */  
  157. extern void progress( int done );  
  158.   
  159.   
  160. /** 
  161. Erases a specified number of characters from a stream. 
  162.  
  163. @param stream the stream from which to erase characters 
  164. @param n the number of characters to erase 
  165. */  
  166. extern void erase_from_stream( FILE* stream, int n );  
  167.   
  168.   
  169. /** 
  170. Doubles the size of an array with error checking 
  171.  
  172. @param array pointer to an array whose size is to be doubled 
  173. @param n number of elements allocated for \a array 
  174. @param size size in bytes of elements in \a array 
  175.  
  176. @return Returns the new number of elements allocated for \a array.  If no 
  177.     memory is available, returns 0 and frees array. 
  178. */  
  179. extern int array_double( void** array, int n, int size );  
  180.   
  181.   
  182. /** 
  183. Calculates the squared distance between two points. 
  184.  
  185. @param p1 a point 
  186. @param p2 another point 
  187. */  
  188. extern double dist_sq_2D( CvPoint2D64f p1, CvPoint2D64f p2 );  
  189.   
  190.   
  191. /** 
  192. Draws an x on an image. 
  193.  
  194. @param img an image 
  195. @param pt the center point of the x 
  196. @param r the x's radius 
  197. @param w the x's line weight 
  198. @param color the color of the x 
  199. */  
  200. extern void draw_x( IplImage* img, CvPoint pt, int r, int w, CvScalar color );  
  201.   
  202.   
  203. /** 
  204. Combines two images by scacking one on top of the other 
  205.  
  206. @param img1 top image 
  207. @param img2 bottom image 
  208.  
  209. @return Returns the image resulting from stacking \a img1 on top if \a img2 
  210. */  
  211. extern IplImage* stack_imgs( IplImage* img1, IplImage* img2 );  
  212.   
  213.   
  214. /** 
  215. Allows user to view an array of images as a video.  Keyboard controls 
  216. are as follows: 
  217.  
  218. <ul> 
  219. <li>Space - start and pause playback</li> 
  220. <li>Page Up - skip forward 10 frames</li> 
  221. <li>Page Down - jump back 10 frames</li> 
  222. <li>Right Arrow - skip forward 1 frame</li> 
  223. <li>Left Arrow - jump back 1 frame</li> 
  224. <li>Backspace - jump back to beginning</li> 
  225. <li>Esc - exit playback</li> 
  226. <li>Closing the window also exits playback</li> 
  227. </ul> 
  228.  
  229. @param imgs an array of images 
  230. @param n number of images in \a imgs 
  231. @param win_name name of window in which images are displayed 
  232. */  
  233. extern void vid_view( IplImage** imgs, int n, char* win_name );  
  234.   
  235.   
  236. /** 
  237. Checks if a HighGUI window is still open or not 
  238.  
  239. @param name the name of the window we're checking 
  240.  
  241. @return Returns 1 if the window named \a name has been closed or 0 otherwise 
  242. */  
  243. extern int win_closed( char* name );  
  244.   
  245. #endif  


 ###utils.c

  1. #include "utils.h"  
  2.   
  3. #include <cv.h>  
  4. #include <cxcore.h>  
  5. #include <highgui.h>  
  6.   
  7. #include <errno.h>  
  8. #include <string.h>  
  9. #include <stdlib.h>  
  10.   
  11.   
  12.   
  13. void fatal_error(char* format, ...)  
  14. {  
  15.       
  16. }  
  17.   
  18.   
  19.   
  20.   
  21. char* replace_extension( const char* file, const char* extn )  
  22. {  
  23.     char* new_file, * lastdot;  
  24.   
  25.     new_file = calloc( strlen( file ) + strlen( extn ) + 2,  sizeofchar ) );  
  26.     strcpy( new_file, file );  
  27.     lastdot = strrchr( new_file, '.' );  
  28.     if( lastdot )  
  29.         *(lastdot + 1) = '\0';  
  30.     else  
  31.         strcat( new_file, "." );  
  32.     strcat( new_file, extn );  
  33.   
  34.     return new_file;  
  35. }  
  36.   
  37.   
  38.   
  39.   
  40. char* basename( const char* pathname )  
  41. {  
  42.     char* base, * last_slash;  
  43.   
  44.     last_slash = strrchr( pathname, '/' );  
  45.     if( ! last_slash )  
  46.     {  
  47.         base = calloc( strlen( pathname ) + 1, sizeofchar ) );  
  48.         strcpy( base, pathname );  
  49.     }  
  50.     else  
  51.     {  
  52.         base = calloc( strlen( last_slash++ ), sizeofchar ) );  
  53.         strcpy( base, last_slash );  
  54.     }  
  55.   
  56.     return base;  
  57. }  
  58.   
  59.   
  60.   
  61.   
  62. void progress( int done )  
  63. {  
  64.     char state[4] = { '|''/''-''\\' };  
  65.     static int cur = -1;  
  66.   
  67.     if( cur == -1 )  
  68.         fprintf( stderr, "  " );  
  69.   
  70.     if( done )  
  71.     {  
  72.         fprintf( stderr, "\b\bdone\n");  
  73.         cur = -1;  
  74.     }  
  75.     else  
  76.     {  
  77.         cur = ( cur + 1 ) % 4;  
  78.         fprintf( stdout, "\b\b%c ", state[cur] );  
  79.         fflush(stderr);  
  80.     }  
  81. }  
  82.   
  83.   
  84.   
  85.   
  86. void erase_from_stream( FILE* stream, int n )  
  87. {  
  88.     int j;  
  89.     for( j = 0; j < n; j++ )  
  90.         fprintf( stream, "\b" );  
  91.     for( j = 0; j < n; j++ )  
  92.         fprintf( stream, " " );  
  93.     for( j = 0; j < n; j++ )  
  94.         fprintf( stream, "\b" );  
  95. }  
  96.   
  97.   
  98.   
  99.   
  100. int array_double( void** array, int n, int size )  
  101. {  
  102.     void* tmp;  
  103.   
  104.     tmp = realloc( *array, 2 * n * size );  
  105.     if( ! tmp )  
  106.     {  
  107.         fprintf( stderr, "Warning: unable to allocate memory in array_double(),"  
  108.                 " %s line %d\n", __FILE__, __LINE__ );  
  109.         if( *array )  
  110.             free( *array );  
  111.         *array = NULL;  
  112.         return 0;  
  113.     }  
  114.     *array = tmp;  
  115.     return n*2;  
  116. }  
  117.   
  118.   
  119.   
  120.   
  121. double dist_sq_2D( CvPoint2D64f p1, CvPoint2D64f p2 )  
  122. {  
  123.     double x_diff = p1.x - p2.x;  
  124.     double y_diff = p1.y - p2.y;  
  125.   
  126.     return x_diff * x_diff + y_diff * y_diff;  
  127. }  
  128.   
  129.   
  130.   
  131.   
  132. void draw_x( IplImage* img, CvPoint pt, int r, int w, CvScalar color )  
  133. {  
  134.     cvLine( img, pt, cvPoint( pt.x + r, pt.y + r), color, w, 8, 0 );  
  135.     cvLine( img, pt, cvPoint( pt.x - r, pt.y + r), color, w, 8, 0 );  
  136.     cvLine( img, pt, cvPoint( pt.x + r, pt.y - r), color, w, 8, 0 );  
  137.     cvLine( img, pt, cvPoint( pt.x - r, pt.y - r), color, w, 8, 0 );  
  138. }  
  139.   
  140.   
  141.   
  142.   
  143. extern IplImage* stack_imgs( IplImage* img1, IplImage* img2 )  
  144. {  
  145.     IplImage* stacked = cvCreateImage( cvSize( MAX(img1->width, img2->width),  
  146.                                         img1->height + img2->height ),  
  147.                                         IPL_DEPTH_8U, 3 );  
  148.   
  149.     cvZero( stacked );  
  150.     cvSetImageROI( stacked, cvRect( 0, 0, img1->width, img1->height ) );  
  151.     cvAdd( img1, stacked, stacked, NULL );  
  152.     cvSetImageROI( stacked, cvRect(0, img1->height, img2->width, img2->height) );  
  153.     cvAdd( img2, stacked, stacked, NULL );  
  154.     cvResetImageROI( stacked );  
  155.   
  156.     return stacked;  
  157. }  
  158.   
  159.   
  160.   
  161.   
  162. void vid_view( IplImage** imgs, int n, char* win_name )  
  163. {  
  164.     int k, i = 0, playing = 0;  
  165.   
  166.     cvNamedWindow( win_name, 1 );  
  167.     cvShowImage( win_name, imgs[i] );  
  168.     while( ! win_closed( win_name ) )  
  169.     {  
  170.         /* if already playing, advance frame and check for pause */  
  171.         if( playing )  
  172.         {  
  173.             i = MIN( i + 1, n - 1 );  
  174.             cvNamedWindow( win_name, 1 );  
  175.             cvShowImage( win_name, imgs[i] );  
  176.             k = cvWaitKey( 33 );  
  177.             if( k == ' '  ||  i == n - 1 )  
  178.                 playing = 0;  
  179.         }  
  180.   
  181.         else  
  182.   
  183.         {  
  184.             k = cvWaitKey( 0 );  
  185.             switch( k )  
  186.             {  
  187.                 /* space */  
  188.             case ' ':  
  189.                 playing = 1;  
  190.                 break;  
  191.   
  192.                 /* esc */  
  193.             case 27:  
  194.             case 1048603:  
  195.                 cvDestroyWindow( win_name );  
  196.                 break;  
  197.   
  198.                 /* backspace */  
  199.             case '\b':  
  200.                 i = 0;  
  201.                 cvNamedWindow( win_name, 1 );  
  202.                 cvShowImage( win_name, imgs[i] );  
  203.                 break;  
  204.   
  205.                 /* left arrow */  
  206.             case 65288:  
  207.             case 1113937:  
  208.                 i = MAX( i - 1, 0 );  
  209.                 cvNamedWindow( win_name, 1 );  
  210.                 cvShowImage( win_name, imgs[i] );  
  211.                 break;  
  212.   
  213.                 /* right arrow */  
  214.             case 65363:  
  215.             case 1113939:  
  216.                 i = MIN( i + 1, n - 1 );  
  217.                 cvNamedWindow( win_name, 1 );  
  218.                 cvShowImage( win_name, imgs[i] );  
  219.                 break;  
  220.   
  221.                 /* page up */  
  222.             case 65365:  
  223.             case 1113941:  
  224.                 i = MAX( i - 10, 0 );  
  225.                 cvNamedWindow( win_name, 1 );  
  226.                 cvShowImage( win_name, imgs[i] );  
  227.                 break;  
  228.   
  229.                 /* page down */  
  230.             case 65366:  
  231.             case 1113942:  
  232.                 i = MIN( i + 10, n - 1 );  
  233.                 cvNamedWindow( win_name, 1 );  
  234.                 cvShowImage( win_name, imgs[i] );  
  235.                 break;  
  236.             }  
  237.         }  
  238.     }  
  239. }  
  240.   
  241.   
  242.   
  243. /* 
  244. Checks if a HighGUI window is still open or not 
  245.  
  246. @param name the name of the window we're checking 
  247.  
  248. @return Returns 1 if the window named \a name has been closed or 0 otherwise 
  249. */  
  250. int win_closed( char* win_name )  
  251. {  
  252.     if( ! cvGetWindowHandle(win_name) )  
  253.         return 1;  
  254.     return 0;  
  255. }  

2、imfeature.h

int import_features (char *filename, inttype, struct feature **feat)

         从一个文件中(txt)读入几个数据,作为特征的初始化参数

         type指的是特征的类型FEATURE_OXFD或者FEATURE_LOWE

int export_features (char *filename, structfeature *feat, int n)

         将几个参数存到一个文件中去,参数指的是feature 这个结构,feature**指的是这个结构的数组的指针      ,传递指针可以避免数据的复制

void draw_features (IplImage *img, structfeature *feat, int n)

        将特征绘制到一个图片上

double     descr_dist_sq(struct feature *f1, struct feature *f2)

        计算两个特征描绘子之间的欧式距离

 

feature数据结构分析:

struct feature

{

        

double x;                      /**< x coord */

double y;                      /**< y coord */

double a;                      /**< Oxford-typeaffine region parameter */

double b;                      /**< Oxford-typeaffine region parameter */

double c;                      /**< Oxford-type affineregion parameter */

double scl;                    /**< scale of aLowe-style feature */

double ori;                    /**< orientation of aLowe-style feature */

int d;                         /**< descriptorlength */

double descr[FEATURE_MAX_D];   /**< descriptor */

int type;                      /**< feature type,OXFD or LOWE */

int category;                  /**< all-purpose featurecategory */

struct feature* fwd_match;     /**< matching feature from forwardimage */

struct feature* bck_match;     /**< matching feature from backmwardimage */

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 */

};

imfeature.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.   
  30. /* colors in which to display different feature types */  
  31. #define FEATURE_OXFD_COLOR CV_RGB(255,255,0)  
  32. #define FEATURE_LOWE_COLOR CV_RGB(255,0,255)  
  33.   
  34. /** max feature descriptor length */  
  35. #define FEATURE_MAX_D 128  
  36.   
  37.   
  38. /** 
  39. Structure to represent an affine invariant image feature.  The fields 
  40. x, y, a, b, c represent the affine region around the feature: 
  41.  
  42. a(x-u)(x-u) + 2b(x-u)(y-v) + c(y-v)(y-v) = 1 
  43. */  
  44. struct feature  
  45. {  
  46.     double x;                      /**< x coord */  
  47.     double y;                      /**< y coord */  
  48.     double a;                      /**< Oxford-type affine region parameter */  
  49.     double b;                      /**< Oxford-type affine region parameter */  
  50.     double c;                      /**< Oxford-type affine region parameter */  
  51.     double scl;                    /**< scale of a Lowe-style feature */  
  52.     double ori;                    /**< orientation of a Lowe-style feature */  
  53.     int d;                         /**< descriptor length */  
  54.     double descr[FEATURE_MAX_D];   /**< descriptor */  
  55.     int type;                      /**< feature type, OXFD or LOWE */  
  56.     int category;                  /**< all-purpose feature category */  
  57.     struct feature* fwd_match;     /**< matching feature from forward image */  
  58.     struct feature* bck_match;     /**< matching feature from backmward image */  
  59.     struct feature* mdl_match;     /**< matching feature from model */  
  60.     CvPoint2D64f img_pt;           /**< location in image */  
  61.     CvPoint2D64f mdl_pt;           /**< location in model */  
  62.     void* feature_data;            /**< user-definable data */  
  63. };  
  64.   
  65.   
  66. /** 
  67. Reads image features from file.  The file should be formatted as from 
  68. the code provided by the Visual Geometry Group at Oxford or from the 
  69. code provided by David Lowe. 
  70.  
  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. /** 
  89. Exports a feature set to a file formatted depending on the type of 
  90. features, as specified in the feature struct's type field. 
  91.  
  92. @param filename name of file to which to export features 
  93. @param feat feature array 
  94. @param n number of features  
  95.  
  96. @return Returns 0 on success or 1 on error 
  97. */  
  98. extern int export_features( char* filename, struct feature* feat, int n );  
  99.   
  100.   
  101. /** 
  102. Displays a set of features on an image 
  103.  
  104. @param img image on which to display features 
  105. @param feat array of Oxford-type features 
  106. @param n number of features 
  107. */  
  108. extern void draw_features( IplImage* img, struct feature* feat, int n );  
  109.   
  110.   
  111. /** 
  112. Calculates the squared Euclidian distance between two feature descriptors. 
  113.  
  114. @param f1 first feature 
  115. @param f2 second feature 
  116.  
  117. @return Returns the squared Euclidian distance between the descriptors of 
  118. \a f1 and \a f2. 
  119. */  
  120. extern double descr_dist_sq( struct feature* f1, struct feature* f2 );  
  121.   
  122.   
  123. #endif  
imfeature.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. /* 
  28. Reads image features from file.  The file should be formatted as from 
  29. the code provided by the Visual Geometry Group at Oxford: 
  30.  
  31.  
  32. @param filename location of a file containing image features 
  33. @param type determines how features are input.  If \a type is FEATURE_OXFD, 
  34.     the input file is treated as if it is from the code provided by the VGG 
  35.     at Oxford: 
  36.  
  37.     http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  38.  
  39.     If \a type is FEATURE_LOWE, the input file is treated as if it is from 
  40.     David Lowe's SIFT code: 
  41.  
  42.     http://www.cs.ubc.ca/~lowe/keypoints   
  43. @param features pointer to an array in which to store features 
  44.  
  45. @return Returns the number of features imported from filename or -1 on error 
  46. */  
  47. int import_features( char* filename, int type, struct feature** feat )  
  48. {  
  49.     int n;  
  50.   
  51.     switch( type )  
  52.     {  
  53.     case FEATURE_OXFD:  
  54.         n = import_oxfd_features( filename, feat );  
  55.         break;  
  56.     case FEATURE_LOWE:  
  57.         n = import_lowe_features( filename, feat );  
  58.         break;  
  59.     default:  
  60.         fprintf( stderr, "Warning: import_features(): unrecognized feature" \  
  61.                 "type, %s, line %d\n", __FILE__, __LINE__ );  
  62.         return -1;  
  63.     }  
  64.   
  65.     if( n == -1 )  
  66.         fprintf( stderr, "Warning: unable to import features from %s,"  \  
  67.             " %s, line %d\n", filename, __FILE__, __LINE__ );  
  68.     return n;  
  69. }  
  70.   
  71.   
  72.   
  73. /* 
  74. Exports a feature set to a file formatted depending on the type of 
  75. features, as specified in the feature struct's type field. 
  76.  
  77. @param filename name of file to which to export features 
  78. @param feat feature array 
  79. @param n number of features  
  80.  
  81. @return Returns 0 on success or 1 on error 
  82. */  
  83. int export_features( char* filename, struct feature* feat, int n )  
  84. {  
  85.     int r, type;  
  86.   
  87.     if( n <= 0  ||  ! feat )  
  88.     {  
  89.         fprintf( stderr, "Warning: no features to export, %s line %d\n",  
  90.                 __FILE__, __LINE__ );  
  91.         return 1;  
  92.     }  
  93.     type = feat[0].type;  
  94.     switch( type )  
  95.     {  
  96.     case FEATURE_OXFD:  
  97.         r = export_oxfd_features( filename, feat, n );  
  98.         break;  
  99.     case FEATURE_LOWE:  
  100.         r = export_lowe_features( filename, feat, n );  
  101.         break;  
  102.     default:  
  103.         fprintf( stderr, "Warning: export_features(): unrecognized feature" \  
  104.                 "type, %s, line %d\n", __FILE__, __LINE__ );  
  105.         return -1;  
  106.     }  
  107.   
  108.     if( r )  
  109.         fprintf( stderr, "Warning: unable to export features to %s,"    \  
  110.                 " %s, line %d\n", filename, __FILE__, __LINE__ );  
  111.     return r;  
  112. }  
  113.   
  114.   
  115. /* 
  116. Draws a set of features on an image 
  117.  
  118. @param img image on which to draw features 
  119. @param feat array of Oxford-type features 
  120. @param n number of features 
  121. */  
  122. void draw_features( IplImage* img, struct feature* feat, int n )  
  123. {  
  124.     int type;  
  125.   
  126.     if( n <= 0  ||  ! feat )  
  127.     {  
  128.         fprintf( stderr, "Warning: no features to draw, %s line %d\n",  
  129.                 __FILE__, __LINE__ );  
  130.         return;  
  131.     }  
  132.     type = feat[0].type;  
  133.     switch( type )  
  134.     {  
  135.     case FEATURE_OXFD:  
  136.         draw_oxfd_features( img, feat, n );  
  137.         break;  
  138.     case FEATURE_LOWE:  
  139.         draw_lowe_features( img, feat, n );  
  140.         break;  
  141.     default:  
  142.         fprintf( stderr, "Warning: draw_features(): unrecognized feature" \  
  143.             " type, %s, line %d\n", __FILE__, __LINE__ );  
  144.         break;  
  145.     }     
  146. }  
  147.   
  148.   
  149.   
  150. /* 
  151. Calculates the squared Euclidian distance between two feature descriptors. 
  152.  
  153. @param f1 first feature  
  154. @param f2 second feature 
  155.  
  156. @return Returns the squared Euclidian distance between the descriptors of 
  157. f1 and f2. 
  158. */  
  159. double descr_dist_sq( struct feature* f1, struct feature* f2 )  
  160. {  
  161.     double diff, dsq = 0;  
  162.     double* descr1, * descr2;  
  163.     int i, d;  
  164.   
  165.     d = f1->d;  
  166.     if( f2->d != d )  
  167.         return DBL_MAX;  
  168.     descr1 = f1->descr;  
  169.     descr2 = f2->descr;  
  170.   
  171.     for( i = 0; i < d; i++ )  
  172.     {  
  173.         diff = descr1[i] - descr2[i];  
  174.         dsq += diff*diff;  
  175.     }  
  176.     return dsq;  
  177. }  
  178.   
  179.   
  180.   
  181. /***************************** Local Functions *******************************/  
  182.   
  183.   
  184. /* 
  185. Reads image features from file.  The file should be formatted as from 
  186. the code provided by the Visual Geometry Group at Oxford: 
  187.  
  188. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  189.  
  190. @param filename location of a file containing image features 
  191. @param features pointer to an array in which to store features 
  192.  
  193. @return Returns the number of features imported from filename or -1 on error 
  194. */  
  195. static int import_oxfd_features( char* filename, struct feature** features )  
  196. {  
  197.     struct feature* f;  
  198.     int i, j, n, d;  
  199.     double x, y, a, b, c, dv;  
  200.     FILE* file;  
  201.   
  202.     if( ! features )  
  203.         fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );  
  204.   
  205.     if( ! ( file = fopen( filename, "r" ) ) )  
  206.     {  
  207.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  208.                 filename, __FILE__, __LINE__ );  
  209.         return -1;  
  210.     }  
  211.   
  212.     /* read dimension and number of features */  
  213.     if( fscanf( file, " %d %d ", &d, &n ) != 2 )  
  214.     {  
  215.         fprintf( stderr, "Warning: file read error, %s, line %d\n",  
  216.                 __FILE__, __LINE__ );  
  217.         return -1;  
  218.     }  
  219.     if( d > FEATURE_MAX_D )  
  220.     {  
  221.         fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",  
  222.                 __FILE__, __LINE__ );  
  223.         return -1;  
  224.     }  
  225.   
  226.   
  227.     f = calloc( n, sizeof(struct feature) );  
  228.     for( i = 0; i < n; i++ )  
  229.     {  
  230.         /* read affine region parameters */  
  231.         if( fscanf( file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c ) != 5 )  
  232.         {  
  233.             fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",  
  234.                     i+1, __FILE__, __LINE__ );  
  235.             free( f );  
  236.             return -1;  
  237.         }  
  238.         f[i].img_pt.x = f[i].x = x;  
  239.         f[i].img_pt.y = f[i].y = y;  
  240.         f[i].a = a;  
  241.         f[i].b = b;  
  242.         f[i].c = c;  
  243.         f[i].d = d;  
  244.         f[i].type = FEATURE_OXFD;  
  245.   
  246.         /* read descriptor */  
  247.         for( j = 0; j < d; j++ )  
  248.         {  
  249.             if( ! fscanf( file, " %lf ", &dv ) )  
  250.             {  
  251.                 fprintf( stderr, "Warning: error reading feature descriptor" \  
  252.                         " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );  
  253.                 free( f );  
  254.                 return -1;  
  255.             }  
  256.             f[i].descr[j] = dv;  
  257.         }  
  258.   
  259.         f[i].scl = f[i].ori = 0;  
  260.         f[i].category = 0;  
  261.         f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;  
  262.         f[i].mdl_pt.x = f[i].mdl_pt.y = -1;  
  263.         f[i].feature_data = NULL;  
  264.     }  
  265.   
  266.     if( fclose(file) )  
  267.     {  
  268.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  269.                 __FILE__, __LINE__ );  
  270.         free( f );  
  271.         return -1;  
  272.     }  
  273.   
  274.     *features = f;  
  275.     return n;  
  276. }  
  277.   
  278.   
  279.   
  280.   
  281. /* 
  282. Exports a feature set to a file formatted as one from the code provided 
  283. by the Visual Geometry Group at Oxford: 
  284.  
  285. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html 
  286.  
  287. @param filename name of file to which to export features 
  288. @param feat feature array 
  289. @param n number of features 
  290.  
  291. @return Returns 0 on success or 1 on error 
  292. */  
  293. static int export_oxfd_features( char* filename, struct feature* feat, int n )  
  294. {  
  295.     FILE* file;  
  296.     int i, j, d;  
  297.   
  298.     if( n <= 0 )  
  299.     {  
  300.         fprintf( stderr, "Warning: feature count %d, %s, line %s\n",  
  301.                 n, __FILE__, __LINE__ );  
  302.         return 1;  
  303.     }  
  304.     if( ! ( file = fopen( filename, "w" ) ) )  
  305.     {  
  306.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  307.                 filename, __FILE__, __LINE__ );  
  308.         return 1;  
  309.     }  
  310.   
  311.     d = feat[0].d;  
  312.     fprintf( file, "%d\n%d\n", d, n );  
  313.     for( i = 0; i < n; i++ )  
  314.     {  
  315.         fprintf( file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,  
  316.                 feat[i].b, feat[i].c );  
  317.         for( j = 0; j < d; j++ )  
  318.             fprintf( file, " %f", feat[i].descr[j] );  
  319.         fprintf( file, "\n" );  
  320.     }  
  321.   
  322.     if( fclose(file) )  
  323.     {  
  324.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  325.                 __FILE__, __LINE__ );  
  326.         return 1;  
  327.     }  
  328.   
  329.     return 0;  
  330. }  
  331.   
  332.   
  333.   
  334. /* 
  335. Draws Oxford-type affine features 
  336.  
  337. @param img image on which to draw features 
  338. @param feat array of Oxford-type features 
  339. @param n number of features 
  340. */  
  341. static void draw_oxfd_features( IplImage* img, struct feature* feat, int n )  
  342. {  
  343.     CvScalar color = CV_RGB( 255, 255, 255 );  
  344.     int i;  
  345.   
  346.     if( img-> nChannels > 1 )  
  347.         color = FEATURE_OXFD_COLOR;  
  348.     for( i = 0; i < n; i++ )  
  349.         draw_oxfd_feature( img, feat + i, color );  
  350. }  
  351.   
  352.   
  353.   
  354. /* 
  355. Draws a single Oxford-type feature 
  356.  
  357. @param img image on which to draw 
  358. @param feat feature to be drawn 
  359. @param color color in which to draw 
  360. */  
  361. static void draw_oxfd_feature( IplImage* img, struct feature* feat, CvScalar color )  
  362. {  
  363.     double m[4] = { feat->a, feat->b, feat->b, feat->c };  
  364.     double v[4] = { 0 };  
  365.     double e[2] = { 0 };  
  366.     CvMat M, V, E;  
  367.     double alpha, l1, l2;  
  368.   
  369.     /* compute axes and orientation of ellipse surrounding affine region */  
  370.     cvInitMatHeader( &M, 2, 2, CV_64FC1, m, CV_AUTOSTEP );  
  371.     cvInitMatHeader( &V, 2, 2, CV_64FC1, v, CV_AUTOSTEP );  
  372.     cvInitMatHeader( &E, 2, 1, CV_64FC1, e, CV_AUTOSTEP );  
  373.     cvEigenVV( &M, &V, &E, DBL_EPSILON, 0, 0 );  
  374.     l1 = 1 / sqrt( e[1] );  
  375.     l2 = 1 / sqrt( e[0] );  
  376.     alpha = -atan2( v[1], v[0] );  
  377.     alpha *= 180 / CV_PI;  
  378.   
  379.     cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,  
  380.                 0, 360, CV_RGB(0,0,0), 3, 8, 0 );  
  381.     cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,  
  382.                 0, 360, color, 1, 8, 0 );  
  383.     cvLine( img, cvPoint( feat->x+2, feat->y ), cvPoint( feat->x-2, feat->y ),  
  384.             color, 1, 8, 0 );  
  385.     cvLine( img, cvPoint( feat->x, feat->y+2 ), cvPoint( feat->x, feat->y-2 ),  
  386.             color, 1, 8, 0 );  
  387. }  
  388.   
  389.   
  390.   
  391. /* 
  392. Reads image features from file.  The file should be formatted as from 
  393. the code provided by David Lowe: 
  394.  
  395. http://www.cs.ubc.ca/~lowe/keypoints/ 
  396.  
  397. @param filename location of a file containing image features 
  398. @param features pointer to an array in which to store features 
  399.  
  400. @return Returns the number of features imported from filename or -1 on error 
  401. */  
  402. static int import_lowe_features( char* filename, struct feature** features )  
  403. {  
  404.     struct feature* f;  
  405.     int i, j, n, d;  
  406.     double x, y, s, o, dv;  
  407.     FILE* file;  
  408.   
  409.     if( ! features )  
  410.         fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );  
  411.   
  412.     if( ! ( file = fopen( filename, "r" ) ) )  
  413.     {  
  414.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  415.             filename, __FILE__, __LINE__ );  
  416.         return -1;  
  417.     }  
  418.   
  419.     /* read number of features and dimension */  
  420.     if( fscanf( file, " %d %d ", &n, &d ) != 2 )  
  421.     {  
  422.         fprintf( stderr, "Warning: file read error, %s, line %d\n",  
  423.                 __FILE__, __LINE__ );  
  424.         return -1;  
  425.     }  
  426.     if( d > FEATURE_MAX_D )  
  427.     {  
  428.         fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",  
  429.                 __FILE__, __LINE__ );  
  430.         return -1;  
  431.     }  
  432.   
  433.     f = calloc( n, sizeof(struct feature) );  
  434.     for( i = 0; i < n; i++ )  
  435.     {  
  436.         /* read affine region parameters */  
  437.         if( fscanf( file, " %lf %lf %lf %lf ", &y, &x, &s, &o ) != 4 )  
  438.         {  
  439.             fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",  
  440.                     i+1, __FILE__, __LINE__ );  
  441.             free( f );  
  442.             return -1;  
  443.         }  
  444.         f[i].img_pt.x = f[i].x = x;  
  445.         f[i].img_pt.y = f[i].y = y;  
  446.         f[i].scl = s;  
  447.         f[i].ori = o;  
  448.         f[i].d = d;  
  449.         f[i].type = FEATURE_LOWE;  
  450.   
  451.         /* read descriptor */  
  452.         for( j = 0; j < d; j++ )  
  453.         {  
  454.             if( ! fscanf( file, " %lf ", &dv ) )  
  455.             {  
  456.                 fprintf( stderr, "Warning: error reading feature descriptor" \  
  457.                         " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );  
  458.                 free( f );  
  459.                 return -1;  
  460.             }  
  461.             f[i].descr[j] = dv;  
  462.         }  
  463.   
  464.         f[i].a = f[i].b = f[i].c = 0;  
  465.         f[i].category = 0;  
  466.         f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;  
  467.         f[i].mdl_pt.x = f[i].mdl_pt.y = -1;  
  468.     }  
  469.   
  470.     if( fclose(file) )  
  471.     {  
  472.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  473.                 __FILE__, __LINE__ );  
  474.         free( f );  
  475.         return -1;  
  476.     }  
  477.   
  478.     *features = f;  
  479.     return n;  
  480. }  
  481.   
  482.   
  483.   
  484. /* 
  485. Exports a feature set to a file formatted as one from the code provided 
  486. by David Lowe: 
  487.  
  488. http://www.cs.ubc.ca/~lowe/keypoints/ 
  489.  
  490. @param filename name of file to which to export features 
  491. @param feat feature array 
  492. @param n number of features 
  493.  
  494. @return Returns 0 on success or 1 on error 
  495. */  
  496. static int export_lowe_features( char* filename, struct feature* feat, int n )  
  497. {  
  498.     FILE* file;  
  499.     int i, j, d;  
  500.   
  501.     if( n <= 0 )  
  502.     {  
  503.         fprintf( stderr, "Warning: feature count %d, %s, line %s\n",  
  504.                 n, __FILE__, __LINE__ );  
  505.         return 1;  
  506.     }  
  507.     if( ! ( file = fopen( filename, "w" ) ) )  
  508.     {  
  509.         fprintf( stderr, "Warning: error opening %s, %s, line %d\n",  
  510.                 filename, __FILE__, __LINE__ );  
  511.         return 1;  
  512.     }  
  513.   
  514.     d = feat[0].d;  
  515.     fprintf( file, "%d %d\n", n, d );  
  516.     for( i = 0; i < n; i++ )  
  517.     {  
  518.         fprintf( file, "%f %f %f %f", feat[i].y, feat[i].x,  
  519.                 feat[i].scl, feat[i].ori );  
  520.         for( j = 0; j < d; j++ )  
  521.         {  
  522.             /* write 20 descriptor values per line */  
  523.             if( j % 20 == 0 )  
  524.                 fprintf( file, "\n" );  
  525.             fprintf( file, " %d", (int)(feat[i].descr[j]) );  
  526.         }  
  527.         fprintf( file, "\n" );  
  528.     }  
  529.   
  530.     if( fclose(file) )  
  531.     {  
  532.         fprintf( stderr, "Warning: file close error, %s, line %d\n",  
  533.                 __FILE__, __LINE__ );  
  534.         return 1;  
  535.     }  
  536.   
  537.     return 0;  
  538. }  
  539.   
  540.   
  541. /* 
  542. Draws Lowe-type features 
  543.  
  544. @param img image on which to draw features 
  545. @param feat array of Oxford-type features 
  546. @param n number of features 
  547. */  
  548. static void draw_lowe_features( IplImage* img, struct feature* feat, int n )  
  549. {  
  550.     CvScalar color = CV_RGB( 255, 255, 255 );  
  551.     int i;  
  552.   
  553.     if( img-> nChannels > 1 )  
  554.         color = FEATURE_LOWE_COLOR;  
  555.     for( i = 0; i < n; i++ )  
  556.         draw_lowe_feature( img, feat + i, color );  
  557. }  
  558.   
  559.   
  560.   
  561. /* 
  562. Draws a single Lowe-type feature 
  563.  
  564. @param img image on which to draw 
  565. @param feat feature to be drawn 
  566. @param color color in which to draw 
  567. */  
  568. static void draw_lowe_feature( IplImage* img, struct feature* feat, CvScalar color )  
  569. {  
  570.     int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;  
  571.     double scl, ori;  
  572.     double scale = 5.0;  
  573.     double hscale = 0.75;  
  574.     CvPoint start, end, h1, h2;  
  575.   
  576.     /* compute points for an arrow scaled and rotated by feat's scl and ori */  
  577.     start_x = cvRound( feat->x );  
  578.     start_y = cvRound( feat->y );  
  579.     scl = feat->scl;  
  580.     ori = feat->ori;  
  581.     len = cvRound( scl * scale );  
  582.     hlen = cvRound( scl * hscale );  
  583.     blen = len - hlen;  
  584.     end_x = cvRound( len *  cos( ori ) ) + start_x;  
  585.     end_y = cvRound( len * -sin( ori ) ) + start_y;  
  586.     h1_x = cvRound( blen *  cos( ori + CV_PI / 18.0 ) ) + start_x;  
  587.     h1_y = cvRound( blen * -sin( ori + CV_PI / 18.0 ) ) + start_y;  
  588.     h2_x = cvRound( blen *  cos( ori - CV_PI / 18.0 ) ) + start_x;  
  589.     h2_y = cvRound( blen * -sin( ori - CV_PI / 18.0 ) ) + start_y;  
  590.     start = cvPoint( start_x, start_y );  
  591.     end = cvPoint( end_x, end_y );  
  592.     h1 = cvPoint( h1_x, h1_y );  
  593.     h2 = cvPoint( h2_x, h2_y );  
  594.   
  595.     cvLine( img, start, end, color, 1, 8, 0 );  
  596.     cvLine( img, end, h1, color, 1, 8, 0 );  
  597.     cvLine( img, end, h2, color, 1, 8, 0 );  
  598. }  

3、xforms.h

CvMat * ransac_xform (struct feature*features, int n, int mtype, ransac_xform_fn xform_fn, int m, doublep_badxform, ransac_err_fn err_fn, double err_tol, struct feature ***inliers,int *n_in)

        运用RANSAC方法进行特征匹配,计算出匹配最佳的图像转化矩阵

CvMat * dlt_homog (CvPoint2D64f *pts,CvPoint2D64f *mpts, int n)

         运用线性变换,进行点匹配计算平面单应性

CvMat * lsq_homog (CvPoint2D64f *pts,CvPoint2D64f *mpts, int n)

         进行点匹配,计算对角线最短的平面单应性

double     homog_xfer_err(CvPoint2D64f pt, CvPoint2D64f mpt, CvMat *H)

         对于给定的单应性,计算某点及其匹配的转换误差

CvPoint2D64f persp_xform_pt (CvPoint2D64fpt, CvMat *T)

        透视变换

xforms.h

  1. /**@file 
  2. Functions for computing transforms from image feature correspondences 
  3.  
  4. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  5. @version 1.1.2-20100521 
  6. */  
  7.   
  8. #ifndef XFORM_H  
  9. #define XFORM_H  
  10.   
  11. #include <cxcore.h>  
  12.   
  13.   
  14. /********************************** Structures *******************************/  
  15.   
  16. struct feature;  
  17.   
  18. /** holds feature data relevant to ransac */  
  19. struct ransac_data  
  20. {  
  21.     void* orig_feat_data;  
  22.     int sampled;  
  23. };  
  24.   
  25. /******************************* Defs and macros *****************************/  
  26.   
  27. /* RANSAC error tolerance in pixels */  
  28. #define RANSAC_ERR_TOL 3  
  29.   
  30. /** pessimistic estimate of fraction of inlers for RANSAC */  
  31. #define RANSAC_INLIER_FRAC_EST 0.25  
  32.   
  33. /** estimate of the probability that a correspondence supports a bad model */  
  34. #define RANSAC_PROB_BAD_SUPP 0.10  
  35.   
  36. /* extracts a feature's RANSAC data */  
  37. #define feat_ransac_data( feat ) ( (struct ransac_data*) (feat)->feature_data )  
  38.   
  39.   
  40. /** 
  41. Prototype for transformation functions passed to ransac_xform().  Functions 
  42. of this type should compute a transformation matrix given a set of point 
  43. correspondences. 
  44.  
  45. @param pts array of points 
  46. @param mpts array of corresponding points; each \a pts[\a i], \a i=0..\a n-1, 
  47.     corresponds to \a mpts[\a i] 
  48. @param n number of points in both \a pts and \a mpts 
  49.  
  50. @return Should return a transformation matrix that transforms each point in 
  51.     \a pts to the corresponding point in \a mpts or NULL on failure. 
  52. */  
  53. typedef CvMat* (*ransac_xform_fn)( CvPoint2D64f* pts, CvPoint2D64f* mpts,  
  54.                                   int n );  
  55.   
  56.   
  57. /** 
  58. Prototype for error functions passed to ransac_xform().  For a given 
  59. point, its correspondence, and a transform, functions of this type should 
  60. compute a measure of error between the correspondence and the point after 
  61. the point has been transformed by the transform. 
  62.  
  63. @param pt a point 
  64. @param mpt \a pt's correspondence 
  65. @param T a transform 
  66.  
  67. @return Should return a measure of error between \a mpt and \a pt after 
  68.     \a pt has been transformed by the transform \a T. 
  69. */  
  70. typedef double (*ransac_err_fn)( CvPoint2D64f pt, CvPoint2D64f mpt, CvMat* M );  
  71.   
  72.   
  73. /***************************** Function Prototypes ***************************/  
  74.   
  75.   
  76. /** 
  77. Calculates a best-fit image transform from image feature correspondences 
  78. using RANSAC. 
  79.  
  80. For more information refer to: 
  81.  
  82. Fischler, M. A. and Bolles, R. C.  Random sample consensus: a paradigm for 
  83. model fitting with applications to image analysis and automated cartography. 
  84. <EM>Communications of the ACM, 24</EM>, 6 (1981), pp. 381--395. 
  85.  
  86. @param features an array of features; only features with a non-NULL match 
  87.     of type \a mtype are used in homography computation 
  88. @param n number of features in \a feat 
  89. @param mtype determines which of each feature's match fields to use 
  90.     for transform computation; should be one of FEATURE_FWD_MATCH, 
  91.     FEATURE_BCK_MATCH, or FEATURE_MDL_MATCH; if this is FEATURE_MDL_MATCH, 
  92.     correspondences are assumed to be between a feature's img_pt field 
  93.     and its match's mdl_pt field, otherwise correspondences are assumed to 
  94.     be between the the feature's img_pt field and its match's img_pt field 
  95. @param xform_fn pointer to the function used to compute the desired 
  96.     transformation from feature correspondences 
  97. @param m minimum number of correspondences necessary to instantiate the 
  98.     transform computed by \a xform_fn 
  99. @param p_badxform desired probability that the final transformation 
  100.     returned by RANSAC is corrupted by outliers (i.e. the probability that 
  101.     no samples of all inliers were drawn) 
  102. @param err_fn pointer to the function used to compute a measure of error 
  103.     between putative correspondences for a given transform 
  104. @param err_tol correspondences within this distance of each other are 
  105.     considered as inliers for a given transform 
  106. @param inliers if not NULL, output as an array of pointers to the final 
  107.     set of inliers; memory for this array is allocated by this function and 
  108.     must be freed by the caller using free(*inliers) 
  109. @param n_in if not NULL, output as the final number of inliers 
  110.  
  111. @return Returns a transformation matrix computed using RANSAC or NULL 
  112.     on error or if an acceptable transform could not be computed. 
  113. */  
  114. extern CvMat* ransac_xform( struct feature* features, int n, int mtype,  
  115.                            ransac_xform_fn xform_fn, int m,  
  116.                            double p_badxform, ransac_err_fn err_fn,  
  117.                            double err_tol, struct feature*** inliers,  
  118.                            int* n_in );  
  119.   
  120.   
  121. /** 
  122. Calculates a planar homography from point correspondeces using the direct 
  123. linear transform.  Intended for use as a ransac_xform_fn. 
  124.  
  125. @param pts array of points 
  126. @param mpts array of corresponding points; each \a pts[\a i], \a i=0..\a 
  127.     n-1, corresponds to \a mpts[\a i] 
  128. @param n number of points in both \a pts and \a mpts; must be at least 4 
  129.  
  130. @return Returns the \f$3 \times 3\f$ planar homography matrix that 
  131.     transforms points in \a pts to their corresponding points in \a mpts 
  132.     or NULL if fewer than 4 correspondences were provided 
  133. */  
  134. extern CvMat* dlt_homog( CvPoint2D64f* pts, CvPoint2D64f* mpts, int n );  
  135.   
  136.   
  137. /** 
  138. Calculates a least-squares planar homography from point correspondeces. 
  139. Intended for use as a ransac_xform_fn. 
  140.  
  141. @param pts array of points 
  142. @param mpts array of corresponding points; each \a pts[\a i], \a i=0..\a n-1, 
  143.     corresponds to \a mpts[\a i] 
  144. @param n number of points in both \a pts and \a mpts; must be at least 4 
  145.  
  146. @return Returns the \f$3 \times 3\f$ least-squares planar homography 
  147.     matrix that transforms points in \a pts to their corresponding points 
  148.     in \a mpts or NULL if fewer than 4 correspondences were provided 
  149. */  
  150. extern CvMat* lsq_homog( CvPoint2D64f* pts, CvPoint2D64f* mpts, int n );  
  151.   
  152.   
  153. /** 
  154. Calculates the transfer error between a point and its correspondence for 
  155. a given homography, i.e. for a point \f$x\f$, it's correspondence \f$x'\f$, 
  156. and homography \f$H\f$, computes \f$d(x', Hx)^2\f$.  Intended for use as a 
  157. ransac_err_fn. 
  158.  
  159. @param pt a point 
  160. @param mpt \a pt's correspondence 
  161. @param H a homography matrix 
  162.  
  163. @return Returns the transfer error between \a pt and \a mpt given \a H 
  164. */  
  165. extern double homog_xfer_err( CvPoint2D64f pt, CvPoint2D64f mpt, CvMat* H );  
  166.   
  167.   
  168. /** 
  169. Performs a perspective transformation on a single point.  That is, for a 
  170. point \f$(x, y)\f$ and a \f$3 \times 3\f$ matrix \f$T\f$ this function 
  171. returns the point \f$(u, v)\f$, where<BR> 
  172.  
  173. \f$[x' \ y' \ w']^T = T \times [x \ y \ 1]^T\f$,<BR> 
  174.  
  175. and<BR> 
  176.  
  177. \f$(u, v) = (x'/w', y'/w')\f$. 
  178.  
  179. Note that affine transforms are a subset of perspective transforms. 
  180.  
  181. @param pt a 2D point 
  182. @param T a perspective transformation matrix 
  183.  
  184. @return Returns the point \f$(u, v)\f$ as above. 
  185. */  
  186. extern CvPoint2D64f persp_xform_pt( CvPoint2D64f pt, CvMat* T );  
  187.   
  188.   
  189. #endif  

xform.c
  1. /* 
  2. This file contains definitions for functions to compute transforms from 
  3. image feature correspondences 
  4.  
  5. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  6.  
  7. @version 1.1.2-20100521 
  8. */  
  9.   
  10. #include "xform.h"  
  11. #include "imgfeatures.h"  
  12. #include "utils.h"  
  13.   
  14. #include <cxcore.h>  
  15.   
  16. #include <stdlib.h>  
  17. #include <time.h>  
  18.   
  19. /************************* Local Function Prototypes *************************/  
  20.   
  21. static __inline struct feature* get_match( struct feature*, int );  
  22. static int get_matched_features( struct feature*, intintstruct feature*** );  
  23. static int calc_min_inliers( intintdoubledouble );  
  24. static __inline double log_factorial( int );  
  25. static struct feature** draw_ransac_sample( struct feature**, intint );  
  26. static void extract_corresp_pts( struct feature**, intint, CvPoint2D64f**,  
  27.                                  CvPoint2D64f** );  
  28. static int find_consensus( struct feature**, intint, CvMat*, ransac_err_fn,  
  29.                            doublestruct feature*** );  
  30. static __inline void release_mem( CvPoint2D64f*, CvPoint2D64f*,  
  31. static struct feature** );  
  32.   
  33. /********************** Functions prototyped in xform.h **********************/  
  34.   
  35.   
  36. /* 
  37. Calculates a best-fit image transform from image feature correspondences 
  38. using RANSAC. 
  39.  
  40. For more information refer to: 
  41.  
  42. Fischler, M. A. and Bolles, R. C.  Random sample consensus: a paradigm for 
  43. model fitting with applications to image analysis and automated cartography. 
  44. <EM>Communications of the ACM, 24</EM>, 6 (1981), pp. 381--395. 
  45.  
  46. @param features an array of features; only features with a non-NULL match 
  47.     of type mtype are used in homography computation 
  48. @param n number of features in feat 
  49. @param mtype determines which of each feature's match fields to use 
  50.     for model computation; should be one of FEATURE_FWD_MATCH, 
  51.     FEATURE_BCK_MATCH, or FEATURE_MDL_MATCH; if this is FEATURE_MDL_MATCH, 
  52.     correspondences are assumed to be between a feature's img_pt field 
  53.     and its match's mdl_pt field, otherwise correspondences are assumed to 
  54.     be between the the feature's img_pt field and its match's img_pt field 
  55. @param xform_fn pointer to the function used to compute the desired 
  56.     transformation from feature correspondences 
  57. @param m minimum number of correspondences necessary to instantiate the 
  58.     model computed by xform_fn 
  59. @param p_badxform desired probability that the final transformation 
  60.     returned by RANSAC is corrupted by outliers (i.e. the probability that 
  61.     no samples of all inliers were drawn) 
  62. @param err_fn pointer to the function used to compute a measure of error 
  63.     between putative correspondences and a computed model 
  64. @param err_tol correspondences within this distance of a computed model are 
  65.     considered as inliers 
  66. @param inliers if not NULL, output as an array of pointers to the final 
  67.     set of inliers 
  68. @param n_in if not NULL and \a inliers is not NULL, output as the final 
  69.     number of inliers 
  70.  
  71. @return Returns a transformation matrix computed using RANSAC or NULL 
  72.     on error or if an acceptable transform could not be computed. 
  73. */  
  74. CvMat* ransac_xform( struct feature* features, int n, int mtype,  
  75.                     ransac_xform_fn xform_fn, int m, double p_badxform,  
  76.                     ransac_err_fn err_fn, double err_tol,  
  77. struct feature*** inliers, int* n_in )  
  78. {  
  79.     struct feature** matched, ** sample, ** consensus, ** consensus_max = NULL;  
  80.     struct ransac_data* rdata;  
  81.     CvPoint2D64f* pts, * mpts;  
  82.     CvMat* M = NULL;  
  83.     double p, in_frac = RANSAC_INLIER_FRAC_EST;  
  84.     int i, nm, in, in_min, in_max = 0, k = 0;  
  85.   
  86.     nm = get_matched_features( features, n, mtype, &matched );  
  87.     if( nm < m )  
  88.     {  
  89.         fprintf( stderr, "Warning: not enough matches to compute xform, %s" \  
  90.             " line %d\n", __FILE__, __LINE__ );  
  91.         goto end;  
  92.     }  
  93.   
  94.     /* initialize random number generator */  
  95.     srand( time(NULL) );  
  96.   
  97.     in_min = calc_min_inliers( nm, m, RANSAC_PROB_BAD_SUPP, p_badxform );  
  98.     p = pow( 1.0 - pow( in_frac, m ), k );  
  99.     i = 0;  
  100.     while( p > p_badxform )  
  101.     {  
  102.         sample = draw_ransac_sample( matched, nm, m );  
  103.         extract_corresp_pts( sample, m, mtype, &pts, &mpts );  
  104.         M = xform_fn( pts, mpts, m );  
  105.         if( ! M )  
  106.             goto iteration_end;  
  107.         in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);  
  108.         if( in > in_max )  
  109.         {  
  110.             if( consensus_max )  
  111.                 free( consensus_max );  
  112.             consensus_max = consensus;  
  113.             in_max = in;  
  114.             in_frac = (double)in_max / nm;  
  115.         }  
  116.         else  
  117.             free( consensus );  
  118.         cvReleaseMat( &M );  
  119.   
  120. iteration_end:  
  121.         release_mem( pts, mpts, sample );  
  122.         p = pow( 1.0 - pow( in_frac, m ), ++k );  
  123.     }  
  124.   
  125.     /* calculate final transform based on best consensus set */  
  126.     if( in_max >= in_min )  
  127.     {  
  128.         extract_corresp_pts( consensus_max, in_max, mtype, &pts, &mpts );  
  129.         M = xform_fn( pts, mpts, in_max );  
  130.         in = find_consensus( matched, nm, mtype, M, err_fn, err_tol, &consensus);  
  131.         cvReleaseMat( &M );  
  132.         release_mem( pts, mpts, consensus_max );  
  133.         extract_corresp_pts( consensus, in, mtype, &pts, &mpts );  
  134.         M = xform_fn( pts, mpts, in );  
  135.         if( inliers )  
  136.         {  
  137.             *inliers = consensus;  
  138.             consensus = NULL;  
  139.         }  
  140.         if( n_in )  
  141.             *n_in = in;  
  142.         release_mem( pts, mpts, consensus );  
  143.     }  
  144.     else if( consensus_max )  
  145.     {  
  146.         if( inliers )  
  147.             *inliers = NULL;  
  148.         if( n_in )  
  149.             *n_in = 0;  
  150.         free( consensus_max );  
  151.     }  
  152.   
  153. end:  
  154.     for( i = 0; i < nm; i++ )  
  155.     {  
  156.         rdata = feat_ransac_data( matched[i] );  
  157.         matched[i]->feature_data = rdata->orig_feat_data;  
  158.         free( rdata );  
  159.     }  
  160.     free( matched );  
  161.     return M;  
  162. }  
  163.   
  164.   
  165.   
  166. /* 
  167. Calculates a planar homography from point correspondeces using the direct 
  168. linear transform.  Intended for use as a ransac_xform_fn. 
  169.    
  170. @param pts array of points 
  171. @param mpts array of corresponding points; each pts[i], i=0..n-1, 
  172.   corresponds to mpts[i] 
  173. @param n number of points in both pts and mpts; must be at least 4 
  174.    
  175. @return Returns the 3x3 planar homography matrix that transforms points 
  176.   in pts to their corresponding points in mpts or NULL if fewer than 4 
  177.   correspondences were provided 
  178. */  
  179. CvMat* dlt_homog( CvPoint2D64f* pts, CvPoint2D64f* mpts, int n )  
  180. {  
  181.     CvMat* H, * A, * VT, * D, h, v9;  
  182.     double _h[9];  
  183.     int i;  
  184.   
  185.     if( n < 4 )  
  186.         return NULL;  
  187.   
  188.     /* set up matrices so we can unstack homography into h; Ah = 0 */  
  189.     A = cvCreateMat( 2*n, 9, CV_64FC1 );  
  190.     cvZero( A );  
  191.     for( i = 0; i < n; i++ )  
  192.     {  
  193.         cvmSet( A, 2*i, 3, -pts[i].x );  
  194.         cvmSet( A, 2*i, 4, -pts[i].y );  
  195.         cvmSet( A, 2*i, 5, -1.0  );  
  196.         cvmSet( A, 2*i, 6, mpts[i].y * pts[i].x );  
  197.         cvmSet( A, 2*i, 7, mpts[i].y * pts[i].y );  
  198.         cvmSet( A, 2*i, 8, mpts[i].y );  
  199.         cvmSet( A, 2*i+1, 0, pts[i].x );  
  200.         cvmSet( A, 2*i+1, 1, pts[i].y );  
  201.         cvmSet( A, 2*i+1, 2, 1.0  );  
  202.         cvmSet( A, 2*i+1, 6, -mpts[i].x * pts[i].x );  
  203.         cvmSet( A, 2*i+1, 7, -mpts[i].x * pts[i].y );  
  204.         cvmSet( A, 2*i+1, 8, -mpts[i].x );  
  205.     }  
  206.     D = cvCreateMat( 9, 9, CV_64FC1 );  
  207.     VT = cvCreateMat( 9, 9, CV_64FC1 );  
  208.     cvSVD( A, D, NULL, VT, CV_SVD_MODIFY_A + CV_SVD_V_T );  
  209.     v9 = cvMat( 1, 9, CV_64FC1, NULL );  
  210.     cvGetRow( VT, &v9, 8 );  
  211.     h = cvMat( 1, 9, CV_64FC1, _h );  
  212.     cvCopy( &v9, &h, NULL );  
  213.     h = cvMat( 3, 3, CV_64FC1, _h );  
  214.     H = cvCreateMat( 3, 3, CV_64FC1 );  
  215.     cvConvert( &h, H );  
  216.   
  217.     cvReleaseMat( &A );  
  218.     cvReleaseMat( &D );  
  219.     cvReleaseMat( &VT );  
  220.     return H;  
  221. }  
  222.   
  223.   
  224.   
  225. /* 
  226. Calculates a least-squares planar homography from point correspondeces. 
  227.  
  228. @param pts array of points 
  229. @param mpts array of corresponding points; each pts[i], i=0..n-1, corresponds 
  230.     to mpts[i] 
  231. @param n number of points in both pts and mpts; must be at least 4 
  232.  
  233. @return Returns the 3 x 3 least-squares planar homography matrix that 
  234.     transforms points in pts to their corresponding points in mpts or NULL if 
  235.     fewer than 4 correspondences were provided 
  236. */  
  237. CvMat* lsq_homog( CvPoint2D64f* pts, CvPoint2D64f* mpts, int n )  
  238. {  
  239.     CvMat* H, * A, * B, X;  
  240.     double x[9];  
  241.     int i;  
  242.   
  243.     if( n < 4 )  
  244.     {  
  245.         fprintf( stderr, "Warning: too few points in lsq_homog(), %s line %d\n",  
  246.             __FILE__, __LINE__ );  
  247.         return NULL;  
  248.     }  
  249.   
  250.     /* set up matrices so we can unstack homography into X; AX = B */  
  251.     A = cvCreateMat( 2*n, 8, CV_64FC1 );  
  252.     B = cvCreateMat( 2*n, 1, CV_64FC1 );  
  253.     X = cvMat( 8, 1, CV_64FC1, x );  
  254.     H = cvCreateMat(3, 3, CV_64FC1);  
  255.     cvZero( A );  
  256.     for( i = 0; i < n; i++ )  
  257.     {  
  258.         cvmSet( A, i, 0, pts[i].x );  
  259.         cvmSet( A, i+n, 3, pts[i].x );  
  260.         cvmSet( A, i, 1, pts[i].y );  
  261.         cvmSet( A, i+n, 4, pts[i].y );  
  262.         cvmSet( A, i, 2, 1.0 );  
  263.         cvmSet( A, i+n, 5, 1.0 );  
  264.         cvmSet( A, i, 6, -pts[i].x * mpts[i].x );  
  265.         cvmSet( A, i, 7, -pts[i].y * mpts[i].x );  
  266.         cvmSet( A, i+n, 6, -pts[i].x * mpts[i].y );  
  267.         cvmSet( A, i+n, 7, -pts[i].y * mpts[i].y );  
  268.         cvmSet( B, i, 0, mpts[i].x );  
  269.         cvmSet( B, i+n, 0, mpts[i].y );  
  270.     }  
  271.     cvSolve( A, B, &X, CV_SVD );  
  272.     x[8] = 1.0;  
  273.     X = cvMat( 3, 3, CV_64FC1, x );  
  274.     cvConvert( &X, H );  
  275.   
  276.     cvReleaseMat( &A );  
  277.     cvReleaseMat( &B );  
  278.     return H;  
  279. }  
  280.   
  281.   
  282.   
  283. /* 
  284. Calculates the transfer error between a point and its correspondence for 
  285. a given homography, i.e. for a point x, it's correspondence x', and 
  286. homography H, computes d(x', Hx)^2. 
  287.  
  288. @param pt a point 
  289. @param mpt pt's correspondence 
  290. @param H a homography matrix 
  291.  
  292. @return Returns the transfer error between pt and mpt given H 
  293. */  
  294. double homog_xfer_err( CvPoint2D64f pt, CvPoint2D64f mpt, CvMat* H )  
  295. {  
  296.     CvPoint2D64f xpt = persp_xform_pt( pt, H );  
  297.   
  298.     return sqrt( dist_sq_2D( xpt, mpt ) );  
  299. }  
  300.   
  301.   
  302.   
  303. /* 
  304. Performs a perspective transformation on a single point.  That is, for a 
  305. point (x, y) and a 3 x 3 matrix T this function returns the point 
  306. (u, v), where 
  307.  
  308. [x' y' w']^T = T * [x y 1]^T, 
  309.  
  310. and 
  311.  
  312. (u, v) = (x'/w', y'/w'). 
  313.  
  314. Note that affine transforms are a subset of perspective transforms. 
  315.  
  316. @param pt a 2D point 
  317. @param T a perspective transformation matrix 
  318.  
  319. @return Returns the point (u, v) as above. 
  320. */  
  321. CvPoint2D64f persp_xform_pt( CvPoint2D64f pt, CvMat* T )  
  322. {  
  323.     CvMat XY, UV;  
  324.     double xy[3] = { pt.x, pt.y, 1.0 }, uv[3] = { 0 };  
  325.     CvPoint2D64f rslt;  
  326.   
  327.     cvInitMatHeader( &XY, 3, 1, CV_64FC1, xy, CV_AUTOSTEP );  
  328.     cvInitMatHeader( &UV, 3, 1, CV_64FC1, uv, CV_AUTOSTEP );  
  329.     cvMatMul( T, &XY, &UV );  
  330.     rslt = cvPoint2D64f( uv[0] / uv[2], uv[1] / uv[2] );  
  331.   
  332.     return rslt;  
  333. }  
  334.   
  335.   
  336. /************************ Local funciton definitions *************************/  
  337.   
  338. /* 
  339. Returns a feature's match according to a specified match type 
  340.  
  341. @param feat feature 
  342. @param mtype match type, one of FEATURE_FWD_MATCH, FEATURE_BCK_MATCH, or 
  343. FEATURE_MDL_MATCH 
  344.  
  345. @return Returns feat's match corresponding to mtype or NULL for bad mtype 
  346. */  
  347. static __inline struct feature* get_match( struct feature* feat, int mtype )  
  348. {  
  349.     if( mtype == FEATURE_MDL_MATCH )  
  350.         return feat->mdl_match;  
  351.     if( mtype == FEATURE_BCK_MATCH )  
  352.         return feat->bck_match;  
  353.     if( mtype == FEATURE_FWD_MATCH )  
  354.         return feat->fwd_match;  
  355.     return NULL;  
  356. }  
  357.   
  358.   
  359.   
  360. /* 
  361. Finds all features with a match of a specified type and stores pointers 
  362. to them in an array.  Additionally initializes each matched feature's 
  363. feature_data field with a ransac_data structure. 
  364.  
  365. @param features array of features 
  366. @param n number of features in features 
  367. @param mtype match type, one of FEATURE_{FWD,BCK,MDL}_MATCH 
  368. @param matched output as an array of pointers to features with a match of 
  369. the specified type 
  370.  
  371. @return Returns the number of features output in matched. 
  372. */  
  373. static int get_matched_features( struct feature* features, int n, int mtype,  
  374.                                  struct feature*** matched )  
  375. {  
  376.     struct feature** _matched;  
  377.     struct ransac_data* rdata;  
  378.     int i, m = 0;  
  379.   
  380.     _matched = calloc( n, sizeofstruct feature* ) );  
  381.     for( i = 0; i < n; i++ )  
  382.         if( get_match( features + i, mtype ) )  
  383.         {  
  384.             rdata = malloc( sizeofstruct ransac_data ) );  
  385.             memset( rdata, 0, sizeofstruct ransac_data ) );  
  386.             rdata->orig_feat_data = features[i].feature_data;  
  387.             _matched[m] = features + i;  
  388.             _matched[m]->feature_data = rdata;  
  389.             m++;  
  390.         }  
  391.         *matched = _matched;  
  392.         return m;  
  393. }  
  394.   
  395.   
  396.   
  397. /* 
  398. Calculates the minimum number of inliers as a function of the number of 
  399. putative correspondences.  Based on equation (7) in 
  400.  
  401. Chum, O. and Matas, J.  Matching with PROSAC -- Progressive Sample Consensus. 
  402. In <EM>Conference on Computer Vision and Pattern Recognition (CVPR)</EM>, 
  403. (2005), pp. 220--226. 
  404.  
  405. @param n number of putative correspondences 
  406. @param m min number of correspondences to compute the model in question 
  407. @param p_badsupp prob. that a bad model is supported by a correspondence 
  408. @param p_badxform desired prob. that the final transformation returned is bad 
  409.  
  410. @return Returns the minimum number of inliers required to guarantee, based 
  411.     on p_badsupp, that the probability that the final transformation returned 
  412.     by RANSAC is less than p_badxform 
  413. */  
  414. static int calc_min_inliers( int n, int m, double p_badsupp, double p_badxform )  
  415. {  
  416.     double pi, sum;  
  417.     int i, j;  
  418.   
  419.     for( j = m+1; j <= n; j++ )  
  420.     {  
  421.         sum = 0;  
  422.         for( i = j; i <= n; i++ )  
  423.         {  
  424.             pi = ( i - m ) * log( p_badsupp ) + ( n - i + m ) * log( 1.0 - p_badsupp ) +  
  425.                 log_factorial( n - m ) - log_factorial( i - m ) -  
  426.                 log_factorial( n - i );  
  427.             /* 
  428.              * Last three terms above are equivalent to log( n-m choose i-m ) 
  429.              */  
  430.             sum += exp( pi );  
  431.         }  
  432.         if( sum < p_badxform )  
  433.             break;  
  434.     }  
  435.     return j;  
  436. }  
  437.   
  438.   
  439.   
  440. /* 
  441.   Calculates the natural log of the factorial of a number 
  442.  
  443.   @param n number 
  444.  
  445.   @return Returns log( n! ) 
  446. */  
  447. static __inline double log_factorial( int n )  
  448. {  
  449.   double f = 0;  
  450.   int i;  
  451.   
  452.   for( i = 1; i <= n; i++ )  
  453.     f += log( i );  
  454.   
  455.   return f;  
  456. }  
  457.   
  458.   
  459.   
  460. /* 
  461. Draws a RANSAC sample from a set of features. 
  462.  
  463. @param features array of pointers to features from which to sample 
  464. @param n number of features in features 
  465. @param m size of the sample 
  466.  
  467. @return Returns an array of pointers to the sampled features; the sampled 
  468.     field of each sampled feature's ransac_data is set to 1 
  469. */  
  470. static struct feature** draw_ransac_sample( struct feature** features, int n, int m )  
  471. {  
  472.     struct feature** sample, * feat;  
  473.     struct ransac_data* rdata;  
  474.     int i, x;  
  475.   
  476.     for( i = 0; i < n; i++ )  
  477.     {  
  478.         rdata = feat_ransac_data( features[i] );  
  479.         rdata->sampled = 0;  
  480.     }  
  481.   
  482.     sample = calloc( m, sizeofstruct feature* ) );  
  483.     for( i = 0; i < m; i++ )  
  484.     {  
  485.         do  
  486.         {  
  487.             x = rand() % n;  
  488.             feat = features[x];  
  489.             rdata = feat_ransac_data( feat );  
  490.         }  
  491.         while( rdata->sampled );  
  492.         sample[i] = feat;  
  493.         rdata->sampled = 1;  
  494.     }  
  495.   
  496.     return sample;  
  497. }  
  498.   
  499.   
  500.   
  501. /* 
  502. Extrancs raw point correspondence locations from a set of features 
  503.  
  504. @param features array of features from which to extract points and match 
  505.     points; each of these is assumed to have a match of type mtype 
  506. @param n number of features 
  507. @param mtype match type; if FEATURE_MDL_MATCH correspondences are assumed 
  508.     to be between each feature's img_pt field and it's match's mdl_pt field, 
  509.     otherwise, correspondences are assumed to be between img_pt and img_pt 
  510. @param pts output as an array of raw point locations from features 
  511. @param mpts output as an array of raw point locations from features' matches 
  512. */  
  513. static void extract_corresp_pts( struct feature** features, int n, int mtype,  
  514.                                  CvPoint2D64f** pts, CvPoint2D64f** mpts )  
  515. {  
  516.     struct feature* match;  
  517.     CvPoint2D64f* _pts, * _mpts;  
  518.     int i;  
  519.   
  520.     _pts = calloc( n, sizeof( CvPoint2D64f ) );  
  521.     _mpts = calloc( n, sizeof( CvPoint2D64f ) );  
  522.   
  523.     if( mtype == FEATURE_MDL_MATCH )  
  524.         for( i = 0; i < n; i++ )  
  525.         {  
  526.             match = get_match( features[i], mtype );  
  527.             if( ! match )  
  528.                 fatal_error( "feature does not have match of type %d, %s line %d",  
  529.                             mtype, __FILE__, __LINE__ );  
  530.             _pts[i] = features[i]->img_pt;  
  531.             _mpts[i] = match->mdl_pt;  
  532.         }  
  533.   
  534.     else  
  535.         for( i = 0; i < n; i++ )  
  536.         {  
  537.             match = get_match( features[i], mtype );  
  538.             if( ! match )  
  539.                 fatal_error( "feature does not have match of type %d, %s line %d",  
  540.                             mtype, __FILE__, __LINE__ );  
  541.             _pts[i] = features[i]->img_pt;  
  542.             _mpts[i] = match->img_pt;  
  543.         }  
  544.   
  545.         *pts = _pts;  
  546.         *mpts = _mpts;  
  547. }  
  548.   
  549.   
  550.   
  551. /* 
  552. For a given model and error function, finds a consensus from a set of 
  553. feature correspondences. 
  554.  
  555. @param features set of pointers to features; every feature is assumed to 
  556.     have a match of type mtype 
  557. @param n number of features in features 
  558. @param mtype determines the match field of each feature against which to 
  559.     measure error; if this is FEATURE_MDL_MATCH, correspondences are assumed 
  560.     to be between the feature's img_pt field and the match's mdl_pt field; 
  561.     otherwise matches are assumed to be between img_pt and img_pt 
  562. @param M model for which a consensus set is being found 
  563. @param err_fn error function used to measure distance from M 
  564. @param err_tol correspondences within this distance of M are added to the 
  565.     consensus set 
  566. @param consensus output as an array of pointers to features in the 
  567.     consensus set 
  568.  
  569. @return Returns the number of points in the consensus set 
  570. */  
  571. static int find_consensus( struct feature** features, int n, int mtype,  
  572.                            CvMat* M, ransac_err_fn err_fn, double err_tol,  
  573.                            struct feature*** consensus )  
  574. {  
  575.     struct feature** _consensus;  
  576.     struct feature* match;  
  577.     CvPoint2D64f pt, mpt;  
  578.     double err;  
  579.     int i, in = 0;  
  580.   
  581.     _consensus = calloc( n, sizeofstruct feature* ) );  
  582.   
  583.     if( mtype == FEATURE_MDL_MATCH )  
  584.         for( i = 0; i < n; i++ )  
  585.         {  
  586.             match = get_match( features[i], mtype );  
  587.             if( ! match )  
  588.                 fatal_error( "feature does not have match of type %d, %s line %d",  
  589.                             mtype, __FILE__, __LINE__ );  
  590.             pt = features[i]->img_pt;  
  591.             mpt = match->mdl_pt;  
  592.             err = err_fn( pt, mpt, M );  
  593.             if( err <= err_tol )  
  594.                 _consensus[in++] = features[i];  
  595.         }  
  596.   
  597.     else  
  598.         for( i = 0; i < n; i++ )  
  599.         {  
  600.             match = get_match( features[i], mtype );  
  601.             if( ! match )  
  602.                 fatal_error( "feature does not have match of type %d, %s line %d",  
  603.                             mtype, __FILE__, __LINE__ );  
  604.             pt = features[i]->img_pt;  
  605.             mpt = match->img_pt;  
  606.             err = err_fn( pt, mpt, M );  
  607.             if( err <= err_tol )  
  608.                 _consensus[in++] = features[i];  
  609.         }  
  610.     *consensus = _consensus;  
  611.     return in;  
  612. }  
  613.   
  614.   
  615.   
  616. /* 
  617. Releases memory and reduces code size above 
  618.  
  619. @param pts1 an array of points 
  620. @param pts2 an array of points 
  621. @param features an array of pointers to features; can be NULL 
  622. */  
  623. static __inline void release_mem( CvPoint2D64f* pts1, CvPoint2D64f* pts2,  
  624.                                   struct feature** features )  
  625. {  
  626.     free( pts1 );  
  627.     free( pts2 );  
  628.     if( features )  
  629.         free( features );  
  630. }  


4、min_pq.h构建一个队列

struct min_pq

{

struct pq_node* pq_array;    /* array containing priority queue */

int nallocd;                 /* number of elementsallocated */

int n;                       /**< number ofelements in pq */

};

实质是一个队列,先入先出

基本功能是插入删除,获取队列首位的元素。

队列的数据类型是struct min_pq

min_pq.h

  1. /**@file 
  2. Functions and structures for implementing a minimizing priority queue. 
  3.  
  4. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  5. @version 1.1.2-20100521 
  6. */  
  7.   
  8.   
  9. #ifndef MINPQ_H  
  10. #define MINPQ_H  
  11.   
  12. #include <stdlib.h>  
  13.   
  14.   
  15. /******************************* Defs and macros *****************************/  
  16.   
  17. /* initial # of priority queue elements for which to allocate space */  
  18. #define MINPQ_INIT_NALLOCD 512  
  19.   
  20. /********************************** Structures *******************************/  
  21.   
  22. /** an element in a minimizing priority queue */  
  23. struct pq_node  
  24. {  
  25.     void* data;  
  26.     int key;  
  27. };  
  28.   
  29.   
  30. /** a minimizing priority queue */  
  31. struct min_pq  
  32. {  
  33.     struct pq_node* pq_array;    /* array containing priority queue */  
  34.     int nallocd;                 /* number of elements allocated */  
  35.     int n;                       /**< number of elements in pq */  
  36. };  
  37.   
  38.   
  39. /*************************** Function Prototypes *****************************/  
  40.   
  41. /** 
  42. Creates a new minimizing priority queue. 
  43. */  
  44. extern struct min_pq* minpq_init();  
  45.   
  46.   
  47. /** 
  48. Inserts an element into a minimizing priority queue. 
  49.  
  50. @param min_pq a minimizing priority queue 
  51. @param data the data to be inserted 
  52. @param key the key to be associated with \a data 
  53.  
  54. @return Returns 0 on success or 1 on failure. 
  55. */  
  56. extern int minpq_insert( struct min_pq* min_pq, void* data, int key );  
  57.   
  58.   
  59. /** 
  60. Returns the element of a minimizing priority queue with the smallest key 
  61. without removing it from the queue. 
  62.  
  63. @param min_pq a minimizing priority queue 
  64.  
  65. @return Returns the element of \a min_pq with the smallest key or NULL 
  66.     if \a min_pq is empty 
  67. */  
  68. extern void* minpq_get_min( struct min_pq* min_pq );  
  69.   
  70.   
  71. /** 
  72. Removes and returns the element of a minimizing priority queue with the 
  73. smallest key. 
  74.  
  75. @param min_pq a minimizing priority queue 
  76.  
  77. @return Returns the element of \a min_pq with the smallest key of NULL 
  78.     if \a min_pq is empty 
  79. */  
  80. extern void* minpq_extract_min( struct min_pq* min_pq );  
  81.   
  82.   
  83. /** 
  84. De-allocates the memory held by a minimizing priorioty queue 
  85.  
  86. @param min_pq pointer to a minimizing priority queue 
  87. */  
  88. extern void minpq_release( struct min_pq** min_pq );  
  89.   
  90.   
  91. #endif  


min_pq.c

  1. /* 
  2. Functions and structures for implementing a minimizing priority queue. 
  3.  
  4. Copyright (C) 2006-2010  Rob Hess <hess@eecs.oregonstate.edu> 
  5.  
  6. @version 1.1.2-20100521 
  7. */  
  8.   
  9. #include "minpq.h"  
  10. #include "utils.h"  
  11.   
  12. #include <limits.h>  
  13.   
  14.   
  15. /************************* Local Function Prototypes *************************/  
  16.   
  17. static void restore_minpq_order( struct pq_node*, intint );  
  18. static void decrease_pq_node_key( struct pq_node*, intint );  
  19.   
  20.   
  21. /************************** Local Inline Functions ***************************/  
  22.   
  23. /* returns the array index of element i's parent */  
  24. static __inline int parent( int i )  
  25. {  
  26.     return ( i - 1 ) / 2;  
  27. }  
  28.   
  29.   
  30. /* returns the array index of element i's right child */  
  31. static __inline int right( int i )  
  32. {  
  33.     return 2 * i + 2;  
  34. }  
  35.   
  36.   
  37. /* returns the array index of element i's left child */  
  38. static __inline int left( int i )  
  39. {  
  40.     return 2 * i + 1;  
  41. }  
  42.   
  43.   
  44. /********************** Functions prototyped in minpq.h **********************/  
  45.   
  46.   
  47. /* 
  48. Creates a new minimizing priority queue. 
  49. */  
  50. struct min_pq* minpq_init()  
  51. {  
  52.     struct min_pq* min_pq;  
  53.   
  54.     min_pq = malloc( sizeofstruct min_pq ) );  
  55.     min_pq->pq_array = calloc( MINPQ_INIT_NALLOCD, sizeofstruct pq_node ) );  
  56.     min_pq->nallocd = MINPQ_INIT_NALLOCD;  
  57.     min_pq->n = 0;  
  58.   
  59.     return min_pq;  
  60. }  
  61.   
  62.   
  63.   
  64. /** 
  65. Inserts an element into a minimizing priority queue. 
  66.  
  67. @param min_pq a minimizing priority queue 
  68. @param data the data to be inserted 
  69. @param key the key to be associated with \a data 
  70.  
  71. @return Returns 0 on success or 1 on failure. 
  72. */  
  73. int minpq_insert( struct min_pq* min_pq, void* data, int key )  
  74. {  
  75.     int n = min_pq->n;  
  76.   
  77.     /* double array allocation if necessary */  
  78.     if( min_pq->nallocd == n )  
  79.     {  
  80.         min_pq->nallocd = array_double( &min_pq->pq_array, min_pq->nallocd,  
  81.                                         sizeofstruct pq_node ) );  
  82.         if( ! min_pq->nallocd )  
  83.         {  
  84.             fprintf( stderr, "Warning: unable to allocate memory, %s, line %d\n",  
  85.                     __FILE__, __LINE__ );  
  86.             return 1;  
  87.         }  
  88.     }  
  89.   
  90.     min_pq->pq_array[n].data = data;  
  91.     min_pq->pq_array[n].key = INT_MAX;  
  92.     decrease_pq_node_key( min_pq->pq_array, min_pq->n, key );  
  93.     min_pq->n++;  
  94.   
  95.     return 0;  
  96. }  
  97.   
  98.   
  99.   
  100. /* 
  101. Returns the element of a minimizing priority queue with the smallest key 
  102. without removing it from the queue. 
  103.  
  104. @param min_pq a minimizing priority queue 
  105.  
  106. @return Returns the element of \a min_pq with the smallest key or NULL 
  107. if \a min_pq is empty 
  108. */  
  109. void* minpq_get_min( struct min_pq* min_pq )  
  110. {  
  111.     if( min_pq->n < 1 )  
  112.     {  
  113.         fprintf( stderr, "Warning: PQ empty, %s line %d\n", __FILE__, __LINE__ );  
  114.         return NULL;  
  115.     }  
  116.     return min_pq->pq_array[0].data;  
  117. }  
  118.   
  119.   
  120.   
  121. /* 
  122. Removes and returns the element of a minimizing priority queue with the 
  123. smallest key. 
  124.  
  125. @param min_pq a minimizing priority queue 
  126.  
  127. @return Returns the element of \a min_pq with the smallest key of NULL 
  128. if \a min_pq is empty 
  129. */  
  130. void* minpq_extract_min( struct min_pq* min_pq )  
  131. {  
  132.     void* data;  
  133.   
  134.     if( min_pq->n < 1 )  
  135.     {  
  136.         fprintf( stderr, "Warning: PQ empty, %s line %d\n", __FILE__, __LINE__ );  
  137.         return NULL;  
  138.     }  
  139.     data = min_pq->pq_array[0].data;  
  140.     min_pq->n--;  
  141.     min_pq->pq_array[0] = min_pq->pq_array[min_pq->n];  
  142.     restore_minpq_order( min_pq->pq_array, 0, min_pq->n );  
  143.   
  144.     return data;  
  145. }  
  146.   
  147.   
  148. /* 
  149. De-allocates the memory held by a minimizing priorioty queue 
  150.  
  151. @param min_pq pointer to a minimizing priority queue 
  152. */  
  153. void minpq_release( struct min_pq** min_pq )  
  154. {  
  155.     if( ! min_pq )  
  156.     {  
  157.         fprintf( stderr, "Warning: NULL pointer error, %s line %d\n", __FILE__,  
  158.                 __LINE__ );  
  159.         return;  
  160.     }  
  161.     if( *min_pq  &&  (*min_pq)->pq_array )  
  162.     {  
  163.         free( (*min_pq)->pq_array );  
  164.         free( *min_pq );  
  165.         *min_pq = NULL;  
  166.     }  
  167. }  
  168.   
  169.   
  170. /************************ Functions prototyped here **************************/  
  171.   
  172. /* 
  173. Decrease a minimizing pq element's key, rearranging the pq if necessary 
  174.  
  175. @param pq_array minimizing priority queue array 
  176. @param i index of the element whose key is to be decreased 
  177. @param key new value of element <EM>i</EM>'s key; if greater than current 
  178.     key, no action is taken 
  179. */  
  180. static void decrease_pq_node_key( struct pq_node* pq_array, int i, int key )  
  181. {  
  182.     struct pq_node tmp;  
  183.   
  184.     if( key > pq_array[i].key )  
  185.         return;  
  186.   
  187.     pq_array[i].key = key;  
  188.     while( i > 0  &&  pq_array[i].key < pq_array[parent(i)].key )  
  189.     {  
  190.         tmp = pq_array[parent(i)];  
  191.         pq_array[parent(i)] = pq_array[i];  
  192.         pq_array[i] = tmp;  
  193.         i = parent(i);  
  194.     }  
  195. }  
  196.   
  197.   
  198.   
  199. /* 
  200. Recursively restores correct priority queue order to a minimizing pq array 
  201.  
  202. @param pq_array a minimizing priority queue array 
  203. @param i index at which to start reordering 
  204. @param n number of elements in \a pq_array 
  205. */  
  206. static void restore_minpq_order( struct pq_node* pq_array, int i, int n )  
  207. {  
  208.     struct pq_node tmp;  
  209.     int l, r, min = i;  
  210.   
  211.     l = left( i );  
  212.     r = right( i );  
  213.     if( l < n )  
  214.         if( pq_array[l].key < pq_array[i].key )  
  215.             min = l;  
  216.     if( r < n )  
  217.         if( pq_array[r].key < pq_array[min].key )  
  218.             min = r;  
  219.   
  220.     if( min != i )  
  221.     {  
  222.         tmp = pq_array[min];  
  223.         pq_array[min] = pq_array[i];  
  224.         pq_array[i] = tmp;  
  225.         restore_minpq_order( pq_array, min, n );  
  226.     }  
  227. }  


5、sift.h

int sift_features(IplImage * img,structfeature ** feat)        

         找到所有的特征点放在feat当中并返回特征点的个数。

         特征点存储在strcutfeature * feat中。

draw_features(img,feat,featCount)

         绘制出所有的特征点

 

int _sift_features (IplImage *img, structfeature **feat, int intvls, double sigma, double contr_thr, int curv_thr, intimg_dbl, int descr_width, int descr_hist_bins)

        找到所有的特征点放在feat当中并返回特征点的个数。

         与intsift_features(IplImage * img,struct feature ** feat)的区别:sift_features实质上只是 调用了一下_sift_features,而在_sift_features用回使用很多用户设置的参数

 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.   
  40. /******************************* Defs and macros *****************************/  
  41.   
  42. /** default number of sampled intervals per octave */  
  43. #define SIFT_INTVLS 3  
  44.   
  45. /** default sigma for initial gaussian smoothing */  
  46. #define SIFT_SIGMA 1.6  
  47.   
  48. /** default threshold on keypoint contrast |D(x)| */  
  49. #define SIFT_CONTR_THR 0.04  
  50.   
  51. /** default threshold on keypoint ratio of principle curvatures */  
  52. #define SIFT_CURV_THR 10  
  53.   
  54. /** double image size before pyramid construction? */  
  55. #define SIFT_IMG_DBL 1  
  56.   
  57. /** default width of descriptor histogram array */  
  58. #define SIFT_DESCR_WIDTH 4  
  59.   
  60. /** default number of bins per histogram in descriptor array */  
  61. #define SIFT_DESCR_HIST_BINS 8  
  62.   
  63. /* assumed gaussian blur for input image */  
  64. #define SIFT_INIT_SIGMA 0.5  
  65.   
  66. /* width of border in which to ignore keypoints */  
  67. #define SIFT_IMG_BORDER 5  
  68.   
  69. /* maximum steps of keypoint interpolation before failure */  
  70. #define SIFT_MAX_INTERP_STEPS 5  
  71.   
  72. /* default number of bins in histogram for orientation assignment */  
  73. #define SIFT_ORI_HIST_BINS 36  
  74.   
  75. /* determines gaussian sigma for orientation assignment */  
  76. #define SIFT_ORI_SIG_FCTR 1.5  
  77.   
  78. /* determines the radius of the region used in orientation assignment */  
  79. #define SIFT_ORI_RADIUS 3.0 * SIFT_ORI_SIG_FCTR  
  80.   
  81. /* number of passes of orientation histogram smoothing */  
  82. #define SIFT_ORI_SMOOTH_PASSES 2  
  83.   
  84. /* orientation magnitude relative to max that results in new feature */  
  85. #define SIFT_ORI_PEAK_RATIO 0.8  
  86.   
  87. /* determines the size of a single descriptor orientation histogram */  
  88. #define SIFT_DESCR_SCL_FCTR 3.0  
  89.   
  90. /* threshold on magnitude of elements of descriptor vector */  
  91. #define SIFT_DESCR_MAG_THR 0.2  
  92.   
  93. /* factor used to convert floating-point descriptor to unsigned char */  
  94. #define SIFT_INT_DESCR_FCTR 512.0  
  95.   
  96. /* returns a feature's detection data */  
  97. #define feat_detection_data(f) ( (struct detection_data*)(f->feature_data) )  
  98.   
  99.   
  100. /*************************** Function Prototypes *****************************/  
  101.   
  102. /** 
  103. Finds SIFT features in an image using default parameter values.  All 
  104. detected features are stored in the array pointed to by \a feat. 
  105.  
  106. @param img the image in which to detect features 
  107. @param feat a pointer to an array in which to store detected features; memory 
  108.     for this array is allocated by this function and must be freed by the caller 
  109.     using free(*feat) 
  110.  
  111. @return Returns the number of features stored in \a feat or -1 on failure 
  112. @see _sift_features() 
  113. */  
  114. extern int sift_features( IplImage* img, struct feature** feat );  
  115.   
  116.   
  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. #endif  

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


  • 7
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
参考教材附录 B,常用 MATLAB 图像处理工具箱函数完成以下操作: (1) 利用“读图像文件 I/O”函数读入图像 football.jpg。 (2) 利用“读图像文件 I/O”的 imfinfo 函数了解图像文件的基本信息:主要包括 Filename (文件 名)、FileModDate (文件修改时间)、FileSize (文件尺寸)、Format (文件格式)、 FormatVersion (格式 版本)、Width (图像宽度)、Height (图像高度)、BitDepth (每个像 素的位深度)、ColorType (彩色类 型)、CodingMethod (编码方法)等。 (3) 利用“像素和统计处理”函数计算读入图像的二维相关系数(Corr2 函数),确定像素 颜色值 (impixel 函数),确定像素的平均值(mean2 函数),显示像素的信息(pixval 函数)、 计算像素的标准偏移(std2 函数)等。 要求:参照例题 1.1,对图像 J 加均值为 0、方差为 0.01 的高斯白噪声形成有噪图像 J1 , 即“ J1 = imnoise(J,'gaussian',0,0.01)”;求 J1 的像素总个数、图像灰度 的平均值、 标准差、J 和 J1 的互协方差和相关系数、J 和 K 的 互协方差和相关系数。 如果将方差加至 0.1,重新计算上述统计参数。 (4) 改变图像尺寸(imresize 函数)、旋转图像(imrotate 函数)、对图像进行裁剪(imcrop 函数)等,再对操作后的图 像进行统计。图 1.2 所示为裁剪后的显微图像。 原图像 I,按比例 SCALE 改变尺寸后的图像为 J。imresize 函数的调用格式是“J = imsize(I, SCALE)”,同理,图像 A 按 ANGLE 角度进行旋转得到图像 B 的语句为:“B = imrotate(A,ANGLE)”。 对于图 1 中的 SBS 改性沥青材料的显微图像,由于尺寸偏大,可以按水平和垂直 0.15 的比 例减低空间分辨率。对图像 J 进行裁剪的 MATLAB 函数是 imcrop,调用格式为“K= imcrop(J, RECT)”,其中 RECT 是 4 元素向量[XMIN YMIN WIDTH HEIGHT],XMIN、YMIN 为左下角坐标值, WIDTH、HEIGHT 分别是裁剪区域的宽度和高度。由于曝光不均匀,可能给图像处理和分析带 来困难。舍去暗的地区,采用图像裁剪参数 RECT= [0 181 363 283]得到光照较均匀的 左下角图像,裁剪结果如图 2 所示。 要求:参照例 2.1,将图像 I 分别放大和缩小 1.5 倍、旋转 30,再对操作后的图像进行统计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值