📄 main.cpp
字号:
/*
* Speeded-Up Robust Features (SURF)
* http://people.ee.ethz.ch/~surf
*
* Authors: Herbert Bay, Andreas Ess, Geert Willems
* Windows port by Stefan Saur
*
* Copyright (2006): ETH Zurich, Switzerland
* Katholieke Universiteit Leuven, Belgium
* All rights reserved.
*
* For details, see the paper:
* Herbert Bay, Tinne Tuytelaars, Luc Van Gool,
* "SURF: Speeded Up Robust Features"
* Proceedings of the ninth European Conference on Computer Vision, May 2006
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for educational, research, and non-commercial
* purposes, without fee and without a signed licensing agreement, is
* hereby granted, provided that the above copyright notice and this
* paragraph appear in all copies modifications, and distributions.
*
* Any commercial use or any redistribution of this software
* requires a license from one of the above mentioned establishments.
*
* For further details, contact Andreas Ess (aess@vision.ee.ethz.ch).
*/
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <string.h>
#ifdef WIN32
#include "surfWINDLL.h"
#endif
#include "imload.h"
#include "surflib.h"
#include "os_mapping.h"
using namespace std;
using namespace surf;
// Length of the descriptor vector
int VLength;
// Forward declaration of the functions to load/save the SURF points
void loadIpoints(string fn, vector< Ipoint >& keys, bool bVerbose = false);
void saveIpoints(string fn, const vector< Ipoint >& keys, bool bVerbose = false, bool bLaplacian = true);
int main (int argc, char **argv)
{
// Initial sampling step (default 2)
int samplingStep = 2;
// Number of analysed octaves (default 4)
int octaves = 4;
// Blob response treshold
double thres = 4.0;
// Set this flag "true" to double the image size
bool doubleImageSize = false;
// Initial lobe size, default 3 and 5 (with double image size)
int initLobe = 3;
// Upright SURF or rotation invaraiant
bool upright = false;
// If the extended flag is turned on, SURF 128 is used
bool extended = false;
// Spatial size of the descriptor window (default 4)
int indexSize = 4;
// Variables for the timing measure
osmapping::os_TIME tim1, tim2; //STS
// verbose output
bool bVerbose = true;
// skip sign of laplacian
bool bLaplacian = true;
bool bLoadRegions = false;
string sRegionFile = "";
// Print command line help
if (argc==1) {
cerr << "./surf -i img.pgm -o img.surf [options]\n"
<< " blob response threshold -thres 1000\n"
<< " double image size: -d\n"
<< " custom lobe size: -ms 3\n"
<< " initial sampling step: -ss 2\n"
<< " number of octaves: -oc 4\n"
<< " U-SURF (not rotation invariant): -u\n"
<< " extended descriptor (SURF-128): -e\n"
<< " descriptor size: -in 4\n"
<< " input regions: -p1 <file>\n"
<< " verbose output: -v\n"
<< " don't write laplacian: -nl\n"
<< " quiet mode: -q\n";
return(0);
}
// Read the arguments
ImLoad ImageLoader;
int arg = 0;
string fn = "out.surf";
Image *im=NULL;
while (++arg < argc) {
if (! strcmp(argv[arg], "-i"))
im = ImageLoader.readImage(argv[++arg]);
if (! strcmp(argv[arg], "-o"))
fn = argv[++arg];
if (! strcmp(argv[arg], "-thres"))
thres = (atof(argv[++arg]))/10000;
if (! strcmp(argv[arg], "-d"))
doubleImageSize = true;
if (! strcmp(argv[arg], "-ms"))
initLobe = atoi(argv[++arg]);
if (! strcmp(argv[arg], "-oc"))
octaves = atoi(argv[++arg]);
if (! strcmp(argv[arg], "-ss"))
samplingStep = atoi(argv[++arg]);
if (! strcmp(argv[arg], "-u"))
upright = true;
if (! strcmp(argv[arg], "-e"))
extended = true;
if (! strcmp(argv[arg], "-in"))
indexSize = atoi(argv[++arg]);
if (! strcmp(argv[arg], "-p1")) {
bLoadRegions = true;
sRegionFile = argv[++arg];
}
if (! strcmp(argv[arg], "-v"))
bVerbose = true;
if (! strcmp(argv[arg], "-nl"))
bLaplacian = false;
if (! strcmp(argv[arg], "-q"))
bVerbose = false;
}
// Start measuring the time
osmapping::os_GetTime(&tim1);
// Create the integral image
Image iimage(im, doubleImageSize);
// Start finding the SURF points
if( bVerbose )
cout << "Finding SURFs...\n";
// These are the interest points
vector< Ipoint > ipts;
ipts.reserve(1000);
// Extract interest points with Fast-Hessian
FastHessian fh(&iimage, /* pointer to integral image */
ipts,
thres, /* blob response threshold */
doubleImageSize, /* double image size flag */
initLobe * 3 /* 3 times lobe size equals the mask size */,
samplingStep, /* subsample the blob response map */
octaves /* number of octaves to be analysed */);
if( bLoadRegions ) {
// Load the interest points from disk
loadIpoints( sRegionFile, ipts, bVerbose );
} else {
// Extract them and get their pointer
fh.getInterestPoints();
}
// Initialise the SURF descriptor
Surf des(&iimage, /* pointer to integral image */
doubleImageSize, /* double image size flag */
upright, /* rotation invariance or upright */
extended, /* use the extended descriptor */
indexSize /* square size of the descriptor window (default 4x4)*/);
// Get the length of the descriptor vector resulting from the parameters
VLength = des.getVectLength();
// Compute the orientation and the descriptor for every interest point
for (unsigned n=0; n<ipts.size(); n++){
//for (Ipoint *k = ipts; k != NULL; k = k->next){
// set the current interest point
des.setIpoint(&ipts[n]);
// assign reproducible orientation
des.assignOrientation();
// make the SURF descriptor
des.makeDescriptor();
}
// stop measuring the time, we're all done
osmapping::os_GetTime(&tim2);
// save the interest points in the output file
saveIpoints(fn, ipts, bVerbose, bLaplacian);
// print some nice information on the command prompt
if( bVerbose )
cout << "Detection time: " << osmapping::os_TimeDiff(&tim2, &tim1) << " ms" << endl;
delete im;
return 0;
}
// Save the interest points to a regular ASCII file
void saveIpoints(string sFileName, const vector< Ipoint >& ipts, bool bVerbose, bool bLaplacian)
{
ofstream ipfile(sFileName.c_str());
if( !ipfile ) {
cerr << "ERROR in loadIpoints(): "
<< "Couldn't open file '" << sFileName.c_str() << "'!" << endl; //STS
return;
}
double sc;
unsigned count = ipts.size();
// Write the file header
if (bLaplacian)
ipfile << VLength + 1 << endl << count << endl;
else
ipfile << VLength << endl << count << endl;
// In order to just save the interest points without descriptor, comment
// the above and uncomment the following command.
// ipfile << 1.0 << endl << count << endl;
// Save interest point with descriptor in the format of Krystian Mikolajczyk
// for reasons of comparison with other descriptors. As our interest points
// are circular in any case, we use the second component of the ellipse to
// provide some information about the strength of the interest point. This is
// important for 3D reconstruction as only the strongest interest points are
// considered. Replace the strength with 0.0 in order to perform Krystian's
// comparisons.
for (unsigned n=0; n<ipts.size(); n++){
// circular regions with diameter 5 x scale
sc = 2.5 * ipts[n].scale; sc*=sc;
ipfile << ipts[n].x /* x-location of the interest point */
<< " " << ipts[n].y /* y-location of the interest point */
<< " " << 1.0/sc /* 1/r^2 */
<< " " << 0.0 //(*ipts)[n]->strength /* 0.0 */
<< " " << 1.0/sc; /* 1/r^2 */
if (bLaplacian)
ipfile << " " << ipts[n].laplace;
// Here comes the descriptor
for (int i = 0; i < VLength; i++) {
ipfile << " " << ipts[n].ivec[i];
}
ipfile << endl;
}
// Write message to terminal.
if( bVerbose )
cout << count << " interest points found" << endl;
}
// Load the interest points from a regular ASCII file
void loadIpoints(string sFileName, vector< Ipoint >& ipts, bool bVerbose)
{
ifstream ipfile(sFileName.c_str());
if( !ipfile ) {
cerr << "ERROR in loadIpoints(): "
<< "Couldn't open file '" << sFileName.c_str() << "'!" << endl; //STS
return;
}
// Load the file header
float dummy;
unsigned count;
ipfile >> dummy >> count;
// create a new interest point vector
ipts.clear();
ipts.resize(count);
// Load the interest points in Mikolajczyk's format
for (unsigned n=0; n<count; n++){
// circular regions with diameter 5 x scale
float x, y, a, b, c;
ipfile >> x >> y >> a >> b >> c;
float det = sqrt((a-c)*(a-c) + 4.0*b*b);
float e1 = 0.5*(a+c + det);
float e2 = 0.5*(a+c - det);
float l1 = (1.0/sqrt(e1));
float l2 = (1.0/sqrt(e2));
float sc = sqrt( l1*l2 );
ipts[n].x = x;
ipts[n].y = y;
ipts[n].scale = sc/2.5;
}
// close the interest point file again
ipfile.close();
// Write message to terminal.
if( bVerbose )
cout << "read in " << count << " interest points." << endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -