Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
main.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 ; tab-width: 4 -*-
2 /*
3 * Copyright (C) 2007-2008 Anael Orlinski
4 *
5 * This file is part of Panomatic.
6 *
7 * Panomatic is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * Panomatic is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Panomatic; if not, write to the Free Software
19 * <http://www.gnu.org/licenses/>.
20 */
21 
22 #include <iostream>
23 #include <vector>
24 #include <string>
25 #include "Utils.h"
26 #include <getopt.h>
27 #include "hugin_utils/stl_utils.h"
28 
29 #include "PanoDetector.h"
30 
32 {
33  std::cout << "Hugin's cpfind " << hugin_utils::GetHuginVersion() << std::endl;
34  std::cout << "based on Pan-o-matic by Anael Orlinski" << std::endl;
35 };
36 
37 void printUsage()
38 {
39  printVersion();
40  std::cout << std::endl
41  << "Basic usage: " << std::endl
42  << " cpfind -o output_project project.pto" << std::endl
43  << " cpfind -k i0 -k i1 ... -k in project.pto" << std::endl
44  << " cpfind --kall project.pto" << std::endl
45  << std::endl << "The input project file is required." << std::endl
46  << std::endl << "General options" << std::endl
47  << " -q|--quiet Do not output progress" << std::endl
48  << " -v|--verbose Verbose output" << std::endl
49  << " -h|--help Shows this help screen" << std::endl
50  << " --version Prints the version number and exits then" << std::endl
51  << " -o|--output=<string> Sets the filename of the output file" << std::endl
52  << " (default: default.pto)" << std::endl
53  << std::endl << "Matching strategy (these options are mutually exclusive)" << std::endl
54  << " --linearmatch Enable linear images matching" << std::endl
55  << " Can be fine tuned with" << std::endl
56  << " --linearmatchlen=<int> Number of images to match (default: 1)" << std::endl
57  << " --multirow Enable heuristic multi row matching" << std::endl
58  << " default matching strategy, keep for backward reason" << std::endl
59  << " --prealigned Match only overlapping images," << std::endl
60  << " requires a rough aligned panorama" << std::endl
61  << " --allpairs Match all image pairs (slow)" << std::endl
62  << std::endl << "Feature description options" << std::endl
63  << " --sieve1width=<int> Sieve 1: Number of buckets on width (default: 10)" << std::endl
64  << " --sieve1height=<int> Sieve 1: Number of buckets on height (default: 10)" << std::endl
65  << " --sieve1size=<int> Sieve 1: Max points per bucket (default: 100)" << std::endl
66  << " --kdtreesteps=<int> KDTree: search steps (default: 200)" << std::endl
67  << " --kdtreeseconddist=<double> KDTree: distance of 2nd match (default: 0.25)" << std::endl
68  << std::endl << "Feature matching options" << std::endl
69  << " --ransaciter=<int> Ransac: iterations (default: 1000)" << std::endl
70  << " --ransacdist=<int> Ransac: homography estimation distance threshold" << std::endl
71  << " (in pixels) (default: 50)" << std::endl
72  << " --ransacmode=<string> Ransac: Select the mode used in the ransac step." << std::endl
73  << " Possible values: auto, hom, rpy, rpyv, rpyb" << std::endl
74  << " (default: auto)" << std::endl
75  << " --minmatches=<int> Minimum matches (default: 6)" << std::endl
76  << " --sieve2width=<int> Sieve 2: Number of buckets on width (default: 5)" << std::endl
77  << " --sieve2height=<int> Sieve 2: Number of buckets on height (default: 5)" << std::endl
78  << " --sieve2size=<int> Sieve 2: Max points per bucket (default: 1)" << std::endl
79  << std::endl << "Caching options" << std::endl
80  << " -c|--cache Caches keypoints to external file" << std::endl
81  << " --clean Clean up cached keyfiles" << std::endl
82  << " -p|--keypath=<string> Store keyfiles in given path" << std::endl
83  << " -k|--writekeyfile=<int> Write a keyfile for this image number" << std::endl
84  << " --kall Write keyfiles for all images in the project" << std::endl
85  << std::endl << "Advanced options" << std::endl
86  << " --celeste Masks area with clouds before running feature descriptor" << std::endl
87  << " Celeste can be fine tuned with the following parameters" << std::endl
88  << " --celestethreshold=<int> Threshold for celeste (default 0.5)" << std::endl
89  << " --celesteradius=<int> Radius for celeste (in pixels, default 20)" << std::endl
90  << " --ncores=<int> Number of threads to use (default: autodetect number of cores)" << std::endl;
91 };
92 
93 bool parseOptions(int argc, char** argv, PanoDetector& ioPanoDetector)
94 {
95  enum
96  {
97  SIEVE1WIDTH=256,
98  SIEVE1HEIGHT,
99  SIEVE1SIZE,
100  LINEARMATCH,
101  LINEARMATCHLEN,
102  MULTIROW,
103  PREALIGNED,
104  ALLPAIRS,
105  KDTREESTEPS,
106  KDTREESECONDDIST,
107  MINMATCHES,
108  RANSACMODE,
109  RANSACITER,
110  RANSACDIST,
111  SIEVE2WIDTH,
112  SIEVE2HEIGHT,
113  SIEVE2SIZE,
114  KALL,
115  CLEAN,
116  CELESTE,
117  CELESTETHRESHOLD,
118  CELESTERADIUS,
119  CPFINDVERSION
120  };
121  const char* optstring = "qvftn:o:k:cp:h";
122  static struct option longOptions[] =
123  {
124  {"quiet", no_argument, NULL, 'q' },
125  {"verbose", no_argument, NULL, 'v'},
126  {"fullscale", no_argument, NULL, 'f'},
127  {"sieve1width", required_argument, NULL, SIEVE1WIDTH},
128  {"sieve1height", required_argument, NULL, SIEVE1HEIGHT},
129  {"sieve1size", required_argument, NULL, SIEVE1SIZE},
130  {"linearmatch", no_argument, NULL, LINEARMATCH},
131  {"linearmatchlen", required_argument, NULL, LINEARMATCHLEN},
132  {"multirow", no_argument, NULL, MULTIROW},
133  {"prealigned", no_argument, NULL, PREALIGNED},
134  { "allpairs", no_argument, NULL, ALLPAIRS},
135  {"kdtreesteps", required_argument, NULL, KDTREESTEPS},
136  {"kdtreeseconddist", required_argument, NULL, KDTREESECONDDIST},
137  {"minmatches", required_argument, NULL, MINMATCHES},
138  {"ransacmode", required_argument, NULL, RANSACMODE},
139  {"ransaciter", required_argument, NULL, RANSACITER},
140  {"ransacdist", required_argument, NULL, RANSACDIST},
141  {"sieve2width", required_argument, NULL, SIEVE2WIDTH},
142  {"sieve2height", required_argument, NULL, SIEVE2HEIGHT},
143  {"sieve2size", required_argument, NULL, SIEVE2SIZE},
144  {"test", no_argument, NULL, 't'},
145  {"ncores", required_argument, NULL, 'n'},
146  {"output", required_argument, NULL, 'o'},
147  {"writekeyfile", required_argument, NULL, 'k'},
148  {"kall", no_argument, NULL, KALL},
149  {"cache", no_argument, NULL, 'c'},
150  {"clean", no_argument, NULL, CLEAN},
151  {"keypath", required_argument, NULL, 'p'},
152  {"celeste", no_argument, NULL, CELESTE},
153  {"celestethreshold", required_argument, NULL, CELESTETHRESHOLD},
154  {"celesteradius", required_argument, NULL, CELESTERADIUS},
155  {"version", no_argument, NULL, CPFINDVERSION},
156  {"help", no_argument, NULL, 'h'},
157  0
158  };
159 
160  int c;
161  int number;
162  double floatNumber;
163  std::string ransacMode;
164  std::vector<int> keyfilesIndex;
165  int doLinearMatch=0;
166  int doMultirow=0;
167  int doPrealign=0;
168  int doAllParis = 0;
169  while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
170  {
171  switch (c)
172  {
173  case 'q':
174  ioPanoDetector.setVerbose(0);
175  break;
176  case 'v':
177  ioPanoDetector.setVerbose(2);
178  break;
179  case 'f':
180  ioPanoDetector.setDownscale(false);
181  break;
182  case SIEVE1WIDTH:
183  number=atoi(optarg);
184  if(number>0)
185  {
186  ioPanoDetector.setSieve1Width(number);
187  };
188  break;
189  case SIEVE1HEIGHT:
190  number=atoi(optarg);
191  if(number>0)
192  {
193  ioPanoDetector.setSieve1Height(number);
194  };
195  break;
196  case SIEVE1SIZE:
197  number=atoi(optarg);
198  if(number>0)
199  {
200  ioPanoDetector.setSieve1Size(number);
201  };
202  break;
203  case LINEARMATCH:
204  doLinearMatch=1;
205  break;
206  case LINEARMATCHLEN:
207  number=atoi(optarg);
208  if(number>0)
209  {
210  ioPanoDetector.setLinearMatchLen(number);
211  };
212  break;
213  case MULTIROW:
214  doMultirow=1;
215  break;
216  case PREALIGNED:
217  doPrealign=1;
218  break;
219  case ALLPAIRS:
220  doAllParis = 1;
221  break;
222  case KDTREESTEPS:
223  number=atoi(optarg);
224  if(number>0)
225  {
226  ioPanoDetector.setKDTreeSearchSteps(number);
227  };
228  break;
229  case KDTREESECONDDIST:
230  floatNumber=atof(optarg);
231  if(floatNumber>0)
232  {
233  ioPanoDetector.setKDTreeSecondDistance(floatNumber);
234  };
235  break;
236  case MINMATCHES:
237  number=atoi(optarg);
238  if(number>0)
239  {
240  ioPanoDetector.setMinimumMatches(number);
241  };
242  break;
243  case RANSACMODE:
244  ransacMode = optarg;
245  std::cout << "Ransac: " << ransacMode << std::endl;
246  ransacMode=hugin_utils::tolower(ransacMode);
247  std::cout << "Ransac: " << ransacMode << std::endl;
248  if(ransacMode=="auto")
249  {
251  }
252  else
253  {
254  if(ransacMode=="hom")
255  {
257  }
258  else
259  {
260  if(ransacMode=="rpy")
261  {
263  }
264  else
265  {
266  if(ransacMode=="rpyv")
267  {
269  }
270  else
271  {
272  if(ransacMode=="rpyvb")
273  {
275  }
276  else
277  {
278  std::cout << "Warning: Invalid parameter in --ransacmode." << std::endl;
279  };
280  };
281  };
282  };
283  };
284  break;
285  case RANSACITER:
286  number=atoi(optarg);
287  if(number>0)
288  {
289  ioPanoDetector.setRansacIterations(number);
290  };
291  break;
292  case RANSACDIST:
293  number=atoi(optarg);
294  if(number>0)
295  {
296  ioPanoDetector.setRansacDistanceThreshold(number);
297  };
298  break;
299  case SIEVE2WIDTH:
300  number=atoi(optarg);
301  if(number>0)
302  {
303  ioPanoDetector.setSieve2Width(number);
304  };
305  break;
306  case SIEVE2HEIGHT:
307  number=atoi(optarg);
308  if(number>0)
309  {
310  ioPanoDetector.setSieve2Height(number);
311  };
312  break;
313  case SIEVE2SIZE:
314  number=atoi(optarg);
315  if(number>0)
316  {
317  ioPanoDetector.setSieve2Size(number);
318  };
319  break;
320  case 't':
321  ioPanoDetector.setTest(true);
322  break;
323  case 'n':
324  number=atoi(optarg);
325  if(number>0)
326  {
327  ioPanoDetector.setCores(number);
328  };
329  break;
330  case 'o':
331  ioPanoDetector.setOutputFile(optarg);
332  break;
333  case 'k':
334  number=atoi(optarg);
335  if((number==0) && (strcmp(optarg,"0")!=0))
336  {
337  std::cout << "Warning: " << optarg << " is not a valid image number of writekeyfile." << std::endl;
338  }
339  else
340  {
341  keyfilesIndex.push_back(number);
342  };
343  break;
344  case KALL:
345  ioPanoDetector.setWriteAllKeyPoints();
346  break;
347  case 'c':
348  ioPanoDetector.setCached(true);
349  break;
350  case CLEAN:
351  ioPanoDetector.setCleanup(true);
352  break;
353  case 'p':
354  ioPanoDetector.setKeyfilesPath(optarg);
355  break;
356  case CELESTE:
357  ioPanoDetector.setCeleste(true);
358  break;
359  case CELESTETHRESHOLD:
360  floatNumber=atof(optarg);
361  if(floatNumber>0.0)
362  {
363  ioPanoDetector.setCelesteThreshold(floatNumber);
364  };
365  break;
366  case CELESTERADIUS:
367  number=atoi(optarg);
368  if(number>0)
369  {
370  ioPanoDetector.setCelesteRadius(number);
371  };
372  break;
373  case CPFINDVERSION:
374  printVersion();
375  return false;
376  break;
377  case 'h':
378  printUsage();
379  return false;
380  break;
381  case ':':
382  case '?':
383  // missing argument or invalid switch
384  return false;
385  break;
386  default:
387  // this should not happen
388  abort();
389  };
390  };
391 
392  if (argc - optind != 1)
393  {
394  if (argc - optind < 1)
395  {
396  std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
397  }
398  else
399  {
400  std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
401  };
402  return false;
403  };
404  ioPanoDetector.setInputFile(argv[optind]);
405  if(doLinearMatch + doMultirow + doPrealign + doAllParis >1)
406  {
407  std::cerr << hugin_utils::stripPath(argv[0]) << ": The arguments --linearmatch, --multirow, --prealigned and --allpairs" << std::endl
408  << " are mutually exclusive. Use only one of them." << std::endl;
409  return false;
410  };
411  if(doLinearMatch)
412  {
414  };
415  if(doMultirow)
416  {
418  };
419  if(doPrealign)
420  {
422  };
423  if (doAllParis)
424  {
426  };
427  if(!keyfilesIndex.empty())
428  {
429  ioPanoDetector.setKeyPointsIdx(keyfilesIndex);
430  };
431  return true;
432 };
433 
434 int main(int argc, char** argv)
435 {
436  // create a panodetector object
437  PanoDetector aPanoDetector;
438  if(!parseOptions(argc, argv, aPanoDetector))
439  {
440  return 0;
441  }
442 
443  if (!aPanoDetector.checkData())
444  {
445  return 0;
446  }
447 
448  printVersion();
449  if (aPanoDetector.getVerbose() > 1)
450  {
451  aPanoDetector.printDetails();
452  }
453 
454  TIMETRACE("Detection",aPanoDetector.run());
455 
456  return 0;
457 
458 }
bool parseOptions(int argc, char **argv, PanoDetector &ioPanoDetector)
Definition: main.cpp:93
void setSieve2Height(int iHeight)
Definition: PanoDetector.h:199
void setVerbose(int level)
Definition: PanoDetector.h:111
void setMatchingStrategy(MatchingStrategy iMatchStrategy)
Definition: PanoDetector.h:228
void setSieve1Height(int iHeight)
Definition: PanoDetector.h:124
void setCores(int iCores)
Definition: PanoDetector.h:308
void setCached(bool iCached)
Definition: PanoDetector.h:264
void setKDTreeSecondDistance(double iDist)
Definition: PanoDetector.h:149
void setCleanup(bool iCleanup)
Definition: PanoDetector.h:272
int getVerbose() const
Definition: PanoDetector.h:115
void setSieve2Width(int iWidth)
Definition: PanoDetector.h:195
void setDownscale(bool iDown)
Definition: PanoDetector.h:241
#define TIMETRACE(TEXT, CODE)
Definition: Utils.h:32
void setSieve1Size(int iSize)
Definition: PanoDetector.h:128
void printUsage()
Definition: main.cpp:37
void setLinearMatchLen(int iLen)
Definition: PanoDetector.h:220
void printVersion()
Definition: main.cpp:31
void setKeyPointsIdx(std::vector< int > keyPointsIdx)
Definition: PanoDetector.h:94
void setKDTreeSearchSteps(int iSteps)
Definition: PanoDetector.h:145
void setSieve1Width(int iWidth)
Definition: PanoDetector.h:120
void setTest(bool iTest)
Definition: PanoDetector.h:300
void setCelesteThreshold(double iCelesteThreshold)
Definition: PanoDetector.h:288
void setOutputFile(const std::string &outputFile)
Definition: PanoDetector.h:247
void setSieve2Size(int iSize)
Definition: PanoDetector.h:203
void setRansacDistanceThreshold(int iDT)
Definition: PanoDetector.h:170
void setWriteAllKeyPoints(bool writeAllKeyPoints=true)
Definition: PanoDetector.h:102
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:907
void setCelesteRadius(int iCelesteRadius)
Definition: PanoDetector.h:296
void setMinimumMatches(int iMatches)
Definition: PanoDetector.h:162
void setRansacIterations(int iIters)
Definition: PanoDetector.h:166
void setKeyfilesPath(const std::string &keypath)
Definition: PanoDetector.h:256
void setInputFile(const std::string &inputFile)
Definition: PanoDetector.h:252
void setCeleste(bool iCeleste)
Definition: PanoDetector.h:280
std::string tolower(const std::string &s)
convert a string to lowercase
Definition: stl_utils.h:49
void setRansacMode(HuginBase::RANSACOptimizer::Mode mode)
Definition: PanoDetector.h:174
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition: utils.cpp:160
void printDetails()
int main(int argc, char *argv[])
Definition: Main.cpp:167