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