123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- // file: sift-driver.cpp
- // author: Andrea Vedaldi
- // description: SIFT command line utility implementation
- // AUTORIGTHS
- #include <vislearning/features/localfeatures/sift.h>
- #include<string>
- #include <stdlib.h>
- #include <memory>
- #include <string.h>
- #include<iostream>
- #include<iomanip>
- #include<fstream>
- #include<sstream>
- #include<algorithm>
- extern "C" {
- #include<getopt.h>
- #if defined(__clang__) || defined(__llvm__)
- #include<libgen.h>
- #else
- #include<string.h>
- #endif
- #include<assert.h>
- }
- using namespace std ;
- typedef unsigned char uint8_t;
- typedef unsigned int uint32_t;
- size_t const not_found = numeric_limits<size_t>::max() - 1 ;
- /** @brief Case insensitive character comparison
- **
- ** This predicate returns @c true if @a a and @a b are equal up to
- ** case.
- **
- ** @return predicate value.
- **/
- inline
- bool ciIsEqual(char a, char b)
- {
- return
- tolower((char unsigned)a) ==
- tolower((char unsigned)b) ;
- }
- /** @brief Case insensitive extension removal
- **
- ** The function returns @a name with the suffix $a ext removed. The
- ** suffix is matched case-insensitve.
- **
- ** @return @a name without @a ext.
- **/
- string
- // refactor-nice.pl: check this substitution
- // old: removeExtension(string name, string ext)
- removeExtension(string name, std::string ext)
- {
- string::iterator pos =
- find_end(name.begin(),name.end(),ext.begin(),ext.end(),ciIsEqual) ;
- // make sure the occurence is at the end
- if(pos+ext.size() == name.end()) {
- return name.substr(0, pos-name.begin()) ;
- } else {
- return name ;
- }
- }
- /** @brief Insert descriptor into stream
- **
- ** The function writes a descriptor in ASCII/binary format
- ** and in integer/floating point format into the stream.
- **
- ** @param os output stream.
- ** @param descr_pt descriptor (floating point)
- ** @param binary write binary descriptor?
- ** @param fp write floating point data?
- **/
- std::ostream&
- insertDescriptor(std::ostream& os,
- VL::float_t const * descr_pt,
- bool binary,
- bool fp )
- {
- #define RAW_CONST_PT(x) reinterpret_cast<char const*>(x)
- #define RAW_PT(x) reinterpret_cast<char*>(x)
- if( fp ) {
- /* convert to 32 bits floats (single precision) */
- VL::float32_t fdescr_pt [128] ;
- for(int i = 0 ; i < 128 ; ++i)
- fdescr_pt[i] = VL::float32_t( descr_pt[i]) ;
- if( binary ) {
- /*
- Test for endianess. Recall: big_endian = the most significant
- byte at lower memory address.
- */
- short int const word = 0x0001 ;
- bool little_endian = RAW_CONST_PT(&word)[0] ;
-
- /*
- We save in big-endian (network) order. So if this machine is
- little endiand do the appropriate conversion.
- */
- if( little_endian ) {
- for(int i = 0 ; i < 128 ; ++i) {
- VL::float32_t tmp = fdescr_pt[ i ] ;
- char* pt = RAW_PT(fdescr_pt + i) ;
- char* spt = RAW_PT(&tmp) ;
- pt[0] = spt[3] ;
- pt[1] = spt[2] ;
- pt[2] = spt[1] ;
- pt[3] = spt[0] ;
- }
- }
- os.write( RAW_PT(fdescr_pt), 128 * sizeof(VL::float32_t) ) ;
- } else {
- for(int i = 0 ; i < 128 ; ++i)
- os << ' '
- << fdescr_pt[i] ;
- }
- } else {
- VL::uint8_t idescr_pt [128] ;
- for(int i = 0 ; i < 128 ; ++i)
- idescr_pt[i] = uint8_t(float_t(512) * descr_pt[i]) ;
-
- if( binary ) {
- os.write( RAW_PT(idescr_pt), 128) ;
- } else {
-
- for(int i = 0 ; i < 128 ; ++i)
- os << ' '
- << uint32_t( idescr_pt[i] ) ;
- }
- }
- return os ;
- }
- /* keypoint list */
- typedef vector<pair<VL::Sift::Keypoint,VL::float_t> > Keypoints ;
- /* predicate used to order keypoints by increasing scale */
- bool cmpKeypoints (Keypoints::value_type const&a,
- Keypoints::value_type const&b) {
- return a.first.sigma < b.first.sigma ;
- }
- // -------------------------------------------------------------------
- // main
- // -------------------------------------------------------------------
- int
- main(int argc, char** argv)
- {
- int first = -1 ;
- int octaves = -1 ;
- int levels = 3 ;
- float threshold = 0.04f / levels / 2.0f ;
- float edgeThreshold = 10.0f;
- float magnif = 1.5 ;
- int nodescr = 0 ;
- int noorient = 0 ;
- int stableorder = 0 ;
- int savegss = 0 ;
- int verbose = 0 ;
- int binary = 0 ;
- int haveKeypoints = 0 ;
- int unnormalized = 0 ;
- int fp = 0 ;
- // refactor-nice.pl: check this substitution
- // old: string outputFilenamePrefix ;
- std::string outputFilenamePrefix ;
- // refactor-nice.pl: check this substitution
- // old: string outputFilename ;
- std::string outputFilename ;
- // refactor-nice.pl: check this substitution
- // old: string descriptorsFilename ;
- std::string descriptorsFilename ;
- // refactor-nice.pl: check this substitution
- // old: string keypointsFilename ;
- std::string keypointsFilename ;
- static struct option longopts[] = {
- { "verbose", no_argument, NULL, 'v' },
- { "help", no_argument, NULL, 'h' },
- { "output", required_argument, NULL, 'o' },
- { "prefix", required_argument, NULL, 'p' },
- { "first-octave", required_argument, NULL, 'f' },
- { "keypoints", required_argument, NULL, 'k' },
- { "octaves", required_argument, NULL, 'O' },
- { "levels", required_argument, NULL, 'S' },
- { "threshold", required_argument, NULL, 't' },
- { "edge-threshold", required_argument, NULL, 'e' },
- { "magnif", required_argument, NULL, 'm' },
- { "binary", no_argument, NULL, 'b' },
- { "no-descriptors", no_argument, &nodescr, 1 },
- { "no-orientations", no_argument, &noorient, 1 },
- { "stable-order", no_argument, &stableorder, 1 },
- { "save-gss", no_argument, &savegss, 1 },
- { "unnormalized", no_argument, &unnormalized, 1 },
- { "floating-point", no_argument, &fp, 1 },
- { NULL, 0, NULL, 0 }
- };
-
- int ch ;
- try {
-
- while ( (ch = getopt_long(argc, argv, "vho:p:f:k:O:S:t:e:b", longopts, NULL)) != -1) {
- switch (ch) {
- case '?' :
- VL_THROW("Invalid option '"<<argv[optind-1]<<"'.") ;
- break;
-
- case ':' :
- VL_THROW("Missing argument of option '"<<argv[optind-1]<<"'.") ;
- break;
-
- case 'h' :
- std::cout
- << argv[0] << " [--verbose|=v] [--help|-h]" << endl
- << " [--output|-o NAME] [--prefix|-p PREFIX] [--binary|-b] [--save-gss] " << endl
- << " [--no-descriptors] [--no-orientations] " << endl
- << " [--levels|-S NUMBER] [--octaves|-O NUMBER] [--first-octave|-f NUMBER] " << endl
- << " [--threshold|-t NUMBER] [--edge-threshold|-e NUMBER] " << endl
- << " [--floating-point] [--unnormalized] " << endl
- << " IMAGE [IMAGE2 ...]" << endl
- << endl
- << "* Options *" << endl
- << " --verbose Be verbose"<< endl
- << " --help Print this message"<<endl
- << " --output=NAME Write to this file"<<endl
- // refactor-nice.pl: check this substitution
- // old: << " --prefix=PREFIX Derive output filename prefixing this string to the input file"<<endl
- << " --prefix=PREFIX Derive output filename prefixing this std::string to the input file"<<endl
- << " --binary Write descriptors to a separate file in binary format"<<endl
- << " --keypoints=FILE Reads keypoint frames from here; do not run SIFT detector" << endl
- << " --save-gss Save Gaussian scale space on disk" << endl
- << " --octaves=O Number of octaves" << endl
- << " --levels=S Number of levels per octave" << endl
- << " --first-octave=MINO Index of the first octave" << endl
- << " --threshold=THR Keypoint strength threhsold" << endl
- << " --magnif=MAG Keypoint magnification" << endl
- << " --edge-threshold=THR On-edge threshold" << endl
- << " --no-descriptors Do not compute descriptors" << endl
- << " --no-orientations Do not compute orientations" << endl
- << " --stable-order Do not reorder keypoints" << endl
- << " --unnormalzied Do not normalize descriptors" << endl
- << " --floating-point Save floating point descriptors" << endl
- << endl
- << " * Examples *" << endl
- << argv[0] << " [OPTS...] image.pgm" << endl
- << argv[0] << " [OPTS...] image.pgm --output=file.key" << endl
- << argv[0] << " [OPTS...] image.pgm --keypoints=frames.key" << endl
- << argv[0] << " [OPTS...] *.pgm --prefix=/tmp/" << endl
- << argv[0] << " [OPTS...] *.pgm --prefix=/tmp/ --binary" << endl
- << endl
- << " * This build: " ;
- #if defined VL_USEFASTMATH
- std::cout << "has fast approximate math" ;
- #else
- std::cout << "has slow accurate math" ;
- #endif
- std::cout << " (fp datatype is '"
- << VL_EXPAND_AND_STRINGIFY(VL_FASTFLOAT)
- << "') *"<<endl ;
- return 0 ;
-
- case 'v' : // verbose
- verbose = 1 ;
- break ;
-
- case 'f': // first octave
- {
- std::istringstream iss(optarg) ;
- iss >> first ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- }
- break ;
-
- case 'O' : // octaves
- {
- std::istringstream iss(optarg) ;
- iss >> octaves ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- if( octaves < 1 ) {
- VL_THROW("The number of octaves cannot be smaller than one.");
- }
- }
- break ;
-
- case 'S' : // levels
- {
- std::istringstream iss(optarg) ;
- iss >> levels ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- if( levels < 1 ) {
- VL_THROW("The number of levels cannot be smaller than one.") ;
- }
- }
- break ;
- case 't' : // threshold
- {
- std::istringstream iss(optarg) ;
- iss >> threshold ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- }
- break ;
- case 'e' : // edge-threshold
- {
- std::istringstream iss(optarg) ;
- iss >> edgeThreshold ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- }
- break ;
- case 'm' : // magnification
- {
- std::istringstream iss(optarg) ;
- iss >> magnif ;
- if( iss.fail() )
- VL_THROW("Invalid argument '" << optarg << "'.") ;
- }
- break ;
- case 'o' : // output filename
- {
- outputFilename = std::string(optarg) ;
- break ;
- }
- case 'p' : // output prefix
- {
- outputFilenamePrefix = std::string(optarg) ;
- break ;
- }
- case 'k' : // keypoint file
- {
- keypointsFilename = std::string(optarg) ;
- haveKeypoints = 1 ;
- break ;
- }
- case 'b' : // write descriptors to a binary file
- {
- binary = 1 ;
- break ;
- }
- case 0 : // all other options
- break ;
-
- default:
- assert(false) ;
- }
- }
-
- argc -= optind;
- argv += optind;
- // check for argument consistency
- if(argc == 0) VL_THROW("No input image specfied.") ;
- if(outputFilename.size() != 0 && ((argc > 1) | binary)) {
- VL_THROW("--output cannot be used with multiple images or --binary.") ;
- }
- if(outputFilename.size() !=0 &&
- outputFilenamePrefix.size() !=0) {
- VL_THROW("--output cannot be used in combination with --prefix.") ;
- }
- /* end option try-catch block */
- }
- catch( VL::Exception const & e ) {
- cerr << "siftpp: error: "
- << e.msg
- << endl ;
- exit(1) ;
- }
- // -----------------------------------------------------------------
- // Loop over input images
- // -----------------------------------------------------------------
- while( argc > 0 ) {
- // refactor-nice.pl: check this substitution
- // old: string name(argv[0]) ;
- std::string name(argv[0]) ;
- try {
- VL::PgmBuffer buffer ;
-
- // compute the output filenames:
- //
- // 1) if --output is specified, then we just use the one provided
- // by the user
- //
- // 2) if --output is not specified, we derive the output filename
- // from the input filename by
- // - removing the extension part from the output filename
- // - and if outputFilenamePrefix is non void, removing
- // the directory part and prefixing outputFilenamePrefix.
- //
- // 3) in any case we derive the binary descriptor filename by
- // removing from the output filename the .key extension (if any)
- // and adding a .desc extension.
-
- if(outputFilename.size() == 0) {
- // case 2) above
- outputFilename = name ;
-
- // if we specify an output directory, then extract
- // the basename
- if(outputFilenamePrefix.size() != 0) {
- outputFilename = outputFilenamePrefix +
- std::string(basename((char*)outputFilename.c_str())) ;
- }
-
- // remove .pgm extension, add .key
- outputFilename = removeExtension(outputFilename, ".pgm") ;
- outputFilename += ".key" ;
- }
-
- // remove .key extension, add .desc
- descriptorsFilename = removeExtension(outputFilename, ".key") ;
- descriptorsFilename += ".desc" ;
-
- // ---------------------------------------------------------------
- // Load PGM image
- // ---------------------------------------------------------------
- verbose && cout
- << "siftpp: lodaing PGM image '" << name << "' ..."
- << flush;
-
- try {
- ifstream in(name.c_str(), ios::binary) ;
- if(! in.good()) VL_THROW("Could not open '"<<name<<"'.") ;
- extractPgm(in, buffer) ;
- }
- catch(VL::Exception const& e) {
- throw VL::Exception("PGM read error: "+e.msg) ;
- }
-
- verbose && cout
- << " read "
- << buffer.width <<" x "
- << buffer.height <<" pixels"
- << endl ;
-
- // ---------------------------------------------------------------
- // Gaussian scale space
- // ---------------------------------------------------------------
- verbose && cout
- << "siftpp: computing Gaussian scale space"
- << endl ;
-
- int O = octaves ;
- int const S = levels ;
- int const omin = first ;
- float const sigman = .5 ;
- float const sigma0 = 1.6 * powf(2.0f, 1.0f / S) ;
-
- // optionally autoselect the number number of octaves
- // we downsample up to 8x8 patches
- if(O < 1) {
- O = std::max
- (int
- (std::floor
- (log2
- (std::min(buffer.width,buffer.height))) - omin -3), 1) ;
- }
- verbose && cout
- << "siftpp: number of octaves : " << O << endl
- << "siftpp: first octave : " << omin << endl
- << "siftpp: levels per octave : " << S
- << endl ;
-
- // initialize scalespace
- VL::Sift sift(buffer.data, buffer.width, buffer.height,
- sigman, sigma0,
- O, S,
- omin, -1, S+1) ;
-
- verbose && cout
- << "siftpp: Gaussian scale space completed"
- << endl ;
-
- // ---------------------------------------------------------------
- // Save Gaussian scale space
- // ---------------------------------------------------------------
-
- if(savegss) {
- verbose && cout<<"siftpp: saving Gaussian scale space"<<endl ;
-
- // refactor-nice.pl: check this substitution
- // old: string imageBasename = removeExtension(outputFilename, ".key") ;
- std::string imageBasename = removeExtension(outputFilename, ".key") ;
-
- for(int o = omin ; o < omin + O ; ++o) {
- for(int s = 0 ; s < S ; ++s) {
-
- // refactor-nice.pl: check this substitution
- // old: ostringstream suffix ;
- std::ostringstream suffix ;
- suffix<<'.'<<o<<'.'<<s<<".pgm" ;
- // refactor-nice.pl: check this substitution
- // old: string imageFilename = imageBasename + suffix.str() ;
- std::string imageFilename = imageBasename + suffix.str() ;
-
- verbose && cout
- << "siftpp: octave " << setw(3) << o
- << " level " << setw(3) << s
- << " to '" << imageFilename
- << "' ..." << flush ;
-
- ofstream fout(imageFilename.c_str(), ios::binary) ;
- if(!fout.good())
- VL_THROW("Could not open '"<<imageFilename<<'\'') ;
-
- VL::insertPgm(fout,
- sift.getLevel(o,s),
- sift.getOctaveWidth(o),
- sift.getOctaveHeight(o)) ;
- fout.close() ;
-
- verbose && cout
- << " done." << endl ;
- }
- }
- }
-
- // -------------------------------------------------------------
- // Run SIFT detector
- // -------------------------------------------------------------
- if( ! haveKeypoints ) {
- verbose && cout
- << "siftpp: running detector "<< endl
- << "siftpp: threshold : " << threshold << endl
- << "siftpp: edge-threshold : " << edgeThreshold
- << endl ;
-
- sift.detectKeypoints(threshold, edgeThreshold) ;
-
- verbose && cout
- << "siftpp: detector completed with "
- << sift.keypointsEnd() - sift.keypointsBegin()
- << " keypoints"
- << endl ;
- }
-
- // -------------------------------------------------------------
- // Run SIFT orientation detector and descriptor
- // -------------------------------------------------------------
- /* set descriptor options */
- sift.setNormalizeDescriptor( ! unnormalized ) ;
- sift.setMagnification( magnif ) ;
- if( verbose ) {
- cout << "siftpp: " ;
- if( ! noorient & nodescr) cout << "computing keypoint orientations" ;
- if( noorient & ! nodescr) cout << "computing keypoint descriptors" ;
- if( ! noorient & ! nodescr) cout << "computing orientations and descriptors" ;
- if( noorient & nodescr) cout << "finalizing" ;
- cout << endl ;
- }
-
- {
- // open output file
- ofstream out(outputFilename.c_str(), ios::binary) ;
-
- if( ! out.good() )
- VL_THROW("Could not open output file '"
- << outputFilename
- << "'.") ;
-
- verbose && cout
- << "siftpp: write keypoints to : '" << outputFilename << "'" << endl
- << "siftpp: floating point descr. : " << (fp ? "yes" : "no") << endl
- << "siftpp: binary descr. : " << (binary ? "yes" : "no") << endl
- << "siftpp: unnormalized descr. : " << (unnormalized ? "yes" : "no") << endl
- << "siftpp: descr. magnif. : " << setprecision(3) << magnif
- << endl ;
-
- out.flags(ios::fixed) ;
-
- /* If a keypoint file is provided, then open it now */
- auto_ptr<ifstream> keypointsIn_pt ;
-
- if( haveKeypoints ) {
- keypointsIn_pt = auto_ptr<ifstream>
- (new ifstream(keypointsFilename.c_str(), ios::binary)) ;
-
- if( ! keypointsIn_pt->good() )
- VL_THROW("Could not open keypoints file '"
- << keypointsFilename
- << "'.") ;
-
- verbose && cout
- << "siftpp: read keypoints from : '"
- << keypointsFilename << "'"
- << endl ;
- }
-
- /* If the descriptors are redirected to a binary file, then open it now */
- auto_ptr<ofstream> descriptorsOut_pt ;
-
- if( binary ) {
- descriptorsOut_pt = auto_ptr<ofstream>
- (new ofstream(descriptorsFilename.c_str(), ios::binary)) ;
-
- if( ! descriptorsOut_pt->good() )
- VL_THROW("Could not open descriptors file '"
- << descriptorsFilename
- << "'.") ;
-
- verbose && cout
- << "siftpp: write descriptors to : '"
- << descriptorsFilename << "'"
- << endl ;
- }
-
- if( haveKeypoints ) {
- // -------------------------------------------------------------
- // Reads keypoint from file, compute descriptors
- // -------------------------------------------------------------
- Keypoints keypoints ;
-
- while( !keypointsIn_pt->eof() ) {
- VL::float_t x,y,sigma,th ;
-
- /* read x, y, sigma and th from the beginning of the line */
- (*keypointsIn_pt)
- >> x
- >> y
- >> sigma
- >> th ;
- /* skip the rest of the line */
- (*keypointsIn_pt).ignore(numeric_limits<streamsize>::max(),'\n') ;
- /* break the loop if end of file reached */
- if( keypointsIn_pt->eof() ) break ;
- /* trhow an error if something wrong */
- if( ! keypointsIn_pt->good() )
- VL_THROW("Error reading keypoints file.") ;
-
- /* compute integer components */
- VL::Sift::Keypoint key
- = sift.getKeypoint(x,y,sigma) ;
-
- Keypoints::value_type entry ;
- entry.first = key ;
- entry.second = th ;
- keypoints.push_back(entry) ;
- }
-
- /* sort keypoints by scale if not required otherwise */
- if(! stableorder)
- sort(keypoints.begin(), keypoints.end(), cmpKeypoints) ;
-
- // process in batch
- for(Keypoints::const_iterator iter = keypoints.begin() ;
- iter != keypoints.end() ;
- ++iter) {
- VL::Sift::Keypoint const& key = iter->first ;
- VL::float_t th = iter->second ;
-
- /* write keypoint */
- out << setprecision(2) << key.x << " "
- << setprecision(2) << key.y << " "
- << setprecision(2) << key.sigma << " "
- << setprecision(3) << th ;
-
- /* compute descriptor */
- VL::float_t descr [128] ;
- sift.computeKeypointDescriptor(descr, key, th) ;
-
- /* save to appropriate file */
- if( descriptorsOut_pt.get() ) {
- ostream& os = *descriptorsOut_pt.get() ;
- insertDescriptor(os, descr, true, fp) ;
- } else {
- insertDescriptor(out, descr, false, fp) ;
- }
-
- /* next keypoint */
- out << endl ;
- } // next keypoint
-
- } else {
-
- // -------------------------------------------------------------
- // Run detector, compute orientations and descriptors
- // -------------------------------------------------------------
- for( VL::Sift::KeypointsConstIter iter = sift.keypointsBegin() ;
- iter != sift.keypointsEnd() ; ++iter ) {
-
- // detect orientations
- VL::float_t angles [4] ;
- int nangles ;
- if( ! noorient ) {
- nangles = sift.computeKeypointOrientations(angles, *iter) ;
- } else {
- nangles = 1;
- angles[0] = VL::float_t(0) ;
- }
-
- // compute descriptors
- for(int a = 0 ; a < nangles ; ++a) {
- out << setprecision(2) << iter->x << ' '
- << setprecision(2) << iter->y << ' '
- << setprecision(2) << iter->sigma << ' '
- << setprecision(3) << angles[a] ;
- /* compute descriptor */
- VL::float_t descr_pt [128] ;
- sift.computeKeypointDescriptor(descr_pt, *iter, angles[a]) ;
-
- /* save descriptor to to appropriate file */
- if( ! nodescr ) {
- if( descriptorsOut_pt.get() ) {
- ostream& os = *descriptorsOut_pt.get() ;
- insertDescriptor(os, descr_pt, true, fp) ;
- } else {
- insertDescriptor(out, descr_pt, false, fp) ;
- }
- }
- /* next line */
- out << endl ;
- } // next angle
- } // next keypoint
- }
-
- out.close() ;
- if(descriptorsOut_pt.get()) descriptorsOut_pt->close();
- if(keypointsIn_pt.get()) keypointsIn_pt->close();
- verbose && cout
- << "siftpp: job completed"<<endl ;
- }
-
- argc-- ;
- argv++ ;
- outputFilename = string("") ;
- }
- catch(VL::Exception &e) {
- cerr<<endl<<"Error processing '"<<name<<"': "<<e.msg<<endl ;
- return 1 ;
- }
- } // next image
-
- return 0 ;
- }
|