00001
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define VL_SIFT_DRIVER_VERSION 0.1
00016
00017 #include "generic-driver.h"
00018
00019 #include <vl/generic.h>
00020 #include <vl/stringop.h>
00021 #include <vl/pgm.h>
00022 #include <vl/sift.h>
00023 #include <vl/getopt_long.h>
00024
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <assert.h>
00028
00029
00030
00031 char const help_message [] =
00032 "Usage: %s [options] files ...\n"
00033 "\n"
00034 "Options include:\n"
00035 " --verbose -v Be verbose\n"
00036 " --help -h Print this help message\n"
00037 " --output -o Specify output file\n"
00038 " --frames Specify frames file\n"
00039 " --descriptors Specify descriptors file\n"
00040 " --meta Specify meta file\n"
00041 " --gss Specify Gaussian scale space files\n"
00042 " --octaves -O Number of octaves\n"
00043 " --levels -S Number of levels per octave\n"
00044 " --first-octave Index of the first octave\n"
00045 " --edge-thresh Specify the edge threshold\n"
00046 " --peak-thresh Specift the peak threshold\n"
00047 " --magnif Specify the magnification factor\n"
00048 " --read-frames Specify a file from which to read frames\n"
00049 " --orientations Force the computation of the orientations\n"
00050 "\n" ;
00051
00052
00053
00054 enum {
00055 opt_meta = 1000,
00056 opt_frames,
00057 opt_descriptors,
00058 opt_gss,
00059 opt_first_octave,
00060 opt_edge_thresh,
00061 opt_peak_thresh,
00062 opt_magnif,
00063 opt_read_frames,
00064 opt_orientations
00065 } ;
00066
00067
00068 char const opts [] = "vhO:S:o:" ;
00069
00070
00071 struct option const longopts [] = {
00072 { "verbose", no_argument, 0, 'v' },
00073 { "help", no_argument, 0, 'h' },
00074 { "octaves", required_argument, 0, 'O' },
00075 { "levels", required_argument, 0, 'S' },
00076 { "output", required_argument, 0, 'o' },
00077 { "meta", optional_argument, 0, opt_meta },
00078 { "frames", optional_argument, 0, opt_frames },
00079 { "descriptors", optional_argument, 0, opt_descriptors },
00080 { "gss", optional_argument, 0, opt_gss },
00081 { "first-octave", required_argument, 0, opt_first_octave },
00082 { "edge-thresh", required_argument, 0, opt_edge_thresh },
00083 { "peak-thresh", required_argument, 0, opt_peak_thresh },
00084 { "magnif", required_argument, 0, opt_magnif },
00085 { "read-frames", required_argument, 0, opt_read_frames },
00086 { "orientations", no_argument, 0, opt_orientations },
00087 { 0, 0, 0, 0 }
00088 } ;
00089
00090
00094 static int
00095 save_gss (VlSiftFilt * filt, VlFileMeta * fm, const char * basename,
00096 int verbose)
00097 {
00098 char tmp [1024] ;
00099 int S = filt -> S ;
00100 int i ;
00101 int s, err = 0 ;
00102 int w, h ;
00103 int o = filt -> o_cur ;
00104 VlPgmImage pim ;
00105 vl_uint8 *buffer = 0 ;
00106 vl_size q ;
00107
00108 if (! fm -> active) {
00109 return VL_ERR_OK ;
00110 }
00111
00112 w = vl_sift_get_octave_width (filt) ;
00113 h = vl_sift_get_octave_height (filt) ;
00114
00115 pim.width = w ;
00116 pim.height = h ;
00117 pim.max_value = 255 ;
00118 pim.is_raw = 1 ;
00119
00120 buffer = malloc (sizeof(vl_uint8) * w * h) ;
00121 if (! buffer) {
00122 err = VL_ERR_ALLOC ;
00123 goto save_gss_quit ;
00124 }
00125
00126 q = vl_string_copy (tmp, sizeof(tmp), basename) ;
00127 if (q >= sizeof(tmp)) {
00128 err = VL_ERR_OVERFLOW ;
00129 goto save_gss_quit ;
00130 }
00131
00132 for (s = 0 ; s < S ; ++s) {
00133 vl_sift_pix * pt = vl_sift_get_octave (filt, s) ;
00134
00135
00136 for (i = 0 ; i < w * h ; ++i) {
00137 buffer [i] = (vl_uint8) pt [i] ;
00138 }
00139
00140
00141 snprintf(tmp + q, sizeof(tmp) - q, "_%02d_%03d", o, s) ;
00142
00143 err = vl_file_meta_open (fm, tmp, "wb") ;
00144 if (err) goto save_gss_quit ;
00145
00146 err = vl_pgm_insert (fm -> file, &pim, buffer) ;
00147 if (err) goto save_gss_quit ;
00148
00149 if (verbose) {
00150 printf("sift: saved gss level to '%s'\n", fm -> name) ;
00151 }
00152
00153 vl_file_meta_close (fm) ;
00154 }
00155
00156 save_gss_quit : ;
00157 if (buffer) free (buffer) ;
00158 vl_file_meta_close (fm) ;
00159 return err ;
00160 }
00161
00162
00166 int
00167 korder (void const* a, void const* b) {
00168 double x = ((double*) a) [2] - ((double*) b) [2] ;
00169 if (x < 0) return -1 ;
00170 if (x > 0) return +1 ;
00171 return 0 ;
00172 }
00173
00174
00177 int
00178 main(int argc, char **argv)
00179 {
00180
00181 double edge_thresh = -1 ;
00182 double peak_thresh = -1 ;
00183 double magnif = -1 ;
00184 int O = -1, S = 3, omin = -1 ;
00185
00186 vl_bool err = VL_ERR_OK ;
00187 char err_msg [1024] ;
00188 int n ;
00189 int exit_code = 0 ;
00190 int verbose = 0 ;
00191 vl_bool force_output = 0 ;
00192 vl_bool force_orientations = 0 ;
00193
00194 VlFileMeta out = {1, "%.sift", VL_PROT_ASCII, "", 0} ;
00195 VlFileMeta frm = {0, "%.frame", VL_PROT_ASCII, "", 0} ;
00196 VlFileMeta dsc = {0, "%.descr", VL_PROT_ASCII, "", 0} ;
00197 VlFileMeta met = {0, "%.meta", VL_PROT_ASCII, "", 0} ;
00198 VlFileMeta gss = {0, "%.pgm", VL_PROT_ASCII, "", 0} ;
00199 VlFileMeta ifr = {0, "%.frame", VL_PROT_ASCII, "", 0} ;
00200
00201 #define ERRF(msg, arg) { \
00202 err = VL_ERR_BAD_ARG ; \
00203 snprintf(err_msg, sizeof(err_msg), msg, arg) ; \
00204 break ; \
00205 }
00206
00207 #define ERR(msg) { \
00208 err = VL_ERR_BAD_ARG ; \
00209 snprintf(err_msg, sizeof(err_msg), msg) ; \
00210 break ; \
00211 }
00212
00213
00214
00215
00216
00217 while (!err) {
00218 int ch = getopt_long(argc, argv, opts, longopts, 0) ;
00219
00220
00221 if (ch == -1 && argc - optind == 0)
00222 ch = 'h';
00223
00224
00225 if (ch == -1) break;
00226
00227 switch (ch) {
00228
00229 case '?' :
00230
00231 ERRF("Invalid option '%s'.", argv [optind - 1]) ;
00232 break ;
00233
00234 case ':' :
00235
00236 ERRF("Missing mandatory argument for option '%s'.",
00237 argv [optind - 1]) ;
00238 break ;
00239
00240 case 'h' :
00241
00242 printf (help_message, argv [0]) ;
00243 printf ("SIFT filespec: `%s'\n", out.pattern) ;
00244 printf ("Frames filespec: `%s'\n", frm.pattern) ;
00245 printf ("Descriptors filespec: `%s'\n", dsc.pattern) ;
00246 printf ("Meta filespec: `%s'\n", met.pattern) ;
00247 printf ("GSS filespec: '%s'\n", gss.pattern) ;
00248 printf ("Read frames filespec: '%s'\n", ifr.pattern) ;
00249 printf ("Version: driver %s; libvl %s\n",
00250 VL_XSTRINGIFY(VL_SIFT_DRIVER_VERSION),
00251 vl_get_version_string()) ;
00252 exit (0) ;
00253 break ;
00254
00255 case 'v' :
00256
00257 ++ verbose ;
00258 break ;
00259
00260 case 'o' :
00261
00262 err = vl_file_meta_parse (&out, optarg) ;
00263 if (err)
00264 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00265 force_output = 1 ;
00266 break ;
00267
00268 case opt_frames :
00269
00270 err = vl_file_meta_parse (&frm, optarg) ;
00271 if (err)
00272 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00273 break ;
00274
00275 case opt_descriptors :
00276
00277 err = vl_file_meta_parse (&dsc, optarg) ;
00278 if (err)
00279 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00280 break;
00281
00282 case opt_meta :
00283
00284 err = vl_file_meta_parse (&met, optarg) ;
00285 if (err)
00286 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00287
00288 if (met.protocol != VL_PROT_ASCII)
00289 ERR("meta file supports only ASCII protocol") ;
00290 break ;
00291
00292 case opt_read_frames :
00293
00294 err = vl_file_meta_parse (&ifr, optarg) ;
00295 if (err)
00296 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00297 break ;
00298
00299 case opt_gss :
00300
00301 err = vl_file_meta_parse (&gss, optarg) ;
00302 if (err)
00303 ERRF("The arguments of '%s' is invalid.", argv [optind - 1]) ;
00304 break ;
00305
00306
00307
00308 case 'O' :
00309
00310 n = sscanf (optarg, "%d", &O) ;
00311 if (n == 0 || O < 0)
00312 ERRF("The argument of '%s' must be a non-negative integer.",
00313 argv [optind - 1]) ;
00314 break ;
00315
00316 case 'S' :
00317
00318 n = sscanf (optarg, "%d", &S) ;
00319 if (n == 0 || S < 0)
00320 ERRF("The argument of '%s' must be a non-negative integer.",
00321 argv [optind - 1]) ;
00322 break ;
00323
00324 case opt_first_octave :
00325
00326 n = sscanf (optarg, "%d", &omin) ;
00327 if (n == 0)
00328 ERRF("The argument of '%s' must be an integer.",
00329 argv [optind - 1]) ;
00330 break ;
00331
00332
00333
00334 case opt_edge_thresh :
00335
00336 n = sscanf (optarg, "%lf", &edge_thresh) ;
00337 if (n == 0 || edge_thresh < 1)
00338 ERRF("The argument of '%s' must be not smaller than 1.",
00339 argv [optind - 1]) ;
00340 break ;
00341
00342 case opt_peak_thresh :
00343
00344 n = sscanf (optarg, "%lf", &peak_thresh) ;
00345 if (n == 0 || peak_thresh < 0)
00346 ERRF("The argument of '%s' must be a non-negative float.",
00347 argv [optind - 1]) ;
00348 break ;
00349
00350 case opt_magnif :
00351
00352 n = sscanf (optarg, "%lf", &magnif) ;
00353 if (n == 0 || magnif < 1)
00354 ERRF("The argument of '%s' must be a non-negative float.",
00355 argv [optind - 1]) ;
00356 break ;
00357
00358
00359 case opt_orientations :
00360
00361 force_orientations = 1 ;
00362 break ;
00363
00364 case 0 :
00365 default :
00366
00367 abort() ;
00368 }
00369 }
00370
00371
00372 if (err) {
00373 fprintf(stderr, "%s: error: %s (%d)\n",
00374 argv [0],
00375 err_msg, err) ;
00376 exit (1) ;
00377 }
00378
00379
00380 argc -= optind ;
00381 argv += optind ;
00382
00383
00384
00385
00386
00387 if (! force_output && (frm.active || dsc.active)) {
00388 out.active = 0 ;
00389 }
00390
00391 if (verbose > 1) {
00392 #define PRNFO(name,fm) \
00393 printf("sift: " name) ; \
00394 printf("%3s ", (fm).active ? "yes" : "no") ; \
00395 printf("%-6s ", vl_string_protocol_name ((fm).protocol)) ; \
00396 printf("%-10s\n", (fm).pattern) ;
00397
00398 PRNFO("write aggregate . ", out) ;
00399 PRNFO("write frames .... ", frm) ;
00400 PRNFO("write descriptors ", dsc) ;
00401 PRNFO("write meta ...... ", met) ;
00402 PRNFO("write GSS ....... ", gss) ;
00403 PRNFO("read frames .... ", ifr) ;
00404
00405 if (force_orientations)
00406 printf("sift: will compute orientations\n") ;
00407 }
00408
00409
00410
00411
00412
00413 while (argc--) {
00414
00415 char basename [1024] ;
00416 char const *name = *argv++ ;
00417
00418 FILE *in = 0 ;
00419 vl_uint8 *data = 0 ;
00420 vl_sift_pix *fdata = 0 ;
00421 VlPgmImage pim ;
00422
00423 VlSiftFilt *filt = 0 ;
00424 vl_size q ;
00425 int i ;
00426 vl_bool first ;
00427
00428 double *ikeys = 0 ;
00429 int nikeys = 0, ikeys_size = 0 ;
00430
00431
00432
00433
00434
00435
00436 q = vl_string_basename (basename, sizeof(basename), name, 1) ;
00437
00438 err = (q >= sizeof(basename)) ;
00439
00440 if (err) {
00441 snprintf(err_msg, sizeof(err_msg),
00442 "Basename of '%s' is too long", name);
00443 err = VL_ERR_OVERFLOW ;
00444 goto done ;
00445 }
00446
00447 if (verbose) {
00448 printf ("sift: <== '%s'\n", name) ;
00449 }
00450
00451 if (verbose > 1) {
00452 printf ("sift: basename is '%s'\n", basename) ;
00453 }
00454
00455
00456 in = fopen (name, "rb") ;
00457 if (!in) {
00458 err = VL_ERR_IO ;
00459 snprintf(err_msg, sizeof(err_msg),
00460 "Could not open '%s' for reading.", name) ;
00461 goto done ;
00462 }
00463
00464
00465
00466
00467
00468
00469 err = vl_pgm_extract_head (in, &pim) ;
00470
00471 if (err) {
00472 switch (vl_get_last_error()) {
00473 case VL_ERR_PGM_IO :
00474 snprintf(err_msg, sizeof(err_msg),
00475 "Cannot read from '%s'.", name) ;
00476 err = VL_ERR_IO ;
00477 break ;
00478
00479 case VL_ERR_PGM_INV_HEAD :
00480 snprintf(err_msg, sizeof(err_msg),
00481 "'%s' contains a malformed PGM header.", name) ;
00482 err = VL_ERR_IO ;
00483 goto done ;
00484 }
00485 }
00486
00487 if (verbose)
00488 printf ("sift: image is %" VL_FMT_SIZE " by %" VL_FMT_SIZE " pixels\n",
00489 pim. width,
00490 pim. height) ;
00491
00492
00493 data = malloc(vl_pgm_get_npixels (&pim) *
00494 vl_pgm_get_bpp (&pim) * sizeof (vl_uint8) ) ;
00495 fdata = malloc(vl_pgm_get_npixels (&pim) *
00496 vl_pgm_get_bpp (&pim) * sizeof (vl_sift_pix)) ;
00497
00498 if (!data || !fdata) {
00499 err = VL_ERR_ALLOC ;
00500 snprintf(err_msg, sizeof(err_msg),
00501 "Could not allocate enough memory.") ;
00502 goto done ;
00503 }
00504
00505
00506 err = vl_pgm_extract_data (in, &pim, data) ;
00507
00508 if (err) {
00509 snprintf(err_msg, sizeof(err_msg), "PGM body malformed.") ;
00510 err = VL_ERR_IO ;
00511 goto done ;
00512 }
00513
00514
00515 for (q = 0 ; q < (unsigned) (pim.width * pim.height) ; ++q) {
00516 fdata [q] = data [q] ;
00517 }
00518
00519
00520
00521
00522
00523 #define WERR(name,op) \
00524 if (err == VL_ERR_OVERFLOW) { \
00525 snprintf(err_msg, sizeof(err_msg), \
00526 "Output file name too long.") ; \
00527 goto done ; \
00528 } else if (err) { \
00529 snprintf(err_msg, sizeof(err_msg), \
00530 "Could not open '%s' for " #op, name) ; \
00531 goto done ; \
00532 }
00533
00534 if (ifr.active) {
00535
00536
00537 err = vl_file_meta_open (&ifr, basename, "rb") ;
00538 WERR(ifr.name, reading) ;
00539
00540 #define QERR \
00541 if (err ) { \
00542 snprintf (err_msg, sizeof(err_msg), \
00543 "'%s' malformed", ifr.name) ; \
00544 err = VL_ERR_IO ; \
00545 goto done ; \
00546 }
00547
00548 while (1) {
00549 double x, y, s, th ;
00550
00551
00552 err = vl_file_meta_get_double (&ifr, &x) ;
00553 if (err == VL_ERR_EOF) break;
00554 else QERR ;
00555 err = vl_file_meta_get_double (&ifr, &y ) ; QERR ;
00556 err = vl_file_meta_get_double (&ifr, &s ) ; QERR ;
00557 err = vl_file_meta_get_double (&ifr, &th) ;
00558 if (err == VL_ERR_EOF) break;
00559 else QERR ;
00560
00561
00562 if (ikeys_size < nikeys + 1) {
00563 ikeys_size += 10000 ;
00564 ikeys = realloc (ikeys, 4 * sizeof(double) * ikeys_size) ;
00565 }
00566
00567
00568 ikeys [4 * nikeys + 0] = x ;
00569 ikeys [4 * nikeys + 1] = y ;
00570 ikeys [4 * nikeys + 2] = s ;
00571 ikeys [4 * nikeys + 3] = th ;
00572
00573 ++ nikeys ;
00574 }
00575
00576
00577 qsort (ikeys, nikeys, 4 * sizeof(double), korder) ;
00578
00579 if (verbose) {
00580 printf ("sift: read %d keypoints from '%s'\n", nikeys, ifr.name) ;
00581 }
00582
00583
00584 vl_file_meta_close (&ifr) ;
00585 }
00586
00587
00588
00589
00590
00591 err = vl_file_meta_open (&out, basename, "wb") ; WERR(out.name, writing) ;
00592 err = vl_file_meta_open (&dsc, basename, "wb") ; WERR(dsc.name, writing) ;
00593 err = vl_file_meta_open (&frm, basename, "wb") ; WERR(frm.name, writing) ;
00594 err = vl_file_meta_open (&met, basename, "wb") ; WERR(met.name, writing) ;
00595
00596 if (verbose > 1) {
00597 if (out.active) printf("sift: writing all ....... to . '%s'\n", out.name);
00598 if (frm.active) printf("sift: writing frames .... to . '%s'\n", frm.name);
00599 if (dsc.active) printf("sift: writing descriptors to . '%s'\n", dsc.name);
00600 if (met.active) printf("sift: writign meta ...... to . '%s'\n", met.name);
00601 }
00602
00603
00604
00605
00606
00607 filt = vl_sift_new (pim.width, pim.height, O, S, omin) ;
00608
00609 if (edge_thresh >= 0) vl_sift_set_edge_thresh (filt, edge_thresh) ;
00610 if (peak_thresh >= 0) vl_sift_set_peak_thresh (filt, peak_thresh) ;
00611 if (magnif >= 0) vl_sift_set_magnif (filt, magnif) ;
00612
00613 if (!filt) {
00614 snprintf (err_msg, sizeof(err_msg),
00615 "Could not create SIFT filter.") ;
00616 err = VL_ERR_ALLOC ;
00617 goto done ;
00618 }
00619
00620 if (verbose > 1) {
00621 printf ("sift: filter settings:\n") ;
00622 printf ("sift: octaves (O) = %d\n",
00623 vl_sift_get_noctaves (filt)) ;
00624 printf ("sift: levels (S) = %d\n",
00625 vl_sift_get_nlevels (filt)) ;
00626 printf ("sift: first octave (o_min) = %d\n",
00627 vl_sift_get_octave_first (filt)) ;
00628 printf ("sift: edge thresh = %g\n",
00629 vl_sift_get_edge_thresh (filt)) ;
00630 printf ("sift: peak thresh = %g\n",
00631 vl_sift_get_peak_thresh (filt)) ;
00632 printf ("sift: magnif = %g\n",
00633 vl_sift_get_magnif (filt)) ;
00634 printf ("sift: will source frames? %s\n",
00635 ikeys ? "yes" : "no") ;
00636 printf ("sift: will force orientations? %s\n",
00637 force_orientations ? "yes" : "no") ;
00638 }
00639
00640
00641
00642
00643 i = 0 ;
00644 first = 1 ;
00645 while (1) {
00646 VlSiftKeypoint const *keys = 0 ;
00647 int nkeys ;
00648
00649
00650 if (first) {
00651 first = 0 ;
00652 err = vl_sift_process_first_octave (filt, fdata) ;
00653 } else {
00654 err = vl_sift_process_next_octave (filt) ;
00655 }
00656
00657 if (err) {
00658 err = VL_ERR_OK ;
00659 break ;
00660 }
00661
00662 if (verbose > 1) {
00663 printf("sift: GSS octave %d computed\n",
00664 vl_sift_get_octave_index (filt));
00665 }
00666
00667
00668 if (gss.active) {
00669 err = save_gss (filt, &gss, basename, verbose) ;
00670 if (err) {
00671 snprintf (err_msg, sizeof(err_msg),
00672 "Could not write GSS to PGM file.") ;
00673 goto done ;
00674 }
00675 }
00676
00677
00678 if (ikeys == 0) {
00679 vl_sift_detect (filt) ;
00680
00681 keys = vl_sift_get_keypoints (filt) ;
00682 nkeys = vl_sift_get_nkeypoints (filt) ;
00683 i = 0 ;
00684
00685 if (verbose > 1) {
00686 printf ("sift: detected %d (unoriented) keypoints\n", nkeys) ;
00687 }
00688 } else {
00689 nkeys = nikeys ;
00690 }
00691
00692
00693 for (; i < nkeys ; ++i) {
00694 double angles [4] ;
00695 int nangles ;
00696 VlSiftKeypoint ik ;
00697 VlSiftKeypoint const *k ;
00698
00699
00700 if (ikeys) {
00701 vl_sift_keypoint_init (filt, &ik,
00702 ikeys [4 * i + 0],
00703 ikeys [4 * i + 1],
00704 ikeys [4 * i + 2]) ;
00705
00706 if (ik.o != vl_sift_get_octave_index (filt)) {
00707 break ;
00708 }
00709
00710 k = &ik ;
00711
00712
00713 if (force_orientations) {
00714 nangles = vl_sift_calc_keypoint_orientations
00715 (filt, angles, k) ;
00716 } else {
00717 angles [0] = ikeys [4 * i + 3] ;
00718 nangles = 1 ;
00719 }
00720 } else {
00721 k = keys + i ;
00722 nangles = vl_sift_calc_keypoint_orientations
00723 (filt, angles, k) ;
00724 }
00725
00726
00727 for (q = 0 ; q < (unsigned) nangles ; ++q) {
00728 vl_sift_pix descr [128] ;
00729
00730
00731 if (out.active || dsc.active) {
00732 vl_sift_calc_keypoint_descriptor
00733 (filt, descr, k, angles [q]) ;
00734 }
00735
00736 if (out.active) {
00737 int l ;
00738 vl_file_meta_put_double (&out, k -> x ) ;
00739 vl_file_meta_put_double (&out, k -> y ) ;
00740 vl_file_meta_put_double (&out, k -> sigma ) ;
00741 vl_file_meta_put_double (&out, angles [q] ) ;
00742 for (l = 0 ; l < 128 ; ++l) {
00743 vl_file_meta_put_uint8 (&out, (vl_uint8) (512.0 * descr [l])) ;
00744 }
00745 if (out.protocol == VL_PROT_ASCII) fprintf(out.file, "\n") ;
00746 }
00747
00748 if (frm.active) {
00749 vl_file_meta_put_double (&frm, k -> x ) ;
00750 vl_file_meta_put_double (&frm, k -> y ) ;
00751 vl_file_meta_put_double (&frm, k -> sigma ) ;
00752 vl_file_meta_put_double (&frm, angles [q] ) ;
00753 if (frm.protocol == VL_PROT_ASCII) fprintf(frm.file, "\n") ;
00754 }
00755
00756 if (dsc.active) {
00757 int l ;
00758 for (l = 0 ; l < 128 ; ++l) {
00759 double x = 512.0 * descr[l] ;
00760 x = (x < 255.0) ? x : 255.0 ;
00761 vl_file_meta_put_uint8 (&dsc, (vl_uint8) (x)) ;
00762 }
00763 if (dsc.protocol == VL_PROT_ASCII) fprintf(dsc.file, "\n") ;
00764 }
00765 }
00766 }
00767 }
00768
00769
00770
00771
00772
00773 if (met.active) {
00774 fprintf(met.file, "<sift\n") ;
00775 fprintf(met.file, " input = '%s'\n", name) ;
00776 if (dsc.active) {
00777 fprintf(met.file, " descriptors = '%s'\n", dsc.name) ;
00778 }
00779 if (frm.active) {
00780 fprintf(met.file," frames = '%s'\n", frm.name) ;
00781 }
00782 fprintf(met.file, ">\n") ;
00783 }
00784
00785 done :
00786
00787 if (ikeys) {
00788 free (ikeys) ;
00789 ikeys_size = nikeys = 0 ;
00790 ikeys = 0 ;
00791 }
00792
00793
00794 if (filt) {
00795 vl_sift_delete (filt) ;
00796 filt = 0 ;
00797 }
00798
00799
00800 if (fdata) {
00801 free (fdata) ;
00802 fdata = 0 ;
00803 }
00804
00805
00806 if (data) {
00807 free (data) ;
00808 data = 0 ;
00809 }
00810
00811
00812 if (in) {
00813 fclose (in) ;
00814 in = 0 ;
00815 }
00816
00817 vl_file_meta_close (&out) ;
00818 vl_file_meta_close (&frm) ;
00819 vl_file_meta_close (&dsc) ;
00820 vl_file_meta_close (&met) ;
00821 vl_file_meta_close (&gss) ;
00822 vl_file_meta_close (&ifr) ;
00823
00824
00825 if (err) {
00826 fprintf
00827 (stderr,
00828 "sift: err: %s (%d)\n",
00829 err_msg,
00830 err) ;
00831 exit_code = 1 ;
00832 }
00833 }
00834
00835
00836 return exit_code ;
00837 }