Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
vig_optimize.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
27 #include <hugin_config.h>
28 #include <fstream>
29 #include <sstream>
30 
32 #include "ExtractPoints.h"
33 #include <getopt.h>
34 #include <hugin_basic.h>
35 #include <nona/Stitcher.h>
36 
37 #include <tiff.h>
38 
39 static void usage(const char* name)
40 {
41  std::cout << name << ": Try to determine the radial vignetting" << std::endl
42  << "vig_optimize version " << hugin_utils::GetHuginVersion() << std::endl
43  << std::endl
44  << "Usage: " << name << " [options] -o output.pto input.pto" << std::endl
45  << "Valid options are:" << std::endl
46  << " -o|--output file write results to output project" << std::endl
47  << " -v|--verbose Verbose, print progress messages" << std::endl
48  << " -p n Number of points to extract" << std::endl
49  << " -s level Work on downscaled images, every step halves width and height" << std::endl
50  << " -h|--help Display help (this text)" << std::endl
51  << std::endl
52  << " Expert and debugging options:" << std::endl
53  << " -i file Read corresponding points from file" << std::endl
54  << " -w file Dump corresponding points to file" << std::endl;
55 }
56 
57 
58 /*
59 template<class RIMG>
60 void importROIImage(ImageImportInfo & info, RIMG & img)
61 {
62  vigra::Rect2D roi(Point2D(info.getPosition()), info.size());
63  img.resize(roi);
64  importImageAlpha(info, destImage(img.m_image), destImage(img.m_mask));
65 }
66 */
67 
68 
69 void loadPointsC(FILE* f, std::vector<vigra_ext::PointPairRGB>& vec)
70 {
71  double dummy1, dummy2;
73  double i1, i2;
74 
75  int n=0;
76  do
77  {
78  n = fscanf(f, " %lf %lf %lf %lf %lf %lf %f %f %f %f %f %f %lf %f %f %lf",
79  &i1, &i2, &(point.p1.x), &(point.p1.y),
80  &(point.p2.x), &(point.p2.y),
81  &(point.i1.red()), &(point.i1.green()), &(point.i1.blue()),
82  &(point.i2.red()), &(point.i2.green()), &(point.i2.blue()),
83  // matlab index.. set to zero
84  &dummy1,
85  &(point.r1), &(point.r2),
86  // edge score at this point, zero so far
87  &(dummy2) );
88 
89 
90  point.imgNr1 = hugin_utils::roundi(i1);
91  point.imgNr2 = hugin_utils::roundi(i2);
92  if (n==16)
93  {
94  vec.push_back(point);
95  }
96  }
97  while (n == 16);
98 }
99 
100 void loadPoints(std::istream& i, std::vector<vigra_ext::PointPairRGB>& vec )
101 {
102  while(!i.eof() && i.good())
103  {
104  double dummy1, dummy2;
106  double i1, i2;
107  i >> i1 >> i2
108  >> point.p1.x >> point.p1.y
109  >> point.p2.x >> point.p2.y
110  >> point.i1.red() >> point.i1.green() >> point.i1.blue()
111  >> point.i2.red() >> point.i2.green() >> point.i2.blue()
112  // matlab index.. set to zero
113  >> dummy1
114  >> point.r1 >> point.r2
115  // edge score at this point, zero so far
116  >> dummy2;
117  point.imgNr1 = hugin_utils::roundi(i1);
118  point.imgNr2 = hugin_utils::roundi(i2);
119  if (i.good())
120  {
121  vec.push_back(point);
122  }
123  }
124 }
125 
127 {
129 
130  for (HuginBase::OptimizeVector::const_iterator it = vars.begin(); it != vars.end(); ++it)
131  {
132  for (std::set<std::string>::const_iterator itv = (*it).begin();
133  itv != (*it).end(); ++itv)
134  {
135  if ((*itv)[0] == 'E' || (*itv)[0] == 'R' || (*itv)[0] == 'V')
136  {
137  return true;
138  }
139  }
140  }
141  return false;
142 }
143 
144 
145 int main(int argc, char* argv[])
146 {
147  AppBase::StreamProgressDisplay progressDisplay(std::cout);
148 
149  // parse arguments
150  const char* optstring = "hi:o:p:s:vw:";
151  static struct option longOptions[] =
152  {
153  { "output", required_argument, NULL, 'o' },
154  { "verbose", no_argument, NULL, 'v' },
155  { "help", no_argument, NULL, 'h' },
156  0
157  };
158  int c;
159 
160  int pyrLevel=3;
161  int verbose = 0;
162  int nPoints = 200;
163  std::string outputFile;
164  std::string outputPointsFile;
165  std::string inputPointsFile;
166  while ((c = getopt_long(argc, argv, optstring, longOptions, nullptr)) != -1)
167  {
168  switch (c)
169  {
170  case 'i':
171  inputPointsFile = optarg;
172  break;
173  case 'o':
174  outputFile = optarg;
175  break;
176  case 'p':
177  nPoints = atoi(optarg);
178  break;
179  case 's':
180  pyrLevel = atoi(optarg);
181  break;
182  case 'v':
183  verbose++;
184  break;
185  case 'h':
186  usage(hugin_utils::stripPath(argv[0]).c_str());
187  return 1;
188  case 'w':
189  outputPointsFile = optarg;
190  break;
191  case ':':
192  case '?':
193  // missing argument or invalid switch
194  return 1;
195  break;
196  default:
197  // this should not happen
198  abort();
199  }
200  };
201 
202  unsigned nFiles = argc - optind;
203  if (nFiles != 1)
204  {
205  if (nFiles< 1)
206  {
207  std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
208  }
209  else
210  {
211  std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
212  };
213  return 1;
214  };
215 
216  const char* scriptFile = argv[optind];
217  HuginBase::Panorama pano;
218  if (!pano.ReadPTOFile(scriptFile, hugin_utils::getPathPrefix(scriptFile)))
219  {
220  return 1;
221  };
222 
223  // Ensure photometric parameters are selected for optimizaion
224  if (!hasphotometricParams(pano))
225  {
226  std::cerr << "ERROR:no photometric parameters were selected for optimization" << std::endl;
227  std::cerr << "please update 'v' line in .pto script and try again." << std::endl;
228  return 1;
229  }
230 
231  // suppress tiff warnings
232  TIFFSetWarningHandler(0);
233 
234  // todo: handle images with alpha masks
235  try
236  {
237  std::vector<vigra_ext::PointPairRGB> points;
238 
239  float imageStepSize = 1 / 255.0f;
240  if (inputPointsFile != "" )
241  {
242  //ifstream ifs(inputPointsFile.c_str());
243  //loadPoints(ifs, points);
244  FILE* f = fopen(inputPointsFile.c_str(), "r");
245  if (f == 0)
246  {
247  perror("Could not open input point file");
248  return 1;
249  }
250  loadPointsC(f, points);
251  fclose(f);
252  }
253  else
254  {
255  loadImgsAndExtractPoints(pano, nPoints, pyrLevel, true, progressDisplay, points, verbose, imageStepSize);
256  }
257  if (verbose)
258  {
259  std::cout << "\rSelected " << points.size() << " points" << std::endl;
260  }
261  if (points.empty())
262  {
263  std::cerr << "Error: no overlapping points found, exiting" << std::endl;
264  return 1;
265  }
266 
267  if (!outputPointsFile.empty())
268  {
269  std::ofstream of(outputPointsFile.c_str());
270  for (std::vector<vigra_ext::PointPairRGB>::iterator it = points.begin(); it != points.end(); ++it)
271  {
272  of << (*it).imgNr1 << " " << (*it).imgNr2 << " "
273  << (*it).p1.x << " " << (*it).p1.y<< " "
274  << (*it).p2.x << " " << (*it).p2.y<< " "
275  << (*it).i1.red() << " " << (*it).i1.green() << " " << (*it).i1.blue() << " "
276  << (*it).i2.red() << " " << (*it).i2.green() << " " << (*it).i2.blue() << " "
277  // matlab index.. set to zero
278  << 0 << " "
279  << (*it).r1 << " " << (*it).r2 << " "
280  // edge score at this point, zero so far
281  << 0 << std::endl;
282  }
283  }
284 
285 
286  progressDisplay.setMessage("Vignetting Optimization");
287  HuginBase::PhotometricOptimizer photoopt(pano, &progressDisplay, pano.getOptimizeVector(), points, imageStepSize);
288  photoopt.run();
289  // double error = photoopt.getResultError();
290 
291  progressDisplay.taskFinished();
292 
293  // save project
294  outputFile = hugin_utils::GetOutputFilename(outputFile, scriptFile, "vig");
295  pano.WritePTOFile(outputFile, hugin_utils::getPathPrefix(outputFile));
296 
297  }
298  catch (std::exception& e)
299  {
300  std::cerr << "caught exception: " << e.what() << std::endl;
301  return 1;
302  }
303  return 0;
304 }
int roundi(T x)
Definition: hugin_math.h:73
bool hasphotometricParams(HuginBase::Panorama &pano)
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition: utils.cpp:420
hugin_utils::FDiff2D p1
Definition: utils.h:122
virtual void run()
runs the algorithm.
void loadImgsAndExtractPoints(HuginBase::Panorama pano, int nPoints, int pyrLevel, bool randomPoints, AppBase::ProgressDisplay &progress, std::vector< vigra_ext::PointPairRGB > &points, int verbose, float &imageStepSize)
Model for a panorama.
Definition: Panorama.h:152
void loadPointsC(FILE *f, std::vector< vigra_ext::PointPairRGB > &vec)
void taskFinished()
call when a task has finished and the status message should be cleared
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
const OptimizeVector & getOptimizeVector() const
return the optimize settings stored inside panorama
Definition: Panorama.h:454
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Definition: Panorama.cpp:2023
void setMessage(const std::string &message, const std::string &filename="")
sets the message to given string
hugin_utils::FDiff2D p2
Definition: utils.h:126
Contains various routines used for stitching panoramas.
static void usage()
Definition: Main.cpp:32
helper procedure for photometric optimizer on command line
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:920
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
std::vector< std::set< std::string > > OptimizeVector
a progress display to print progress reports to a stream
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 loadPoints(std::istream &i, std::vector< vigra_ext::PointPairRGB > &vec)
int main(int argc, char *argv[])
Definition: Main.cpp:167