Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AutoCtrlPointCreator.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
25 #include "hugin_config.h"
26 
27 #include "panoinc_WX.h"
28 #include "panoinc.h"
29 
30 #include <fstream>
31 #if defined (__GNUC__) && !defined (__FreeBSD__) && !defined (__clang__)
32 #include <ext/stdio_filebuf.h>
33 #endif
34 
36 
37 #include <hugin_utils/platform.h>
38 #include <wx/app.h>
39 #include "hugin/config_defaults.h"
45 
47 #include "base_wx/platform.h"
48 #include "base_wx/huginConfig.h"
49 #include "base_wx/wxPlatform.h"
50 #include "base_wx/wxutils.h"
51 #include <wx/utils.h>
52 #if defined __WXMSW__ || defined UNIX_SELF_CONTAINED_BUNDLE
53 #include <wx/stdpaths.h>
54 #endif
55 
56 // somewhere SetDesc gets defined.. this breaks wx/cmdline.h on OSX
57 #ifdef SetDesc
58 #undef SetDesc
59 #endif
60 
61 #include <wx/cmdline.h>
62 
63 #if defined MAC_SELF_CONTAINED_BUNDLE
64  #include <wx/dir.h>
65  #include <CoreFoundation/CFBundle.h>
66 #endif
67 
68 void CPMessage(const wxString message,const wxString caption, wxWindow *parent)
69 {
70  if(parent!=NULL)
71  {
72  hugin_utils::HuginMessageBox(message, caption, wxOK | wxICON_ERROR, parent);
73  }
74  else
75  {
76  std::cout << message << std::endl;
77  }
78 };
79 
80 int CPExecute(wxString prog, wxString args, wxString caption, wxWindow *parent)
81 {
82  if(parent!=NULL)
83  {
84  return MyExecuteCommandOnDialog(prog, args, parent, caption);
85  }
86  else
87  {
88  wxString cmdline=prog+" "+args;
89  return wxExecute(cmdline,wxEXEC_SYNC | wxEXEC_MAKE_GROUP_LEADER);
90  };
91 };
92 
94  HuginBase::Panorama & pano, const HuginBase::UIntSet & imgs, bool reordered)
95 {
96  std::ifstream stream(file.c_str());
97  if (! stream.is_open()) {
98  DEBUG_ERROR("Could not open control point detector output: " << file);
99  return HuginBase::CPVector();
100  }
101 
102  HuginBase::Panorama tmpp;
104  int ptoVersion = 0;
105  newPano.loadPTScript(stream, ptoVersion, "");
106  tmpp.setMemento(newPano);
107 
108  //check if sizes matches
109  if(tmpp.getNrOfImages()!=imgs.size())
110  {
111  return HuginBase::CPVector();
112  };
113 
114  // create mapping between the panorama images.
115  std::map<unsigned int, unsigned int> imgMapping;
116 
117  // create mapping between the panorama images.
118  if (reordered) {
119  for (unsigned int ni = 0; ni < tmpp.getNrOfImages(); ni++) {
120  std::string nname = hugin_utils::stripPath(tmpp.getImage(ni).getFilename());
121  for(HuginBase::UIntSet::const_iterator it=imgs.begin();it!=imgs.end();++it) {
122  std::string oname = hugin_utils::stripPath(pano.getImage(*it).getFilename());
123  if (nname == oname) {
124  // insert image
125  imgMapping[ni] = *it;
126  break;
127  }
128  }
129  if (! set_contains(imgMapping, ni)) {
130  DEBUG_ERROR("Could not find image " << ni << ", name: " << tmpp.getImage(ni).getFilename() << " in autopano output");
131  return HuginBase::CPVector();
132  }
133  }
134  } else {
135  size_t i=0;
136  for(HuginBase::UIntSet::const_iterator it=imgs.begin();it!=imgs.end();++it)
137  {
138  imgMapping[i++]=*it;
139  };
140  }
141 
142  // get control points
143  HuginBase::CPVector ctrlPoints = tmpp.getCtrlPoints();
144  // make sure they are in correct order
145  for (HuginBase::CPVector::iterator it = ctrlPoints.begin(); it != ctrlPoints.end(); ++it) {
146  (*it).image1Nr = imgMapping[(*it).image1Nr];
147  (*it).image2Nr = imgMapping[(*it).image2Nr];
148  }
149 
150  return ctrlPoints;
151 }
152 
153 #if defined MAC_SELF_CONTAINED_BUNDLE
154 wxString GetBundledProg(wxString progName)
155 {
156  // First check inside the bundle for (AutoCP generator "without path"), e.g. binary name with path stripped off
157  wxFileName file(progName);
158  // if executable contains no path, look inside bundle, if program can be found there
159  if(file.GetPath().IsEmpty())
160  //return MacGetPathToBundledResourceFile(MacCreateCFStringWithWxString(progName));
161  return MacGetPathToBundledExecutableFile(MacCreateCFStringWithWxString(progName));
162  return wxEmptyString;
163 }
164 #endif
165 
166 wxString GetProgPath(wxString progName)
167 {
168 #if defined MAC_SELF_CONTAINED_BUNDLE
169  wxString bundled=GetBundledProg(progName);
170  if(!bundled.IsEmpty())
171  return bundled;
172 #else
173 #if defined __WXMSW__ || defined UNIX_SELF_CONTAINED_BUNDLE
174  wxFileName prog(progName);
175  if(prog.IsAbsolute())
176  {
177  return progName;
178  }
179  else
180  {
181  wxPathList pathlist;
182  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
183  pathlist.Add(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
184  pathlist.AddEnvList("PATH");
185  return pathlist.FindAbsoluteValidPath(progName);
186  };
187 #endif
188 #endif
189  return progName;
190 };
191 
192 bool CanStartProg(wxString progName,wxWindow* parent)
193 {
194 #if defined MAC_SELF_CONTAINED_BUNDLE
195  if(!GetBundledProg(progName).IsEmpty())
196  return true;
197 #endif
198  wxFileName prog(progName);
199  bool canStart=false;
200  if(prog.IsAbsolute())
201  {
202  canStart=(prog.IsFileExecutable());
203  }
204  else
205  {
206  wxPathList pathlist;
207 #if defined __WXMSW__ || defined UNIX_SELF_CONTAINED_BUNDLE
208  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
209  pathlist.Add(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
210 #endif
211  pathlist.AddEnvList("PATH");
212  wxString path = pathlist.FindAbsoluteValidPath(progName);
213  if(path.IsEmpty())
214  canStart=false;
215  else
216  {
217  wxFileName prog2(path);
218  canStart=(prog2.IsFileExecutable());
219  };
220  };
221  if(!canStart)
222  CPMessage(wxString::Format(
223  _("Could not find \"%s\" in path.\nMaybe you have not installed it properly or given a wrong path in the settings."),progName.c_str()),
224  _("Error"),parent);
225  return canStart;
226 };
227 
229 {
230  wxString tempDir = wxConfigBase::Get()->Read("tempDir", wxEmptyString);
231  if (!tempDir.IsEmpty())
232  {
233  if (tempDir.Last() != wxFileName::GetPathSeparator())
234  {
235  tempDir.Append(wxFileName::GetPathSeparator());
236  };
237  };
238  return tempDir;
239 };
240 
242  int nFeatures, wxWindow *parent)
243 {
244  int return_value;
245  return automatch(setting,pano,imgs,nFeatures,return_value,parent);
246 };
247 
249  HuginBase::Panorama & pano,
250  const HuginBase::UIntSet & imgs,
251  int nFeatures,
252  int & ret_value,
253  wxWindow *parent)
254 {
256  CPDetectorType t = setting.GetType();
257  //check, if the cp generators exists
258  if(!CanStartProg(setting.GetProg(),parent))
259  return cps;
260  if(setting.IsTwoStepDetector())
261  if(!CanStartProg(setting.GetProgMatcher(),parent))
262  return cps;
264  if(!setting.GetProgStack().IsEmpty())
265  if(!CanStartProg(setting.GetProgStack(),parent))
266  return cps;
267  //change locale for correct numeric output
268  char * p = setlocale(LC_NUMERIC,NULL);
269  char * old_locale = strdup(p);
270  setlocale(LC_NUMERIC,"C");
271  switch (t) {
272  case CPDetector_AutoPano:
273  {
274  // autopano@kolor
275  AutoPanoKolor matcher;
276  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
277  break;
278  }
280  {
281  // autopano-sift
282  AutoPanoSift matcher;
283  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
284  break;
285  }
287  {
288  // autopano-sift with stacks
289  AutoPanoSiftStack matcher;
290  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
291  break;
292  }
294  {
295  // autopano-sift for multi-row panoramas
296  AutoPanoSiftMultiRow matcher;
297  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
298  break;
299  }
301  {
302  // autopano-sift for multi-row panoramas with stacks
304  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
305  break;
306  }
308  {
309  // autopano-sift for panoramas with position information
310  AutoPanoSiftPreAlign matcher;
311  cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
312  break;
313  }
314  default:
315  DEBUG_ERROR("Invalid autopano type");
316  }
317  setlocale(LC_NUMERIC,old_locale);
318  free(old_locale);
319  return cps;
320 }
321 
323  std::vector<wxString> &keyFiles, wxWindow *parent)
324 {
325  if(setting.IsTwoStepDetector())
326  {
327  if(!keyFiles.empty())
328  {
329  for(unsigned int i=0;i<keyFiles.size();i++)
330  {
331  if(wxFileExists(keyFiles[i]))
332  {
333  if(!wxRemoveFile(keyFiles[i]))
334  {
335  DEBUG_DEBUG("could not remove temporary file: " << keyFiles[i].c_str());
336  };
337  };
338  };
339  };
340  }
341  else
342  {
343  if(!setting.IsCleanupPossible())
344  {
345  return;
346  };
347  // create suitable command line..
348  wxString cleanupExe = GetProgPath(setting.GetProg());
349  wxString cleanupArgs = setting.GetArgsCleanup();
350  if(cleanupArgs.IsEmpty())
351  {
352  return;
353  };
354 
355  wxString ptoinfile_name = wxFileName::CreateTempFileName(GetCheckedTempDir() + ("ap_inproj"));
356  cleanupArgs.Replace("%s", hugin_utils::wxQuoteFilename(ptoinfile_name));
357  std::ofstream ptoinstream(ptoinfile_name.mb_str(wxConvFile));
358  pano.printPanoramaScript(ptoinstream, pano.getOptimizeVector(), pano.getOptions(), imgs, false);
359 
360  int ret_value=CPExecute(cleanupExe, cleanupArgs, _("cleaning up temporary keypoint files"), parent);
361 
362  if(ret_value!=0)
363  {
364  DEBUG_DEBUG("could not cleanup temporary keypoint files");
365  };
366  if(!wxRemoveFile(ptoinfile_name))
367  {
368  DEBUG_DEBUG("could not remove temporary file: " << ptoinfile_name.c_str());
369  };
370  };
371 };
372 
374  int nFeatures, int & ret_value, wxWindow *parent)
375 {
377  if (imgs.empty()) {
378  return cps;
379  }
380  // create suitable command line..
381  const wxString autopanoExe = GetProgPath(setting.GetProg());
382  // special cases
383  // geocpset needs other control points to link only unlinked images
384  // linefind needs other control points to correctly ignore nadir/zenit near images
385  // (but only when all images are selected, ignore this limitation when user
386  // selected certain images
387  // cpfind with prealigned setting
388  const bool detectorNeedsOtherCp = (autopanoExe.Find("geocpset") != wxNOT_FOUND) ||
389  (autopanoExe.Find("linefind") != wxNOT_FOUND && pano.getNrOfImages()==imgs.size()) ||
390  (autopanoExe.Find("cpfind") != wxNOT_FOUND && setting.GetArgs().Find("--prealigned") != wxNOT_FOUND);
391  size_t oldCpsSize = -1;
392  if(setting.IsTwoStepDetector())
393  {
394  std::vector<wxString> keyFiles(pano.getNrOfImages());
395  cps=automatch(setting, pano, imgs, nFeatures, keyFiles, ret_value, parent);
396  Cleanup(setting, pano, imgs, keyFiles, parent);
397  return cps;
398  };
399  wxString autopanoArgs = setting.GetArgs();
400 
401  // generate hash for all old cps
402  std::set<std::string> cpsHash;
403  {
404  const HuginBase::CPVector& cps = pano.getCtrlPoints();
405  for (auto& cp : cps)
406  {
407  cpsHash.insert(cp.getCPString());
408  };
409  };
410 
411  // TODO: create a secure temporary filename here
412  wxString ptofile = wxFileName::CreateTempFileName(GetCheckedTempDir() + "ap_res");
413  autopanoArgs.Replace("%o", hugin_utils::wxQuoteFilename(ptofile));
414  wxString tmp;
415  tmp.Printf("%d", nFeatures);
416  autopanoArgs.Replace("%p", tmp);
417 
418  HuginBase::SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
419  tmp.Printf("%f", firstImg.getHFOV());
420  autopanoArgs.Replace("%v", tmp);
421 
422  tmp.Printf("%d", (int) firstImg.getProjection());
423  autopanoArgs.Replace("%f", tmp);
424 
425  long idx = autopanoArgs.Find("%namefile") ;
426  DEBUG_DEBUG("find %namefile in '"<< autopanoArgs.mb_str(wxConvLocal) << "' returned: " << idx);
427  bool use_namefile = idx >=0;
428  idx = autopanoArgs.Find("%i");
429  DEBUG_DEBUG("find %i in '"<< autopanoArgs.mb_str(wxConvLocal) << "' returned: " << idx);
430  bool use_params = idx >=0;
431  idx = autopanoArgs.Find("%s");
432  bool use_inputscript = idx >=0;
433 
434  if (! (use_namefile || use_params || use_inputscript)) {
435  CPMessage(_("Please use %namefile, %i or %s to specify the input files for the control point detector"),
436  _("Error in control point detector command"), parent);
437  return cps;
438  }
439 
440  wxFile namefile;
441  wxString namefile_name;
442  if (use_namefile) {
443  // create temporary file with image names.
444  namefile_name = wxFileName::CreateTempFileName(GetCheckedTempDir() + "ap_imgnames", &namefile);
445  DEBUG_DEBUG("before replace %namefile: " << autopanoArgs.mb_str(wxConvLocal));
446  autopanoArgs.Replace("%namefile", hugin_utils::wxQuoteFilename(namefile_name));
447  DEBUG_DEBUG("after replace %namefile: " << autopanoArgs.mb_str(wxConvLocal));
448  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
449  {
450  namefile.Write(wxString(pano.getImage(*it).getFilename().c_str(), HUGIN_CONV_FILENAME));
451  namefile.Write("\r\n");
452  }
453  // close namefile
454  if (namefile_name != wxString(wxEmptyString)) {
455  namefile.Close();
456  }
457  } else {
458  std::string imgFiles;
459  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
460  {
461  imgFiles.append(" ").append(hugin_utils::quoteFilename(pano.getImage(*it).getFilename()));
462  }
463  autopanoArgs.Replace("%i", wxString (imgFiles.c_str(), HUGIN_CONV_FILENAME));
464  }
465 
466  wxString ptoinfile_name;
467  if (use_inputscript) {
468  wxFile ptoinfile;
469  ptoinfile_name = wxFileName::CreateTempFileName(GetCheckedTempDir() + ("ap_inproj"));
470  autopanoArgs.Replace("%s", hugin_utils::wxQuoteFilename(ptoinfile_name));
471 
472  std::ofstream ptoinstream(ptoinfile_name.mb_str(wxConvFile));
473  // create a temporary project with only the selected images
474  HuginBase::Panorama tempPano = pano.getSubset(imgs);
475  if (detectorNeedsOtherCp)
476  {
477  // when the cp generator needs the other cps to work
478  // store the number of cps in the input project
479  oldCpsSize = tempPano.getNrOfCtrlPoints();
480  }
481  else
482  {
483  // in all other cases delete all cps
484  HuginBase::CPVector emptyCPV;
485  tempPano.setCtrlPoints(emptyCPV);
486  };
487  HuginBase::UIntSet tempImgSet;
488  fill_set(tempImgSet, 0, tempPano.getNrOfImages() - 1);
489  tempPano.printPanoramaScript(ptoinstream, tempPano.getOptimizeVector(), tempPano.getOptions(), tempImgSet, false);
490  }
491 
492 #ifdef __WXMSW__
493  if (autopanoArgs.size() > 32000) {
494  CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
495  _("Too many images selected"), parent );
496  return cps;
497  }
498 #endif
499 
500  wxString cmd = autopanoExe + " " + autopanoArgs;
501  DEBUG_DEBUG("Executing: " << autopanoExe.mb_str(wxConvLocal) << " " << autopanoArgs.mb_str(wxConvLocal));
502 
503  wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(autopanoArgs);
504  if (arguments.GetCount() > 127) {
505  DEBUG_ERROR("Too many arguments for call to wxExecute()");
506  DEBUG_ERROR("Try using the %%s parameter in preferences");
507  CPMessage(wxString::Format(_("Too many arguments (images). Try using the %%s parameter in preferences.\n\n Could not execute command: %s"), autopanoExe.c_str()), _("wxExecute Error"), parent);
508  return cps;
509  }
510 
511  ret_value = 0;
512  // use MyExternalCmdExecDialog
513  ret_value = CPExecute(autopanoExe, autopanoArgs, _("finding control points"), parent);
514 
515  if (ret_value == HUGIN_EXIT_CODE_CANCELLED) {
516  return cps;
517  } else if (ret_value == -1) {
518  CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
519  return cps;
520  } else if (ret_value > 0) {
521  CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
522  _("wxExecute Error"), parent);
523  return cps;
524  }
525 
526  if (! wxFileExists(ptofile.c_str())) {
527  CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
528  _("Control point detector failure"), parent );
529  return cps;
530  }
531 
532  // read and update control points
533  cps = readUpdatedControlPoints((const char*)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, !use_inputscript);
534  if (detectorNeedsOtherCp && oldCpsSize >= 0)
535  {
536  // for geocpset/cpfind --prealigned remove all old cps from the vector
537  cps.erase(cps.begin(), cps.begin() + oldCpsSize);
538  };
539  // now check that the new cp are unique
540  if (!cps.empty())
541  {
542  size_t i = cps.size() - 1;
543  for (auto it = cps.rbegin(); it != cps.rend(); ++it, --i)
544  {
545  if (set_contains(cpsHash, it->getCPString()))
546  {
547  // remove duplicates
548  cps.erase(cps.begin() + i);
549  };
550  };
551  };
552 
553  if (namefile_name != wxString(wxEmptyString)) {
554  namefile.Close();
555  wxRemoveFile(namefile_name);
556  }
557 
558  if (ptoinfile_name != wxString(wxEmptyString)) {
559  wxRemoveFile(ptoinfile_name);
560  }
561 
562  if (!wxRemoveFile(ptofile)) {
563  DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
564  }
565 
566  return cps;
567 }
568 
570  int nFeatures, std::vector<wxString> &keyFiles, int & ret_value, wxWindow *parent)
571 {
573  if (imgs.empty())
574  {
575  return cps;
576  }
577  DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages());
578  // create suitable command line..
579  wxString generateKeysExe=GetProgPath(setting.GetProg());
580  wxString matcherExe = GetProgPath(setting.GetProgMatcher());
581  wxString generateKeysArgs=setting.GetArgs();
582  wxString matcherArgs = setting.GetArgsMatcher();
583 
584  //check arguments
585  if(generateKeysArgs.Find("%i")==wxNOT_FOUND || generateKeysArgs.Find("%k")==wxNOT_FOUND)
586  {
587  CPMessage(_("Please use %i to specify the input files and %k to specify the keypoint file for the generate keys step"),
588  _("Error in control point detector command"), parent);
589  return cps;
590  };
591  if(matcherArgs.Find("%k")==wxNOT_FOUND || matcherArgs.Find("%o")==wxNOT_FOUND)
592  {
593  CPMessage(_("Please use %k to specify the keypoint files and %o to specify the output project file for the matching step"),
594  _("Error in control point detector command"), parent);
595  return cps;
596  };
597 
598  ret_value=0;
599  const wxString tempDir = GetCheckedTempDir();
600  for (HuginBase::UIntSet::const_iterator img = imgs.begin(); img != imgs.end(); ++img)
601  {
602  if(keyFiles[*img].IsEmpty())
603  {
604  //no key files exists, so generate it
605  wxString keyfile=wxFileName::CreateTempFileName(tempDir+"apk_");
606  keyFiles[*img]=keyfile;
607  wxString cmd=generateKeysArgs;
608  wxString tmp;
609  tmp.Printf("%d", nFeatures);
610  cmd.Replace("%p", tmp);
611 
612  HuginBase::SrcPanoImage srcImg = pano.getSrcImage(*img);
613  tmp.Printf("%f", srcImg.getHFOV());
614  cmd.Replace("%v", tmp);
615 
616  tmp.Printf("%d", (int) srcImg.getProjection());
617  cmd.Replace("%f", tmp);
618 
619  cmd.Replace("%i",hugin_utils::wxQuoteFilename(wxString(srcImg.getFilename().c_str(), HUGIN_CONV_FILENAME)));
620  cmd.Replace("%k",hugin_utils::wxQuoteFilename(keyfile));
621  // use MyExternalCmdExecDialog
622  ret_value = CPExecute(generateKeysExe, cmd, _("generating key file"), parent);
623  cmd=generateKeysExe+" "+cmd;
624  if (ret_value == HUGIN_EXIT_CODE_CANCELLED)
625  return cps;
626  else
627  if (ret_value == -1)
628  {
629  CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
630  return cps;
631  }
632  else
633  if (ret_value > 0)
634  {
635  CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
636  _("wxExecute Error"), parent);
637  return cps;
638  };
639  };
640  };
641 
642  // TODO: create a secure temporary filename here
643  wxString ptofile = wxFileName::CreateTempFileName(GetCheckedTempDir() + "ap_res");
644  matcherArgs.Replace("%o", hugin_utils::wxQuoteFilename(ptofile));
645  wxString tmp;
646  tmp.Printf("%d", nFeatures);
647  matcherArgs.Replace("%p", tmp);
648 
649  HuginBase::SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
650  tmp.Printf("%f", firstImg.getHFOV());
651  matcherArgs.Replace("%v", tmp);
652 
653  tmp.Printf("%d", (int) firstImg.getProjection());
654  matcherArgs.Replace("%f", tmp);
655 
656  wxString imgFiles;
657  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
658  {
659  imgFiles.append(" ").append(hugin_utils::wxQuoteFilename(keyFiles[*it]));
660  };
661  matcherArgs.Replace("%k", wxString (imgFiles.wc_str(), HUGIN_CONV_FILENAME));
662 
663 #ifdef __WXMSW__
664  if (matcherArgs.size() > 32000) {
665  CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
666  _("Too many images selected"), parent );
667  return cps;
668  }
669 #endif
670 
671  wxString cmd = matcherExe + " " + matcherArgs;
672  DEBUG_DEBUG("Executing: " << matcherExe.mb_str(wxConvLocal) << " " << matcherArgs.mb_str(wxConvLocal));
673 
674  wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(matcherArgs);
675  if (arguments.GetCount() > 127) {
676  DEBUG_ERROR("Too many arguments for call to wxExecute()");
677  CPMessage(wxString::Format(_("Too many arguments (images). Try using a cp generator setting which supports the %%s parameter in preferences.\n\n Could not execute command: %s"), matcherExe.c_str()), _("wxExecute Error"), parent);
678  return cps;
679  }
680 
681  // use MyExternalCmdExecDialog
682  ret_value = CPExecute(matcherExe, matcherArgs, _("finding control points"), parent);
683 
684  if (ret_value == HUGIN_EXIT_CODE_CANCELLED)
685  return cps;
686  else
687  if (ret_value == -1)
688  {
689  CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
690  return cps;
691  }
692  else
693  if (ret_value > 0)
694  {
695  CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
696  _("wxExecute Error"), parent);
697  return cps;
698  };
699 
700  if (! wxFileExists(ptofile.c_str()))
701  {
702  CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
703  _("Control point detector failure"), parent );
704  return cps;
705  }
706 
707  // read and update control points
708  cps = readUpdatedControlPoints((const char *)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, true);
709 
710  if (!wxRemoveFile(ptofile)) {
711  DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
712  }
713 
714  return cps;
715 };
716 
718  int nFeatures, int & ret_value, wxWindow *parent)
719 {
721  wxString autopanoExe = setting.GetProg();
722 
723  // write default autopano.kolor.com flags
724  wxString autopanoArgs = setting.GetArgs();
725 
726  std::string imgFiles;
727  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
728  {
729  imgFiles.append(" ").append(hugin_utils::quoteFilename(pano.getImage(*it).getFilename()));
730  }
731 
732  wxString ptofilepath = wxFileName::CreateTempFileName(GetCheckedTempDir() + "ap_res");
733  wxFileName ptofn(ptofilepath);
734  wxString ptofile = ptofn.GetFullName();
735  autopanoArgs.Replace("%o", hugin_utils::wxQuoteFilename(ptofile));
736  wxString tmp;
737  tmp.Printf("%d", nFeatures);
738  autopanoArgs.Replace("%p", tmp);
739  HuginBase::SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
740  tmp.Printf("%f", firstImg.getHFOV());
741  autopanoArgs.Replace("%v", tmp);
742 
743  tmp.Printf("%d", (int) firstImg.getProjection());
744  autopanoArgs.Replace("%f", tmp);
745 
746  autopanoArgs.Replace("%i", wxString (imgFiles.c_str(), HUGIN_CONV_FILENAME));
747 
748  wxString tempdir = ptofn.GetPath();
749  autopanoArgs.Replace("%d", ptofn.GetPath());
750  wxString cmd;
751  cmd.Printf("%s %s", hugin_utils::wxQuoteFilename(autopanoExe).c_str(), autopanoArgs.c_str());
752 #ifdef __WXMSW__
753  if (cmd.size() > 32766) {
754  CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
755  _("Too many images selected"), parent);
756  return cps;
757  }
758 #endif
759  DEBUG_DEBUG("Executing: " << cmd.c_str());
760 
761  wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(cmd);
762  if (arguments.GetCount() > 127) {
763  DEBUG_ERROR("Too many arguments for call to wxExecute()");
764  DEBUG_ERROR("Try using the %s parameter in preferences");
765  CPMessage(wxString::Format(_("Too many arguments (images). Try using the %%s parameter in preferences.\n\n Could not execute command: %s"), autopanoExe.c_str()), _("wxExecute Error"), parent);
766  return cps;
767  }
768 
769  ret_value = 0;
770  // use MyExternalCmdExecDialog
771  ret_value = CPExecute(autopanoExe, autopanoArgs, _("finding control points"), parent);
772 
773  if (ret_value == HUGIN_EXIT_CODE_CANCELLED) {
774  return cps;
775  } else if (ret_value == -1) {
776  CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
777  return cps;
778  } else if (ret_value > 0) {
779  CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
780  _("wxExecute Error"), parent);
781  return cps;
782  }
783 
784  ptofile = ptofn.GetFullPath();
785  ptofile.append("0.oto");
786  if (! wxFileExists(ptofile.c_str()) ) {
787  CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
788  _("Control point detector failure"), parent );
789  return cps;
790  }
791  // read and update control points
792  cps = readUpdatedControlPoints((const char *)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, true);
793 
794  if (!wxRemoveFile(ptofile)) {
795  DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
796  }
797  return cps;
798 }
799 
800 struct img_ev
801 {
802  unsigned int img_nr;
803  double ev;
804 };
805 struct stack_img
806 {
807  unsigned int layer_nr;
808  std::vector<img_ev> images;
809 };
810 bool sort_img_ev (img_ev i1, img_ev i2) { return (i1.ev<i2.ev); };
811 
813 {
814  for(unsigned int i=0;i<new_cp.size();i++)
815  {
816  HuginBase::ControlPoint cp=new_cp[i];
817  bool duplicate=false;
818  for(unsigned int j=0;j<cpv.size();j++)
819  {
820  if(cp==cpv[j])
821  {
822  duplicate=true;
823  break;
824  }
825  };
826  if(!duplicate)
827  {
828  cpv.push_back(cp);
829  if(pano!=NULL)
830  pano->addCtrlPoint(cp);
831  };
832  };
833 };
834 
836  int nFeatures, int & ret_value, wxWindow *parent)
837 {
839  if (imgs.empty()) {
840  return cps;
841  };
842  std::vector<stack_img> stack_images;
844  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
845  {
846  unsigned int stack_nr=variable_groups->getStacks().getPartNumber(*it);
847  //check, if this stack is already in list
848  bool found=false;
849  unsigned int index=0;
850  for(index=0;index<stack_images.size();index++)
851  {
852  found=(stack_images[index].layer_nr==stack_nr);
853  if(found)
854  break;
855  };
856  if(!found)
857  {
858  //new stack
859  stack_images.resize(stack_images.size()+1);
860  index=stack_images.size()-1;
861  //add new stack
862  stack_images[index].layer_nr=stack_nr;
863  };
864  //add new image
865  unsigned int new_image_index=stack_images[index].images.size();
866  stack_images[index].images.resize(new_image_index+1);
867  stack_images[index].images[new_image_index].img_nr=*it;
868  stack_images[index].images[new_image_index].ev=pano.getImage(*it).getExposure();
869  };
870  delete variable_groups;
871  //get image with median exposure for search with cp generator
872  HuginBase::UIntSet images_layer;
873  for(unsigned int i=0;i<stack_images.size();i++)
874  {
875  std::sort(stack_images[i].images.begin(),stack_images[i].images.end(),sort_img_ev);
876  unsigned int index=0;
877  if(stack_images[i].images[0].ev!=stack_images[i].images[stack_images[i].images.size()-1].ev)
878  {
879  index=stack_images[i].images.size() / 2;
880  };
881  images_layer.insert(stack_images[i].images[index].img_nr);
882  };
883  //generate cp for median exposure
884  ret_value=0;
885  if(images_layer.size()>1)
886  {
887  AutoPanoSift matcher;
888  cps=matcher.automatch(setting, pano, images_layer, nFeatures, ret_value, parent);
889  if(ret_value!=0)
890  return cps;
891  };
892  //now work on all stacks
893  if(!setting.GetProgStack().IsEmpty())
894  {
895  CPDetectorSetting stack_setting;
896  stack_setting.SetType(CPDetector_AutoPanoSift);
897  stack_setting.SetProg(setting.GetProgStack());
898  stack_setting.SetArgs(setting.GetArgsStack());
899 
900  for(unsigned int i=0;i<stack_images.size();i++)
901  {
902  HuginBase::UIntSet images_stack;
903  images_stack.clear();
904  for(unsigned int j=0;j<stack_images[i].images.size();j++)
905  images_stack.insert(stack_images[i].images[j].img_nr);
906  if(images_stack.size()>1)
907  {
908  AutoPanoSift matcher;
909  HuginBase::CPVector new_cps = matcher.automatch(stack_setting, pano, images_stack, nFeatures, ret_value, parent);
910  if(!new_cps.empty())
911  AddControlPointsWithCheck(cps,new_cps);
912  if(ret_value!=0)
913  return cps;
914  };
915  };
916  }
917  return cps;
918 };
919 
921  int nFeatures, int & ret_value, wxWindow *parent)
922 {
924  if (imgs.size() < 2)
925  {
926  return cps;
927  };
928  std::vector<wxString> keyFiles(pano.getNrOfImages());
929  //generate cp for every consecutive image pair
930  unsigned int counter=0;
931  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end();)
932  {
933  if(counter==imgs.size()-1)
934  break;
935  counter++;
936  HuginBase::UIntSet ImagePair;
937  ImagePair.clear();
938  ImagePair.insert(*it);
939  ++it;
940  ImagePair.insert(*it);
941  AutoPanoSift matcher;
942  HuginBase::CPVector new_cps;
943  new_cps.clear();
944  if(setting.IsTwoStepDetector())
945  new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, keyFiles, ret_value, parent);
946  else
947  new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, ret_value, parent);
948  if(!new_cps.empty())
949  AddControlPointsWithCheck(cps,new_cps);
950  if(ret_value!=0)
951  {
952  Cleanup(setting, pano, imgs, keyFiles, parent);
953  return cps;
954  };
955  };
956  // now connect all image groups
957  // generate temporary panorama to add all found cps
958  HuginBase::UIntSet allImgs;
959  fill_set(allImgs, 0, pano.getNrOfImages()-1);
960  HuginBase::Panorama optPano = pano.getSubset(allImgs);
961  for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
962  optPano.addCtrlPoint(*it);
963 
964  HuginGraph::ImageGraph graph(optPano);
966  size_t n = comps.size();
967  if(n>1)
968  {
969  HuginBase::UIntSet ImagesGroups;
970  for(size_t i=0;i<n;i++)
971  {
972  ImagesGroups.insert(*(comps[i].begin()));
973  if(comps[i].size()>1)
974  ImagesGroups.insert(*(comps[i].rbegin()));
975  };
976  AutoPanoSift matcher;
977  HuginBase::CPVector new_cps;
978  if(setting.IsTwoStepDetector())
979  new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, keyFiles, ret_value, parent);
980  else
981  new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, ret_value, parent);
982  if(!new_cps.empty())
983  AddControlPointsWithCheck(cps,new_cps,&optPano);
984  if(ret_value!=0)
985  {
986  Cleanup(setting, pano, imgs, keyFiles, parent);
987  return cps;
988  };
989  HuginGraph::ImageGraph graph2(optPano);
990  n = graph2.IsConnected() ? 1 : 2;
991  };
992  if(n==1 && setting.GetOption())
993  {
994  //next steps happens only when all images are connected;
995  //now optimize panorama
998  // calculate proper scaling, 1:1 resolution.
999  // Otherwise optimizer distances are meaningless.
1000  opts.setWidth(30000, false);
1001  opts.setHeight(15000);
1002 
1003  optPano.setOptions(opts);
1004  int w = hugin_utils::roundi(HuginBase::CalculateOptimalScale::calcOptimalScale(optPano) * optPano.getOptions().getWidth());
1005 
1006  opts.setWidth(w);
1007  opts.setHeight(w/2);
1008  optPano.setOptions(opts);
1009 
1010  //generate optimize vector, optimize only yaw and pitch
1011  HuginBase::OptimizeVector optvars;
1012  const HuginBase::SrcPanoImage & anchorImage = optPano.getImage(opts.optimizeReferenceImage);
1013  for (unsigned i=0; i < optPano.getNrOfImages(); i++)
1014  {
1015  std::set<std::string> imgopt;
1016  if(i==opts.optimizeReferenceImage)
1017  {
1018  //optimize only anchors pitch, not yaw
1019  imgopt.insert("p");
1020  }
1021  else
1022  {
1023  // do not optimize anchor image's stack for position.
1024  if(!optPano.getImage(i).YawisLinkedWith(anchorImage))
1025  {
1026  imgopt.insert("p");
1027  imgopt.insert("y");
1028  };
1029  };
1030  optvars.push_back(imgopt);
1031  }
1032  optPano.setOptimizeVector(optvars);
1033 
1034  // remove vertical and horizontal control points
1035  HuginBase::CPVector backupOldCPS = optPano.getCtrlPoints();
1036  HuginBase::CPVector backupNewCPS;
1037  for (HuginBase::CPVector::const_iterator it = backupOldCPS.begin(); it != backupOldCPS.end(); ++it) {
1038  if (it->mode == HuginBase::ControlPoint::X_Y)
1039  {
1040  backupNewCPS.push_back(*it);
1041  }
1042  }
1043  optPano.setCtrlPoints(backupNewCPS);
1044  // do a first pairwise optimisation step
1046  HuginBase::PTools::optimize(optPano);
1047  optPano.setCtrlPoints(backupOldCPS);
1048  //and find cp on overlapping images
1049  //work only on image pairs, which are not yet connected
1050  AutoPanoSiftPreAlign matcher;
1051  CPDetectorSetting newSetting;
1052  newSetting.SetProg(setting.GetProg());
1053  newSetting.SetArgs(setting.GetArgs());
1054  if(setting.IsTwoStepDetector())
1055  {
1056  newSetting.SetProgMatcher(setting.GetProgMatcher());
1057  newSetting.SetArgsMatcher(setting.GetArgsMatcher());
1058  };
1059  newSetting.SetOption(true);
1060  HuginBase::CPVector new_cps;
1061  if(setting.IsTwoStepDetector())
1062  new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, keyFiles, ret_value, parent);
1063  else
1064  new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, ret_value, parent);
1065  if(!new_cps.empty())
1066  AddControlPointsWithCheck(cps,new_cps);
1067  };
1068  Cleanup(setting, pano, imgs, keyFiles, parent);
1069  return cps;
1070 };
1071 
1073  int nFeatures, int & ret_value, wxWindow *parent)
1074 {
1075  HuginBase::CPVector cps;
1076  if (imgs.empty()) {
1077  return cps;
1078  };
1079  std::vector<stack_img> stack_images;
1081  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
1082  {
1083  unsigned int stack_nr=variable_groups->getStacks().getPartNumber(*it);
1084  //check, if this stack is already in list
1085  bool found=false;
1086  unsigned int index=0;
1087  for(index=0;index<stack_images.size();index++)
1088  {
1089  found=(stack_images[index].layer_nr==stack_nr);
1090  if(found)
1091  break;
1092  };
1093  if(!found)
1094  {
1095  //new stack
1096  stack_images.resize(stack_images.size()+1);
1097  index=stack_images.size()-1;
1098  //add new stack
1099  stack_images[index].layer_nr=stack_nr;
1100  };
1101  //add new image
1102  unsigned int new_image_index=stack_images[index].images.size();
1103  stack_images[index].images.resize(new_image_index+1);
1104  stack_images[index].images[new_image_index].img_nr=*it;
1105  stack_images[index].images[new_image_index].ev=pano.getImage(*it).getExposure();
1106  };
1107  delete variable_groups;
1108  //get image with median exposure for search with cp generator
1109  HuginBase::UIntSet images_layer;
1110  for(unsigned int i=0;i<stack_images.size();i++)
1111  {
1112  std::sort(stack_images[i].images.begin(),stack_images[i].images.end(),sort_img_ev);
1113  unsigned int index=0;
1114  if(stack_images[i].images[0].ev!=stack_images[i].images[stack_images[i].images.size()-1].ev)
1115  {
1116  index=stack_images[i].images.size() / 2;
1117  };
1118  images_layer.insert(stack_images[i].images[index].img_nr);
1119  };
1120  ret_value=0;
1121  //work on all stacks
1122  if(!setting.GetProgStack().IsEmpty())
1123  {
1124  CPDetectorSetting stack_setting;
1125  stack_setting.SetType(CPDetector_AutoPanoSift);
1126  stack_setting.SetProg(setting.GetProgStack());
1127  stack_setting.SetArgs(setting.GetArgsStack());
1128 
1129  for(unsigned int i=0;i<stack_images.size();i++)
1130  {
1131  HuginBase::UIntSet images_stack;
1132  images_stack.clear();
1133  for(unsigned int j=0;j<stack_images[i].images.size();j++)
1134  images_stack.insert(stack_images[i].images[j].img_nr);
1135  if(images_stack.size()>1)
1136  {
1137  AutoPanoSift matcher;
1138  HuginBase::CPVector new_cps = matcher.automatch(stack_setting, pano, images_stack, nFeatures, ret_value, parent);
1139  if(!new_cps.empty())
1140  AddControlPointsWithCheck(cps,new_cps);
1141  if(ret_value!=0)
1142  {
1143  std::vector<wxString> emptyKeyfiles;
1144  Cleanup(setting, pano, imgs, emptyKeyfiles, parent);
1145  return cps;
1146  };
1147  };
1148  };
1149  }
1150  //generate cp for median exposure with multi-row algorithm
1151  if(images_layer.size()>1)
1152  {
1153  HuginBase::UIntSet allImgs;
1154  fill_set(allImgs, 0, pano.getNrOfImages()-1);
1155  HuginBase::Panorama newPano = pano.getSubset(allImgs);
1156  if(!cps.empty())
1157  for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
1158  newPano.addCtrlPoint(*it);
1159 
1160  AutoPanoSiftMultiRow matcher;
1161  HuginBase::CPVector new_cps = matcher.automatch(setting, newPano, images_layer, nFeatures, ret_value, parent);
1162  if(!new_cps.empty())
1163  AddControlPointsWithCheck(cps,new_cps);
1164  };
1165  return cps;
1166 };
1167 
1169  int nFeatures, int & ret_value, wxWindow *parent)
1170 {
1171  std::vector<wxString> keyFiles(pano.getNrOfImages());
1172  return automatch(setting, pano, imgs, nFeatures, keyFiles, ret_value, parent);
1173 };
1174 
1176  int nFeatures, std::vector<wxString> &keyFiles, int & ret_value, wxWindow *parent)
1177 {
1178  HuginBase::CPVector cps;
1179  if (imgs.size()<2)
1180  return cps;
1181  DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages());
1182 
1183  std::vector<HuginBase::UIntSet> usedImages;
1184  usedImages.resize(pano.getNrOfImages());
1185  if(setting.GetOption())
1186  {
1187  //only work on not connected image pairs
1188  HuginBase::CPVector oldCps = pano.getCtrlPoints();
1189  for(unsigned i=0;i<oldCps.size();i++)
1190  {
1191  if (oldCps[i].mode == HuginBase::ControlPoint::X_Y)
1192  {
1193  usedImages[oldCps[i].image1Nr].insert(oldCps[i].image2Nr);
1194  usedImages[oldCps[i].image2Nr].insert(oldCps[i].image1Nr);
1195  };
1196  };
1197  };
1198  HuginBase::CalculateImageOverlap overlap(&pano);
1199  overlap.calculate(10);
1200  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
1201  {
1202  HuginBase::UIntSet images;
1203  images.clear();
1204  images.insert(*it);
1205  HuginBase::UIntSet::const_iterator it2 = it;
1206  for(++it2;it2!=imgs.end();++it2)
1207  {
1208  //check if this image pair was yet used
1209  if(set_contains(usedImages[*it2],*it))
1210  continue;
1211  //now check position
1212  if(overlap.getOverlap(*it,*it2)>0)
1213  {
1214  images.insert(*it2);
1215  };
1216  };
1217  if(images.size()<2)
1218  continue;
1219  //remember image pairs for later
1220  for (HuginBase::UIntSet::const_iterator img_it = images.begin(); img_it != images.end(); ++img_it)
1221  for (HuginBase::UIntSet::const_iterator img_it2 = images.begin(); img_it2 != images.end(); ++img_it2)
1222  usedImages[*img_it].insert(*img_it2);
1223  AutoPanoSift matcher;
1224  HuginBase::CPVector new_cps;
1225  if(setting.IsTwoStepDetector())
1226  new_cps=matcher.automatch(setting, pano, images, nFeatures, keyFiles, ret_value, parent);
1227  else
1228  new_cps=matcher.automatch(setting, pano, images, nFeatures, ret_value, parent);
1229  if(!new_cps.empty())
1230  AddControlPointsWithCheck(cps,new_cps);
1231  if(ret_value!=0)
1232  {
1233  Cleanup(setting, pano, imgs, keyFiles, parent);
1234  return cps;
1235  };
1236  };
1237  Cleanup(setting, pano, imgs, keyFiles, parent);
1238  return cps;
1239 };
int MyExecuteCommandOnDialog(wxString command, wxString args, wxWindow *parent, wxString title, bool isQuoted)
execute a single command in own dialog, redirect output to frame and allow canceling ...
implementation of huginApp Class
wxString GetProgPath(wxString progName)
void setMemento(const PanoramaMemento &memento)
set the internal state
Definition: Panorama.cpp:1507
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
void setHeight(unsigned int h)
set panorama height
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
int roundi(T x)
Definition: hugin_math.h:73
double getOverlap(unsigned int i, unsigned int j) const
returns the overlap for 2 images with number i and j
const CPDetectorType GetType()
return type of this setting
const int HUGIN_EXIT_CODE_CANCELLED
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
ImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables.
CPDetectorType
A matcher that uses Alexandres sift matcher.
Somewhere to specify what variables belong to what.
void SetType(CPDetectorType new_type)
sets type of this setting
bool IsConnected()
check if all images are connected
Definition: ImageGraph.cpp:128
HuginBase::CPVector readUpdatedControlPoints(const std::string &file, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, bool reordered)
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
A matcher for multi-rows, which considers stacks.
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
void SetArgs(wxString new_args)
sets arguments of one step detector or feature descriptor
void calculate(unsigned int steps)
does the calculation, for each image steps*steps points are extracted and tested with all other image...
include file for the hugin project
wxString GetCheckedTempDir()
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
int CPExecute(wxString prog, wxString args, wxString caption, wxWindow *parent)
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
represents a control point
Definition: ControlPoint.h:38
A matcher for multi-row panoramas based on an idea by Bruno Postle.
str quoteFilename(const str &arg)
Quote a filename, so that it is surrounded by &quot;&quot;.
Definition: platform.h:158
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition: ImageGraph.h:50
void AddControlPointsWithCheck(HuginBase::CPVector &cpv, HuginBase::CPVector &new_cp, HuginBase::Panorama *pano=NULL)
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
unsigned int layer_nr
virtual void Cleanup(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, std::vector< wxString > &keyFiles, wxWindow *parent=NULL)
Model for a panorama.
Definition: Panorama.h:152
const wxString GetProgMatcher()
return program for feature matcher
void CPMessage(const wxString message, const wxString caption, wxWindow *parent)
void SetArgsMatcher(wxString new_args)
sets arguments for feature matcher
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
Definition: Panorama.cpp:381
const OptimizeVector & getOptimizeVector() const
return the optimize settings stored inside panorama
Definition: Panorama.h:454
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
bool loadPTScript(std::istream &i, int &ptoVersion, const std::string &prefix="")
load a Hugin file
class, which stores all settings of one cp detector
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
const wxString GetArgsMatcher()
return arguments for feature matcher
void SetProg(wxString new_prog)
sets program for one step detector or feature descriptor
platform/compiler specific stuff.
static double calcOptimalScale(PanoramaData &panorama)
const wxString GetArgs()
return arguments of one step detector or feature descriptor
std::vector< img_ev > images
const wxString GetArgsCleanup()
return arguments for the cleanup step
const wxString GetProgStack()
return program name, which works on stacks
A matcher that uses Sebastians Nowozin&#39;s excellent sift matcher and considers stacks.
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
const wxString GetArgsStack()
return arguments of program for detection of cp in stacks
const bool GetOption()
gets options, used in multi-row and prealigned cp detectors
#define DEBUG_ERROR(msg)
Definition: utils.h:76
!! from PTOptimise.h 1951
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
double getExposure() const
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
unsigned int img_nr
void SetProgMatcher(wxString new_prog)
sets program for feature matcher
const bool IsTwoStepDetector()
returns true, if setting is suitable for two step detector otherwise false
bool CanStartProg(wxString progName, wxWindow *parent)
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
virtual HuginBase::CPVector automatch(CPDetectorSetting &setting, HuginBase::Panorama &pano, const HuginBase::UIntSet &imgs, int nFeatures, int &ret_value, wxWindow *parent=NULL)
Do cp matching, calles the right routines, based on the matcher selected.
Components GetComponents()
find all connected components
Definition: ImageGraph.cpp:101
bool sort_img_ev(img_ev i1, img_ev i2)
definitions of classes to calculate overlap between different images
Memento class for a Panorama object.
Definition: Panorama.h:49
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
functions for interaction with the hugin configuration file
platform/compiler specific stuff.
std::vector< std::set< std::string > > OptimizeVector
class for calculating overlap of images
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void SetOption(bool new_option)
set options, used in multi-row cp and prealigned detectors
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
void printPanoramaScript(std::ostream &o, const OptimizeVector &optvars, const PanoramaOptions &options, const UIntSet &imgs, bool forPTOptimizer, const std::string &stripPrefix="") const
create an optimizer script
A matcher that uses the align information in the panorama to generate cp between overlapping images...
str wxQuoteFilename(const str &arg)
Quote a filename, so that it is surrounded by &quot;&quot;.
Definition: wxPlatform.h:82
static const bool IsCleanupPossible(CPDetectorType _type)
return true, if setting allows a final cleanup run
A matcher that uses Sebastians Nowozin&#39;s excellent sift matcher.
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Panorama image options.
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
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 setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
static void autoOptimise(PanoramaData &pano, bool optRoll=true)
const wxString GetProg()
return program for one step detector or feature descriptor
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition: ImageGraph.h:44