00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "utils.h"
00010 #include "imgfeatures.h"
00011
00012 #include <cxcore.h>
00013
00014 int import_oxfd_features( char*, struct feature** );
00015 int export_oxfd_features( char*, struct feature*, int );
00016 void draw_oxfd_features( IplImage*, struct feature*, int );
00017 void draw_oxfd_feature( IplImage*, struct feature*, CvScalar );
00018
00019 int import_lowe_features( char*, struct feature** );
00020 int export_lowe_features( char*, struct feature*, int );
00021 void draw_lowe_features( IplImage*, struct feature*, int );
00022 void draw_lowe_feature( IplImage*, struct feature*, CvScalar );
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 int import_features( char* filename, int type, struct feature** feat )
00046 {
00047 int n;
00048
00049 switch( type )
00050 {
00051 case FEATURE_OXFD:
00052 n = import_oxfd_features( filename, feat );
00053 break;
00054 case FEATURE_LOWE:
00055 n = import_lowe_features( filename, feat );
00056 break;
00057 default:
00058 fprintf( stderr, "Warning: import_features(): unrecognized feature" \
00059 "type, %s, line %d\n", __FILE__, __LINE__ );
00060 return -1;
00061 }
00062
00063 if( n == -1 )
00064 fprintf( stderr, "Warning: unable to import features from %s," \
00065 " %s, line %d\n", filename, __FILE__, __LINE__ );
00066 return n;
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 int export_features( char* filename, struct feature* feat, int n )
00082 {
00083 int r, type;
00084
00085 if( n <= 0 || ! feat )
00086 {
00087 fprintf( stderr, "Warning: no features to export, %s line %d\n",
00088 __FILE__, __LINE__ );
00089 return 1;
00090 }
00091 type = feat[0].type;
00092 switch( type )
00093 {
00094 case FEATURE_OXFD:
00095 r = export_oxfd_features( filename, feat, n );
00096 break;
00097 case FEATURE_LOWE:
00098 r = export_lowe_features( filename, feat, n );
00099 break;
00100 default:
00101 fprintf( stderr, "Warning: export_features(): unrecognized feature" \
00102 "type, %s, line %d\n", __FILE__, __LINE__ );
00103 return -1;
00104 }
00105
00106 if( r )
00107 fprintf( stderr, "Warning: unable to export features to %s," \
00108 " %s, line %d\n", filename, __FILE__, __LINE__ );
00109 return r;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 void draw_features( IplImage* img, struct feature* feat, int n )
00121 {
00122 int type;
00123
00124 if( n <= 0 || ! feat )
00125 {
00126 fprintf( stderr, "Warning: no features to draw, %s line %d\n",
00127 __FILE__, __LINE__ );
00128 return;
00129 }
00130 type = feat[0].type;
00131 switch( type )
00132 {
00133 case FEATURE_OXFD:
00134 draw_oxfd_features( img, feat, n );
00135 break;
00136 case FEATURE_LOWE:
00137 draw_lowe_features( img, feat, n );
00138 break;
00139 default:
00140 fprintf( stderr, "Warning: draw_features(): unrecognized feature" \
00141 " type, %s, line %d\n", __FILE__, __LINE__ );
00142 break;
00143 }
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157 double descr_dist_sq( struct feature* f1, struct feature* f2 )
00158 {
00159 double diff, dsq = 0;
00160 double* descr1, * descr2;
00161 int i, d;
00162
00163 d = f1->d;
00164 if( f2->d != d )
00165 return DBL_MAX;
00166 descr1 = f1->descr;
00167 descr2 = f2->descr;
00168
00169 for( i = 0; i < d; i++ )
00170 {
00171 diff = descr1[i] - descr2[i];
00172 dsq += diff*diff;
00173 }
00174 return dsq;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 int import_oxfd_features( char* filename, struct feature** features )
00194 {
00195 struct feature* f;
00196 int i, j, n, d;
00197 double x, y, a, b, c, dv;
00198 FILE* file;
00199
00200 if( ! features )
00201 fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ );
00202 if( ! ( file = fopen( filename, "r" ) ) )
00203 {
00204 fprintf( stderr, "Warning: error opening %s, %s, line %d\n",
00205 filename, __FILE__, __LINE__ );
00206 return -1;
00207 }
00208
00209
00210 if( fscanf( file, " %d %d ", &d, &n ) != 2 )
00211 {
00212 fprintf( stderr, "Warning: file read error, %s, line %d\n",
00213 __FILE__, __LINE__ );
00214 return -1;
00215 }
00216 if( d > FEATURE_MAX_D )
00217 {
00218 fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",
00219 __FILE__, __LINE__ );
00220 return -1;
00221 }
00222
00223
00224 f = (struct feature *) calloc( n, sizeof(struct feature) );
00225 for( i = 0; i < n; i++ )
00226 {
00227
00228 if( fscanf( file, " %lf %lf %lf %lf %lf ", &x, &y, &a, &b, &c ) != 5 )
00229 {
00230 fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",
00231 i+1, __FILE__, __LINE__ );
00232 free( f );
00233 return -1;
00234 }
00235 f[i].img_pt.x = f[i].x = x;
00236 f[i].img_pt.y = f[i].y = y;
00237 f[i].a = a;
00238 f[i].b = b;
00239 f[i].c = c;
00240 f[i].d = d;
00241 f[i].type = FEATURE_OXFD;
00242
00243
00244 for( j = 0; j < d; j++ )
00245 {
00246 if( ! fscanf( file, " %lf ", &dv ) )
00247 {
00248 fprintf( stderr, "Warning: error reading feature descriptor" \
00249 " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );
00250 free( f );
00251 return -1;
00252 }
00253 f[i].descr[j] = dv;
00254 }
00255
00256 f[i].scl = f[i].ori = 0;
00257 f[i].category = 0;
00258 f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
00259 f[i].mdl_pt.x = f[i].mdl_pt.y = -1;
00260 f[i].feature_data = NULL;
00261 }
00262
00263 if( fclose(file) )
00264 {
00265 fprintf( stderr, "Warning: file close error, %s, line %d\n",
00266 __FILE__, __LINE__ );
00267 free( f );
00268 return -1;
00269 }
00270
00271 *features = f;
00272 return n;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int export_oxfd_features( char* filename, struct feature* feat, int n )
00291 {
00292 FILE* file;
00293 int i, j, d;
00294
00295 if( n <= 0 )
00296 {
00297 fprintf( stderr, "Warning: feature count %d, %s, line %s\n",
00298 n, __FILE__, __LINE__ );
00299 return 1;
00300 }
00301 if( ! ( file = fopen( filename, "w" ) ) )
00302 {
00303 fprintf( stderr, "Warning: error opening %s, %s, line %d\n",
00304 filename, __FILE__, __LINE__ );
00305 return 1;
00306 }
00307
00308 d = feat[0].d;
00309 fprintf( file, "%d\n%d\n", d, n );
00310 for( i = 0; i < n; i++ )
00311 {
00312 fprintf( file, "%f %f %f %f %f", feat[i].x, feat[i].y, feat[i].a,
00313 feat[i].b, feat[i].c );
00314 for( j = 0; j < d; j++ )
00315 fprintf( file, " %f", feat[i].descr[j] );
00316 fprintf( file, "\n" );
00317 }
00318
00319 if( fclose(file) )
00320 {
00321 fprintf( stderr, "Warning: file close error, %s, line %d\n",
00322 __FILE__, __LINE__ );
00323 return 1;
00324 }
00325 return 0;
00326 }
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 void draw_oxfd_features( IplImage* img, struct feature* feat, int n )
00338 {
00339 CvScalar color = CV_RGB( 255, 255, 255 );
00340 int i;
00341
00342 if( img-> nChannels > 1 )
00343 color = FEATURE_OXFD_COLOR;
00344 for( i = 0; i < n; i++ )
00345 draw_oxfd_feature( img, feat + i, color );
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 void draw_oxfd_feature( IplImage* img, struct feature* feat, CvScalar color )
00358 {
00359 double m[4] = { feat->a, feat->b, feat->b, feat->c };
00360 double v[4] = { 0 };
00361 double e[2] = { 0 };
00362 CvMat M, V, E;
00363 double alpha, l1, l2;
00364
00365
00366 cvInitMatHeader( &M, 2, 2, CV_64FC1, m, CV_AUTOSTEP );
00367 cvInitMatHeader( &V, 2, 2, CV_64FC1, v, CV_AUTOSTEP );
00368 cvInitMatHeader( &E, 2, 1, CV_64FC1, e, CV_AUTOSTEP );
00369 cvEigenVV( &M, &V, &E, DBL_EPSILON );
00370 l1 = 1 / sqrt( e[1] );
00371 l2 = 1 / sqrt( e[0] );
00372 alpha = -atan2( v[1], v[0] );
00373 alpha *= 180 / M_PI;
00374
00375 cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,
00376 0, 360, CV_RGB(0,0,0), 3, 8, 0 );
00377 cvEllipse( img, cvPoint( feat->x, feat->y ), cvSize( l2, l1 ), alpha,
00378 0, 360, color, 1, 8, 0 );
00379 cvLine( img, cvPoint( feat->x+2, feat->y ), cvPoint( feat->x-2, feat->y ),
00380 color, 1, 8, 0 );
00381 cvLine( img, cvPoint( feat->x, feat->y+2 ), cvPoint( feat->x, feat->y-2 ),
00382 color, 1, 8, 0 );
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 int import_lowe_features( char* filename, struct feature** features )
00399 {
00400 struct feature* f;
00401 int i, j, n, d;
00402 double x, y, s, o, dv;
00403 FILE* file;
00404
00405 if( ! features )
00406 fatal_error( "NULL pointer error, %s, line %d", __FILE__, __LINE__ );
00407 if( ! ( file = fopen( filename, "r" ) ) )
00408 {
00409 fprintf( stderr, "Warning: error opening %s, %s, line %d\n",
00410 filename, __FILE__, __LINE__ );
00411 return -1;
00412 }
00413
00414
00415 if( fscanf( file, " %d %d ", &n, &d ) != 2 )
00416 {
00417 fprintf( stderr, "Warning: file read error, %s, line %d\n",
00418 __FILE__, __LINE__ );
00419 return -1;
00420 }
00421 if( d > FEATURE_MAX_D )
00422 {
00423 fprintf( stderr, "Warning: descriptor too long, %s, line %d\n",
00424 __FILE__, __LINE__ );
00425 return -1;
00426 }
00427
00428 f = (struct feature *) calloc( n, sizeof(struct feature) );
00429 for( i = 0; i < n; i++ )
00430 {
00431
00432 if( fscanf( file, " %lf %lf %lf %lf ", &y, &x, &s, &o ) != 4 )
00433 {
00434 fprintf( stderr, "Warning: error reading feature #%d, %s, line %d\n",
00435 i+1, __FILE__, __LINE__ );
00436 free( f );
00437 return -1;
00438 }
00439 f[i].img_pt.x = f[i].x = x;
00440 f[i].img_pt.y = f[i].y = y;
00441 f[i].scl = s;
00442 f[i].ori = o;
00443 f[i].d = d;
00444 f[i].type = FEATURE_LOWE;
00445
00446
00447 for( j = 0; j < d; j++ )
00448 {
00449 if( ! fscanf( file, " %lf ", &dv ) )
00450 {
00451 fprintf( stderr, "Warning: error reading feature descriptor" \
00452 " #%d, %s, line %d\n", i+1, __FILE__, __LINE__ );
00453 free( f );
00454 return -1;
00455 }
00456 f[i].descr[j] = dv;
00457 }
00458
00459 f[i].a = f[i].b = f[i].c = 0;
00460 f[i].category = 0;
00461 f[i].fwd_match = f[i].bck_match = f[i].mdl_match = NULL;
00462 f[i].mdl_pt.x = f[i].mdl_pt.y = -1;
00463 f[i].feature_data = NULL;
00464 }
00465
00466 if( fclose(file) )
00467 {
00468 fprintf( stderr, "Warning: file close error, %s, line %d\n",
00469 __FILE__, __LINE__ );
00470 free( f );
00471 return -1;
00472 }
00473
00474 *features = f;
00475 return n;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 int export_lowe_features( char* filename, struct feature* feat, int n )
00493 {
00494 FILE* file;
00495 int i, j, d;
00496
00497 if( n <= 0 )
00498 {
00499 fprintf( stderr, "Warning: feature count %d, %s, line %s\n",
00500 n, __FILE__, __LINE__ );
00501 return 1;
00502 }
00503 if( ! ( file = fopen( filename, "w" ) ) )
00504 {
00505 fprintf( stderr, "Warning: error opening %s, %s, line %d\n",
00506 filename, __FILE__, __LINE__ );
00507 return 1;
00508 }
00509
00510 d = feat[0].d;
00511 fprintf( file, "%d %d\n", n, d );
00512 for( i = 0; i < n; i++ )
00513 {
00514 fprintf( file, "%f %f %f %f", feat[i].y, feat[i].x,
00515 feat[i].scl, feat[i].ori );
00516 for( j = 0; j < d; j++ )
00517 {
00518
00519 if( j % 20 == 0 )
00520 fprintf( file, "\n" );
00521 fprintf( file, " %d", (int)(feat[i].descr[j]) );
00522 }
00523 fprintf( file, "\n" );
00524 }
00525
00526 if( fclose(file) )
00527 {
00528 fprintf( stderr, "Warning: file close error, %s, line %d\n",
00529 __FILE__, __LINE__ );
00530 return 1;
00531 }
00532 return 0;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 void draw_lowe_features( IplImage* img, struct feature* feat, int n )
00544 {
00545 CvScalar color = CV_RGB( 255, 255, 255 );
00546 int i;
00547
00548 if( img-> nChannels > 1 )
00549 color = FEATURE_LOWE_COLOR;
00550 for( i = 0; i < n; i++ )
00551 draw_lowe_feature( img, feat + i, color );
00552 }
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 void draw_lowe_feature( IplImage* img, struct feature* feat, CvScalar color )
00564 {
00565 int len, hlen, blen, start_x, start_y, end_x, end_y, h1_x, h1_y, h2_x, h2_y;
00566 double scl, ori;
00567 double scale = 5.0;
00568 double hscale = 0.75;
00569 CvPoint start, end, h1, h2;
00570
00571
00572 start_x = cvRound( feat->x );
00573 start_y = cvRound( feat->y );
00574 scl = feat->scl;
00575 ori = feat->ori;
00576 len = cvRound( scl * scale );
00577 hlen = cvRound( scl * hscale );
00578 blen = len - hlen;
00579 end_x = cvRound( len * cos( ori ) ) + start_x;
00580 end_y = cvRound( len * -sin( ori ) ) + start_y;
00581 h1_x = cvRound( blen * cos( ori + CV_PI / 18.0 ) ) + start_x;
00582 h1_y = cvRound( blen * -sin( ori + CV_PI / 18.0 ) ) + start_y;
00583 h2_x = cvRound( blen * cos( ori - CV_PI / 18.0 ) ) + start_x;
00584 h2_y = cvRound( blen * -sin( ori - CV_PI / 18.0 ) ) + start_y;
00585 start = cvPoint( start_x, start_y );
00586 end = cvPoint( end_x, end_y );
00587 h1 = cvPoint( h1_x, h1_y );
00588 h2 = cvPoint( h2_x, h2_y );
00589
00590 cvLine( img, start, end, color, 1, 8, 0 );
00591 cvLine( img, end, h1, color, 1, 8, 0 );
00592 cvLine( img, end, h2, color, 1, 8, 0 );
00593 }
00594
00595