imgfeatures.c
上传用户:lwxipeng
上传日期:2022-05-16
资源大小:15982k
文件大小:14k
源码类别:

视频捕捉/采集

开发平台:

Visual C++

  1. /*
  2. Functions and structures for dealing with image features
  3. Copyright (C) 2006  Rob Hess <hess@eecs.oregonstate.edu>
  4. @version 1.1.1-20070330
  5. */
  6. #include "utils.h"
  7. #include "imgfeatures.h"
  8. #include <cxcore.h>
  9. #include <math.h>
  10. int import_oxfd_features( char*, struct feature** );
  11. int export_oxfd_features( char*, struct feature*, int );
  12. void draw_oxfd_features( IplImage*, struct feature*, int );
  13. void draw_oxfd_feature( IplImage*, struct feature*, CvScalar );
  14. int import_lowe_features( char*, struct feature** );
  15. int export_lowe_features( char*, struct feature*, int );
  16. void draw_lowe_features( IplImage*, struct feature*, int );
  17. void draw_lowe_feature( IplImage*, struct feature*, CvScalar );
  18. /*
  19. Reads image features from file.  The file should be formatted as from
  20. the code provided by the Visual Geometry Group at Oxford:
  21. @param filename location of a file containing image features
  22. @param type determines how features are input.  If a type is FEATURE_OXFD,
  23. the input file is treated as if it is from the code provided by the VGG
  24. at Oxford:
  25. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  26. If a type is FEATURE_LOWE, the input file is treated as if it is from
  27. David Lowe's SIFT code:
  28. http://www.cs.ubc.ca/~lowe/keypoints  
  29. @param features pointer to an array in which to store features
  30. @return Returns the number of features imported from filename or -1 on error
  31. */
  32. int import_features( char* filename, int type, struct feature** feat )
  33. {
  34. int n;
  35. switch( type )
  36. {
  37. case FEATURE_OXFD:
  38. n = import_oxfd_features( filename, feat );
  39. break;
  40. case FEATURE_LOWE:
  41. n = import_lowe_features( filename, feat );
  42. break;
  43. default:
  44. fprintf( stderr, "Warning: import_features(): unrecognized feature" 
  45. "type, %s, line %dn", __FILE__, __LINE__ );
  46. return -1;
  47. }
  48. if( n == -1 )
  49. fprintf( stderr, "Warning: unable to import features from %s,"
  50. " %s, line %dn", filename, __FILE__, __LINE__ );
  51. return n;
  52. }
  53. /*
  54. Exports a feature set to a file formatted depending on the type of
  55. features, as specified in the feature struct's type field.
  56. @param filename name of file to which to export features
  57. @param feat feature array
  58. @param n number of features 
  59. @return Returns 0 on success or 1 on error
  60. */
  61. int export_features( char* filename, struct feature* feat, int n )
  62. {
  63. int r, type;
  64. if( n <= 0  ||  ! feat )
  65. {
  66. fprintf( stderr, "Warning: no features to export, %s line %dn",
  67. __FILE__, __LINE__ );
  68. return 1;
  69. }
  70. type = feat[0].type;
  71. switch( type )
  72. {
  73. case FEATURE_OXFD:
  74. r = export_oxfd_features( filename, feat, n );
  75. break;
  76. case FEATURE_LOWE:
  77. r = export_lowe_features( filename, feat, n );
  78. break;
  79. default:
  80. fprintf( stderr, "Warning: export_features(): unrecognized feature" 
  81. "type, %s, line %dn", __FILE__, __LINE__ );
  82. return -1;
  83. }
  84. if( r )
  85. fprintf( stderr, "Warning: unable to export features to %s,"
  86. " %s, line %dn", filename, __FILE__, __LINE__ );
  87. return r;
  88. }
  89. /*
  90. Draws a set of features on an image
  91. @param img image on which to draw features
  92. @param feat array of Oxford-type features
  93. @param n number of features
  94. */
  95. void draw_features( IplImage* img, struct feature* feat, int n )
  96. {
  97. int type;
  98. if( n <= 0  ||  ! feat )
  99. {
  100. fprintf( stderr, "Warning: no features to draw, %s line %dn",
  101. __FILE__, __LINE__ );
  102. return;
  103. }
  104. type = feat[0].type;
  105. switch( type )
  106. {
  107. case FEATURE_OXFD:
  108. draw_oxfd_features( img, feat, n );
  109. break;
  110. case FEATURE_LOWE:
  111. draw_lowe_features( img, feat, n );
  112. break;
  113. default:
  114. fprintf( stderr, "Warning: draw_features(): unrecognized feature" 
  115. " type, %s, line %dn", __FILE__, __LINE__ );
  116. break;
  117. }
  118. }
  119. /*
  120. Calculates the squared Euclidian distance between two feature descriptors.
  121. @param f1 first feature
  122. @param f2 second feature
  123. @return Returns the squared Euclidian distance between the descriptors of
  124. f1 and f2.
  125. */
  126. double descr_dist_sq( struct feature* f1, struct feature* f2 )
  127. {
  128. double diff, dsq = 0;
  129. double* descr1, * descr2;
  130. int i, d;
  131. d = f1->d;
  132. if( f2->d != d )
  133. return DBL_MAX;
  134. descr1 = f1->descr;
  135. descr2 = f2->descr;
  136. for( i = 0; i < d; i++ )
  137. {
  138. diff = descr1[i] - descr2[i];
  139. dsq += diff*diff;
  140. }
  141. return dsq;
  142. }
  143. /***************************** Local Functions *******************************/
  144. /*
  145. Reads image features from file.  The file should be formatted as from
  146. the code provided by the Visual Geometry Group at Oxford:
  147. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  148. @param filename location of a file containing image features
  149. @param features pointer to an array in which to store features
  150. @return Returns the number of features imported from filename or -1 on error
  151. */
  152. int import_oxfd_features( char* filename, struct feature** features )
  153. {
  154. struct feature* f;
  155. int i, j, n, d;
  156. double x, y, a, b, c, dv;
  157. FILE* file;
  158. if( ! features )
  159. fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );
  160. if( ! ( file = fopen( filename, "r" ) ) )
  161. {
  162. fprintf( stderr, "Warning: error opening %s, %s, line %dn",
  163. filename, __FILE__, __LINE__ );
  164. return -1;
  165. }
  166. /* read dimension and number of features */
  167. if( fscanf( file, " %d %d ", &d, &n ) != 2 )
  168. {
  169. fprintf( stderr, "Warning: file read error, %s, line %dn",
  170. __FILE__, __LINE__ );
  171. return -1;
  172. }
  173. if( d > FEATURE_MAX_D )
  174. {
  175. fprintf( stderr, "Warning: descriptor too long, %s, line %dn",
  176. __FILE__, __LINE__ );
  177. return -1;
  178. }
  179. f = calloc( n, sizeof(struct feature) );
  180. for( i = 0; i < n; i++ )
  181. {
  182. /* read affine region parameters */
  183. if( fscanf( file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c ) != 5 )
  184. {
  185. fprintf( stderr, "Warning: error reading feature #%d, %s, line %dn",
  186. i+1, __FILE__, __LINE__ );
  187. free( f );
  188. return -1;
  189. }
  190. f[i].img_pt.x = f[i].x = x;
  191. f[i].img_pt.y = f[i].y = y;
  192. f[i].a = a;
  193. f[i].b = b;
  194. f[i].c = c;
  195. f[i].d = d;
  196. f[i].type = FEATURE_OXFD;
  197. /* read descriptor */
  198. for( j = 0; j < d; j++ )
  199. {
  200. if( ! fscanf( file, " %lf ", &dv ) )
  201. {
  202. fprintf( stderr, "Warning: error reading feature descriptor" 
  203. " #%d, %s, line %dn", i+1, __FILE__, __LINE__ );
  204. free( f );
  205. return -1;
  206. }
  207. f[i].descr[j] = dv;
  208. }
  209. f[i].scl = f[i].ori = 0;
  210. f[i].pclass = 0;
  211. f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
  212. f[i].mdl_pt.x = f[i].mdl_pt.y = -1;
  213. f[i].feature_data = NULL;
  214. }
  215. if( fclose(file) )
  216. {
  217. fprintf( stderr, "Warning: file close error, %s, line %dn",
  218. __FILE__, __LINE__ );
  219. free( f );
  220. return -1;
  221. }
  222. *features = f;
  223. return n;
  224. }
  225. /*
  226. Exports a feature set to a file formatted as one from the code provided
  227. by the Visual Geometry Group at Oxford:
  228. http://www.robots.ox.ac.uk:5000/~vgg/research/affine/index.html
  229. @param filename name of file to which to export features
  230. @param feat feature array
  231. @param n number of features
  232. @return Returns 0 on success or 1 on error
  233. */
  234. int export_oxfd_features( char* filename, struct feature* feat, int n )
  235. {
  236. FILE* file;
  237. int i, j, d;
  238. if( n <= 0 )
  239. {
  240. fprintf( stderr, "Warning: feature count %d, %s, line %sn",
  241. n, __FILE__, __LINE__ );
  242. return 1;
  243. }
  244. if( ! ( file = fopen( filename, "w" ) ) )
  245. {
  246. fprintf( stderr, "Warning: error opening %s, %s, line %dn",
  247. filename, __FILE__, __LINE__ );
  248. return 1;
  249. }
  250. d = feat[0].d;
  251. fprintf( file, "%dn%dn", d, n );
  252. for( i = 0; i < n; i++ )
  253. {
  254. fprintf( file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,
  255. feat[i].b, feat[i].c );
  256. for( j = 0; j < d; j++ )
  257. fprintf( file, " %f", feat[i].descr[j] );
  258. fprintf( file, "n" );
  259. }
  260. if( fclose(file) )
  261. {
  262. fprintf( stderr, "Warning: file close error, %s, line %dn",
  263. __FILE__, __LINE__ );
  264. return 1;
  265. }
  266. return 0;
  267. }
  268. /*
  269. Draws Oxford-type affine features
  270. @param img image on which to draw features
  271. @param feat array of Oxford-type features
  272. @param n number of features
  273. */
  274. void draw_oxfd_features( IplImage* img, struct feature* feat, int n )
  275. {
  276. CvScalar color = CV_RGB( 255, 255, 255 );
  277. int i;
  278. if( img-> nChannels > 1 )
  279. color = FEATURE_OXFD_COLOR;
  280. for( i = 0; i < n; i++ )
  281. draw_oxfd_feature( img, feat + i, color );
  282. }
  283. /*
  284. Draws a single Oxford-type feature
  285. @param img image on which to draw
  286. @param feat feature to be drawn
  287. @param color color in which to draw
  288. */
  289. void draw_oxfd_feature( IplImage* img, struct feature* feat, CvScalar color )
  290. {
  291. double m[4] = { feat->a, feat->b, feat->b, feat->c };
  292. double v[4] = { 0 };
  293. double e[2] = { 0 };
  294. CvMat M, V, E;
  295. double alpha, l1, l2;
  296. /* compute axes and orientation of ellipse surrounding affine region */
  297. cvInitMatHeader( &M, 2, 2, CV_64FC1, m, CV_AUTOSTEP );
  298. cvInitMatHeader( &V, 2, 2, CV_64FC1, v, CV_AUTOSTEP );
  299. cvInitMatHeader( &E, 2, 1, CV_64FC1, e, CV_AUTOSTEP );
  300. cvEigenVV( &M, &V, &E, 0, -1,-1);
  301. l1 = 1 / sqrt( e[1] );
  302. l2 = 1 / sqrt( e[0] );
  303. alpha = -atan2( v[1], v[0] );
  304. alpha *= 180 / CV_PI;
  305. cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,
  306. 0, 360, CV_RGB(0,0,0), 3, 8, 0 );
  307. cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,
  308. 0, 360, color, 1, 8, 0 );
  309. cvLine( img, cvPoint( feat->x+2, feat->y ), cvPoint( feat->x-2, feat->y ),
  310. color, 1, 8, 0 );
  311. cvLine( img, cvPoint( feat->x, feat->y+2 ), cvPoint( feat->x, feat->y-2 ),
  312. color, 1, 8, 0 );
  313. }
  314. /*
  315. Reads image features from file.  The file should be formatted as from
  316. the code provided by David Lowe:
  317. http://www.cs.ubc.ca/~lowe/keypoints/
  318. @param filename location of a file containing image features
  319. @param features pointer to an array in which to store features
  320. @return Returns the number of features imported from filename or -1 on error
  321. */
  322. int import_lowe_features( char* filename, struct feature** features )
  323. {
  324. struct feature* f;
  325. int i, j, n, d;
  326. double x, y, s, o, dv;
  327. FILE* file;
  328. if( ! features )
  329. fatal_error( "NULL pointer error, %s, line %d",  __FILE__, __LINE__ );
  330. if( ! ( file = fopen( filename, "r" ) ) )
  331. {
  332. fprintf( stderr, "Warning: error opening %s, %s, line %dn",
  333. filename, __FILE__, __LINE__ );
  334. return -1;
  335. }
  336. /* read number of features and dimension */
  337. if( fscanf( file, " %d %d ", &n, &d ) != 2 )
  338. {
  339. fprintf( stderr, "Warning: file read error, %s, line %dn",
  340. __FILE__, __LINE__ );
  341. return -1;
  342. }
  343. if( d > FEATURE_MAX_D )
  344. {
  345. fprintf( stderr, "Warning: descriptor too long, %s, line %dn",
  346. __FILE__, __LINE__ );
  347. return -1;
  348. }
  349. f = calloc( n, sizeof(struct feature) );
  350. for( i = 0; i < n; i++ )
  351. {
  352. /* read affine region parameters */
  353. if( fscanf( file, " %lf %lf %lf %lf ", &y, &x, &s, &o ) != 4 )
  354. {
  355. fprintf( stderr, "Warning: error reading feature #%d, %s, line %dn",
  356. i+1, __FILE__, __LINE__ );
  357. free( f );
  358. return -1;
  359. }
  360. f[i].img_pt.x = f[i].x = x;
  361. f[i].img_pt.y = f[i].y = y;
  362. f[i].scl = s;
  363. f[i].ori = o;
  364. f[i].d = d;
  365. f[i].type = FEATURE_LOWE;
  366. /* read descriptor */
  367. for( j = 0; j < d; j++ )
  368. {
  369. if( ! fscanf( file, " %lf ", &dv ) )
  370. {
  371. fprintf( stderr, "Warning: error reading feature descriptor" 
  372. " #%d, %s, line %dn", i+1, __FILE__, __LINE__ );
  373. free( f );
  374. return -1;
  375. }
  376. f[i].descr[j] = dv;
  377. }
  378. f[i].a = f[i].b = f[i].c = 0;
  379. f[i].pclass = 0;
  380. f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
  381. f[i].mdl_pt.x = f[i].mdl_pt.y = -1;
  382. }
  383. if( fclose(file) )
  384. {
  385. fprintf( stderr, "Warning: file close error, %s, line %dn",
  386. __FILE__, __LINE__ );
  387. free( f );
  388. return -1;
  389. }
  390. *features = f;
  391. return n;
  392. }
  393. /*
  394. Exports a feature set to a file formatted as one from the code provided
  395. by David Lowe:
  396. http://www.cs.ubc.ca/~lowe/keypoints/
  397. @param filename name of file to which to export features
  398. @param feat feature array
  399. @param n number of features
  400. @return Returns 0 on success or 1 on error
  401. */
  402. int export_lowe_features( char* filename, struct feature* feat, int n )
  403. {
  404. FILE* file;
  405. int i, j, d;
  406. if( n <= 0 )
  407. {
  408. fprintf( stderr, "Warning: feature count %d, %s, line %sn",
  409. n, __FILE__, __LINE__ );
  410. return 1;
  411. }
  412. if( ! ( file = fopen( filename, "w" ) ) )
  413. {
  414. fprintf( stderr, "Warning: error opening %s, %s, line %dn",
  415. filename, __FILE__, __LINE__ );
  416. return 1;
  417. }
  418. d = feat[0].d;
  419. fprintf( file, "%d %dn", n, d );
  420. for( i = 0; i < n; i++ )
  421. {
  422. fprintf( file, "%f %f %f %f", feat[i].y, feat[i].x,
  423. feat[i].scl, feat[i].ori );
  424. for( j = 0; j < d; j++ )
  425. {
  426. /* write 20 descriptor values per line */
  427. if( j % 20 == 0 )
  428. fprintf( file, "n" );
  429. fprintf( file, " %d", (int)(feat[i].descr[j]) );
  430. }
  431. fprintf( file, "n" );
  432. }
  433. if( fclose(file) )
  434. {
  435. fprintf( stderr, "Warning: file close error, %s, line %dn",
  436. __FILE__, __LINE__ );
  437. return 1;
  438. }
  439. return 0;
  440. }
  441. /*
  442. Draws Lowe-type features
  443. @param img image on which to draw features
  444. @param feat array of Oxford-type features
  445. @param n number of features
  446. */
  447. void draw_lowe_features( IplImage* img, struct feature* feat, int n )
  448. {
  449. CvScalar color = CV_RGB( 255, 255, 255 );
  450. int i;
  451. if( img-> nChannels > 1 )
  452. color = FEATURE_LOWE_COLOR;
  453. for( i = 0; i < n; i++ )
  454. draw_lowe_feature( img, feat + i, color );
  455. }
  456. /*
  457. Draws a single Lowe-type feature
  458. @param img image on which to draw
  459. @param feat feature to be drawn
  460. @param color color in which to draw
  461. */
  462. void draw_lowe_feature( IplImage* img, struct feature* feat, CvScalar color )
  463. {
  464. int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;
  465. double scl, ori;
  466. double scale = 5.0;
  467. double hscale = 0.75;
  468. CvPoint start, end, h1, h2;
  469. /* compute points for an arrow scaled and rotated by feat's scl and ori */
  470. start_x = cvRound( feat->x );
  471. start_y = cvRound( feat->y );
  472. scl = feat->scl;
  473. ori = feat->ori;
  474. len = cvRound( scl * scale );
  475. hlen = cvRound( scl * hscale );
  476. blen = len - hlen;
  477. end_x = cvRound( len *  cos( ori ) ) + start_x;
  478. end_y = cvRound( len * -sin( ori ) ) + start_y;
  479. h1_x = cvRound( blen *  cos( ori + CV_PI / 18.0 ) ) + start_x;
  480. h1_y = cvRound( blen * -sin( ori + CV_PI / 18.0 ) ) + start_y;
  481. h2_x = cvRound( blen *  cos( ori - CV_PI / 18.0 ) ) + start_x;
  482. h2_y = cvRound( blen * -sin( ori - CV_PI / 18.0 ) ) + start_y;
  483. start = cvPoint( start_x, start_y );
  484. end = cvPoint( end_x, end_y );
  485. h1 = cvPoint( h1_x, h1_y );
  486. h2 = cvPoint( h2_x, h2_y );
  487. cvLine( img, start, end, color, 1, 8, 0 );
  488. cvLine( img, end, h1, color, 1, 8, 0 );
  489. cvLine( img, end, h2, color, 1, 8, 0 );
  490. }