Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PanoDetector.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 ; tab-width: 4 -*-
2 /*
3 * Copyright (C) 2007-2008 Anael Orlinski
4 *
5 * This file is part of Panomatic.
6 *
7 * Panomatic is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * Panomatic is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Panomatic; if not, write to the Free Software
19 * <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "PanoDetector.h"
23 #include <iostream>
24 #include <fstream>
25 #include <sstream>
26 
27 #include <time.h>
28 
29 #include "Utils.h"
30 #include "Tracer.h"
32 
36 #include <nona/RemappedPanoImage.h>
37 #include <nona/ImageRemapper.h>
38 
39 //for multi row strategy
41 #include <panodata/Panorama.h>
45 
46 #include "ImageImport.h"
47 
48 #ifdef _WIN32
49 #include <direct.h>
50 #else
51 #include <unistd.h>
52 #endif
53 #include <hugin_config.h>
54 
55 #ifndef srandom
56 #define srandom srand
57 #endif
58 
59 #ifdef HAVE_OPENMP
60 #include <omp.h>
61 #endif
62 
63 #define TRACE_IMG(X) {if (_panoDetector.getVerbose() == 1) {TRACE_INFO("i" << _imgData._number << " : " << X << std::endl);}}
64 #define TRACE_PAIR(X) {if (_panoDetector.getVerbose() == 1){ TRACE_INFO("i" << _matchData._i1->_number << " <> " \
65  "i" << _matchData._i2->_number << " : " << X << std::endl);}}
66 
67 std::string includeTrailingPathSep(std::string path)
68 {
69  std::string pathWithSep(path);
70 #ifdef _WIN32
71  if(pathWithSep[pathWithSep.length()-1]!='\\' || pathWithSep[pathWithSep.length()-1]!='/')
72  {
73  pathWithSep.append("\\");
74  }
75 #else
76  if(pathWithSep[pathWithSep.length()-1]!='/')
77  {
78  pathWithSep.append("/");
79  }
80 #endif
81  return pathWithSep;
82 };
83 
84 std::string getKeyfilenameFor(std::string keyfilesPath, std::string filename)
85 {
86  std::string newfilename;
87  if(keyfilesPath.empty())
88  {
89  //if no path for keyfiles is given we are saving into the same directory as image file
90  newfilename=hugin_utils::stripExtension(filename);
91  }
92  else
93  {
94  newfilename = includeTrailingPathSep(keyfilesPath);
95  newfilename.append(hugin_utils::stripPath(hugin_utils::stripExtension(filename)));
96  };
97  newfilename.append(".key");
98  return newfilename;
99 };
100 
102  _writeAllKeyPoints(false), _verbose(1),
103  _sieve1Width(10), _sieve1Height(10), _sieve1Size(100),
104  _kdTreeSearchSteps(200), _kdTreeSecondDistance(0.25),
105  _minimumMatches(6), _ransacMode(HuginBase::RANSACOptimizer::AUTO), _ransacIters(1000), _ransacDistanceThres(50),
106  _sieve2Width(5), _sieve2Height(5), _sieve2Size(1),
107  _matchingStrategy(MULTIROW), _linearMatchLen(1),
108  _test(false), _cores(0), _downscale(true), _cache(false), _cleanup(false),
109  _celeste(false), _celesteThreshold(0.5), _celesteRadius(20),
110  _keypath(""), _outputFile("default.pto"), _outputGiven(false), svmModel(NULL)
111 {
113 }
114 
116 {
117  delete _panoramaInfo;
118 }
119 
121 {
122  // test linear match data
123  if (_linearMatchLen < 1)
124  {
125  std::cout << "Linear match length must be at least 1." << std::endl;
126  return false;
127  }
128 
129  // check the test mode
130  if (_test)
131  {
132  if (_filesData.size() != 2)
133  {
134  std::cout << "In test mode you must provide exactly 2 images." << std::endl;
135  return false;
136  }
137  }
138 
139  return true;
140 }
141 
143 {
144  std::cout << "Input file : " << _inputFile << std::endl;
145  if (_keyPointsIdx.size() != 0)
146  {
147  std::cout << "Output file(s) : keyfile(s) for images";
148  for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i)
149  {
150  std::cout << " " << _keyPointsIdx[i] << std::endl;
151  }
152  }
153  else
154  {
156  {
157  std::cout << "Output file(s) : keyfiles for all images in project" << std::endl;
158  }
159  else
160  {
161  std::cout << "Output file : " << _outputFile << std::endl;
162  };
163  }
164  if(!_keypath.empty())
165  {
166  std::cout << "Path to keyfiles : " << _keypath << std::endl;
167  };
168  if(_cleanup)
169  {
170  std::cout << "Cleanup temporary files." << std::endl;
171  };
172  if(_cache)
173  {
174  std::cout << "Automatically cache keypoints files to disc." << std::endl;
175  };
176  std::cout << "Input image options" << std::endl;
177  std::cout << " Downscale to half-size : " << (_downscale?"yes":"no") << std::endl;
178  if(_celeste)
179  {
180  std::cout << "Celeste options" << std::endl;
181  std::cout << " Threshold : " << _celesteThreshold << std::endl;
182  std::cout << " Radius : " << _celesteRadius << std::endl;
183  }
184  std::cout << "Sieve 1 Options" << std::endl;
185  std::cout << " Width : " << _sieve1Width << std::endl;
186  std::cout << " Height : " << _sieve1Height << std::endl;
187  std::cout << " Size : " << _sieve1Size << std::endl;
188  std::cout << " ==> Maximum keypoints per image : " << _sieve1Size* _sieve1Height* _sieve1Width << std::endl;
189  std::cout << "KDTree Options" << std::endl;
190  std::cout << " Search steps : " << _kdTreeSearchSteps << std::endl;
191  std::cout << " Second match distance : " << _kdTreeSecondDistance << std::endl;
192  std::cout << "Matching Options" << std::endl;
193  switch(_matchingStrategy)
194  {
195  case ALLPAIRS:
196  std::cout << " Mode : All pairs" << std::endl;
197  break;
198  case LINEAR:
199  std::cout << " Mode : Linear match with length of " << _linearMatchLen << " image" << std::endl;
200  break;
201  case MULTIROW:
202  std::cout << " Mode : Multi row" << std::endl;
203  break;
204  case PREALIGNED:
205  std::cout << " Mode : Prealigned positions" << std::endl;
206  break;
207  };
208  std::cout << " Distance threshold : " << _ransacDistanceThres << std::endl;
209  std::cout << "RANSAC Options" << std::endl;
210  std::cout << " Mode : ";
211  switch (_ransacMode)
212  {
214  std::cout << "auto" << std::endl;
215  break;
217  std::cout << "homography" << std::endl;
218  break;
220  std::cout << "roll, pitch, yaw" << std::endl;
221  break;
223  std::cout << "roll, pitch, yaw, fov" << std::endl;
224  break;
226  std::cout << "roll, pitch, yaw, fov, distortion" << std::endl;
227  break;
228  }
229  std::cout << " Iterations : " << _ransacIters << std::endl;
230  std::cout << " Distance threshold : " << _ransacDistanceThres << std::endl;
231  std::cout << "Minimum matches per image pair: " << _minimumMatches << std::endl;
232  std::cout << "Sieve 2 Options" << std::endl;
233  std::cout << " Width : " << _sieve2Width << std::endl;
234  std::cout << " Height : " << _sieve2Height << std::endl;
235  std::cout << " Size : " << _sieve2Size << std::endl;
236  std::cout << " ==> Maximum matches per image pair : " << _sieve2Size* _sieve2Height* _sieve2Width << std::endl;
237 }
238 
240 {
241  std::cout << std::endl << "Project contains the following images:" << std::endl;
242  for(unsigned int i=0; i<_panoramaInfo->getNrOfImages(); i++)
243  {
244  std::string name(_panoramaInfo->getImage(i).getFilename());
245  if(name.compare(0,_prefix.length(),_prefix)==0)
246  {
247  name=name.substr(_prefix.length(),name.length()-_prefix.length());
248  }
249  std::cout << "Image " << i << std::endl << " Imagefile: " << name << std::endl;
250  bool writeKeyfileForImage=false;
251  if(!_keyPointsIdx.empty())
252  {
253  for(unsigned j=0; j<_keyPointsIdx.size() && !writeKeyfileForImage; j++)
254  {
255  writeKeyfileForImage=_keyPointsIdx[j]==i;
256  };
257  };
258  if(_cache || _filesData[i]._hasakeyfile || writeKeyfileForImage)
259  {
260  name=_filesData[i]._keyfilename;
261  if(name.compare(0,_prefix.length(),_prefix)==0)
262  {
263  name=name.substr(_prefix.length(),name.length()-_prefix.length());
264  }
265  std::cout << " Keyfile : " << name;
266  if(writeKeyfileForImage)
267  {
268  std::cout << " (will be generated)" << std::endl;
269  }
270  else
271  {
272  std::cout << (_filesData[i]._hasakeyfile?" (will be loaded)":" (will be generated)") << std::endl;
273  };
274  };
275  std::cout << " Remapped : " << (_filesData[i].NeedsRemapping()?"yes":"no") << std::endl;
276  };
277 };
278 
279 class Runnable
280 {
281 public:
282  Runnable() {};
283  virtual void run() = 0;
284  virtual ~Runnable() {};
285 };
286 
287 // definition of a runnable class for image data
288 class ImgDataRunnable : public Runnable
289 {
290 public:
291  ImgDataRunnable(PanoDetector::ImgData& iImageData, const PanoDetector& iPanoDetector) : Runnable(),
292  _panoDetector(iPanoDetector), _imgData(iImageData) {};
293 
294  virtual void run()
295  {
296  TRACE_IMG("Analyzing image...");
298  {
299  return;
300  }
307  }
308 private:
311 };
312 
313 // definition of a runnable class for writeKeyPoints
315 {
316 public:
317  WriteKeyPointsRunnable(PanoDetector::ImgData& iImageData, const PanoDetector& iPanoDetector) :
318  _panoDetector(iPanoDetector), _imgData(iImageData) {};
319 
320  virtual void run()
321  {
322  TRACE_IMG("Analyzing image...");
324  {
325  return;
326  }
332  }
333 private:
336 };
337 
338 // definition of a runnable class for keypoints data
340 {
341 public:
342  LoadKeypointsDataRunnable(PanoDetector::ImgData& iImageData, const PanoDetector& iPanoDetector) :
343  _panoDetector(iPanoDetector), _imgData(iImageData) {};
344 
345  virtual void run()
346  {
347  TRACE_IMG("Loading keypoints...");
350  }
351 
352 private:
355 };
356 
357 // definition of a runnable class for MatchData
359 {
360 public:
361  MatchDataRunnable(PanoDetector::MatchData& iMatchData, const PanoDetector& iPanoDetector) :
362  _panoDetector(iPanoDetector), _matchData(iMatchData) {};
363 
364  virtual void run()
365  {
366  //TRACE_PAIR("Matching...");
367  if(!_matchData._i1->_kp.empty() && !_matchData._i2->_kp.empty())
368  {
372  TRACE_PAIR("Found " << _matchData._matches.size() << " matches");
373  };
374  }
375 private:
378 };
379 
381 {
382  std::string model_file = ("celeste.model");
383  std::ifstream test(model_file.c_str());
384  if (!test.good())
385  {
386  std::string install_path_model=hugin_utils::GetDataDir();
387  install_path_model.append(model_file);
388  std::ifstream test2(install_path_model.c_str());
389  if (!test2.good())
390  {
391  std::cout << std::endl << "Couldn't open SVM model file " << model_file << std::endl;
392  std::cout << "Also tried " << install_path_model << std::endl << std::endl;
393  return false;
394  };
395  model_file = install_path_model;
396  }
397  if(!celeste::loadSVMmodel(svmModel,model_file))
398  {
399  svmModel=NULL;
400  return false;
401  };
402  return true;
403 };
404 
405 typedef std::vector<Runnable*> RunnableVector;
406 
407 void RunQueue(std::vector<Runnable*>& queue)
408 {
409 #pragma omp parallel for schedule(dynamic)
410  for (int i = 0; i < queue.size(); ++i)
411  {
412  queue[i]->run();
413  };
414  // now clear queue
415  while (!queue.empty())
416  {
417  delete queue.back();
418  queue.pop_back();
419  };
420 };
421 
423 {
424  // init the random time generator
425  srandom((unsigned int)time(NULL));
426 
427  // Load the input project file
428  if(!loadProject())
429  {
430  return;
431  };
433  {
434  for(unsigned int i=0; i<_panoramaInfo->getNrOfImages(); i++)
435  {
436  _keyPointsIdx.push_back(i);
437  };
438  };
439 
440  if(_cleanup)
441  {
442  CleanupKeyfiles();
443  return;
444  };
445 
446  //checking, if memory allows running desired number of threads
447  unsigned long maxImageSize=0;
448  bool withRemap=false;
449  for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB)
450  {
451  if(!aB->second._hasakeyfile)
452  {
453  maxImageSize=std::max<unsigned long>(aB->second._detectWidth*aB->second._detectHeight,maxImageSize);
454  if(aB->second.NeedsRemapping())
455  {
456  withRemap=true;
457  };
458  };
459  };
460 #ifdef HAVE_OPENMP
461  if (_cores == 0)
462  {
463  // use number of physical cores - 1
464  size_t nrCores = utils::GetPhysicalCPUCount();
465  if (nrCores > 4)
466  {
467  --nrCores;
468  };
469  setCores(nrCores);
470  };
471  if (maxImageSize != 0)
472  {
473  unsigned long long maxCores;
474  //determinded factors by testing of some projects
475  //the memory usage seems to be very high
476  //if the memory usage could be decreased these numbers can be decreased
477  if(withRemap)
478  {
479  maxCores=utils::getTotalMemory()/(maxImageSize*75);
480  }
481  else
482  {
483  maxCores=utils::getTotalMemory()/(maxImageSize*50);
484  };
485  if(maxCores<1)
486  {
487  maxCores=1;
488  }
489  if(maxCores<_cores)
490  {
491  if(getVerbose()>0)
492  {
493  std::cout << "\nThe available memory does not allow running " << _cores << " threads parallel.\n"
494  << "Running cpfind with " << maxCores << " threads.\n";
495  };
496  setCores(maxCores);
497  };
498  };
499  omp_set_num_threads(_cores);
500  std::cout << "Using " << _cores << " threads" << std::endl;
501 #endif
502  RunnableVector queue;
503  svmModel = NULL;
504  if(_celeste)
505  {
506  TRACE_INFO("\nLoading Celeste model file...\n");
507  if(!LoadSVMModel())
508  {
509  setCeleste(false);
510  };
511  };
512 
513  //print some more information about the images
514  if (_verbose > 0)
515  {
516  printFilenames();
517  }
518 
519  // 2. run analysis of images or keypoints
520 #if _WIN32
521  //multi threading of image loading results sometime in a race condition
522  //try to prevent this by initialisation of codecManager before
523  //running multi threading part
524  std::string s=vigra::impexListExtensions();
525 #endif
526  if (_keyPointsIdx.size() != 0)
527  {
528  if (_verbose > 0)
529  {
530  TRACE_INFO(std::endl << "--- Analyze Images ---" << std::endl);
531  }
532  for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i)
533  {
534  queue.push_back(new WriteKeyPointsRunnable(_filesData[_keyPointsIdx[i]], *this));
535  };
536  }
537  else
538  {
539  TRACE_INFO(std::endl << "--- Analyze Images ---" << std::endl);
540  if (getMatchingStrategy() == MULTIROW)
541  {
542  // when using multirow, don't analyse stacks with linked positions
544  HuginBase::UIntSet imagesToAnalyse;
545  imagesToAnalyse.insert(_image_layer.begin(), _image_layer.end());
546  for (size_t i = 0; i < _image_stacks.size(); i++)
547  {
548  imagesToAnalyse.insert(_image_stacks[i].begin(), _image_stacks[i].end());
549  }
550  for (HuginBase::UIntSet::const_iterator it = imagesToAnalyse.begin(); it != imagesToAnalyse.end(); ++it)
551  {
552  if (_filesData[*it]._hasakeyfile)
553  {
554  queue.push_back(new LoadKeypointsDataRunnable(_filesData[*it], *this));
555  }
556  else
557  {
558  queue.push_back(new ImgDataRunnable(_filesData[*it], *this));
559  };
560  };
561  }
562  else
563  {
564  for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB)
565  {
566  if (aB->second._hasakeyfile)
567  {
568  queue.push_back(new LoadKeypointsDataRunnable(aB->second, *this));
569  }
570  else
571  {
572  queue.push_back(new ImgDataRunnable(aB->second, *this));
573  }
574  }
575  };
576  }
577  RunQueue(queue);
578 
579  if(svmModel!=NULL)
580  {
582  };
583 
584  // check if the load of images succeed.
585  if (!checkLoadSuccess())
586  {
587  TRACE_INFO("One or more images failed to load. Exiting.");
588  return;
589  }
590 
591  if(_cache)
592  {
593  TRACE_INFO(std::endl << "--- Cache keyfiles to disc ---" << std::endl);
594  for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB)
595  {
596  if (!aB->second._hasakeyfile)
597  {
598  TRACE_INFO("i" << aB->second._number << " : Caching keypoints..." << std::endl);
599  writeKeyfile(aB->second);
600  };
601  };
602  };
603 
604  // Detect matches if writeKeyPoints wasn't set
605  if(_keyPointsIdx.empty())
606  {
607  switch (getMatchingStrategy())
608  {
609  case ALLPAIRS:
610  case LINEAR:
611  {
612  std::vector<HuginBase::UIntSet> imgPairs(_panoramaInfo->getNrOfImages());
613  if(!match(imgPairs))
614  {
615  return;
616  };
617  };
618  break;
619  case MULTIROW:
620  if(!matchMultiRow())
621  {
622  return;
623  };
624  break;
625  case PREALIGNED:
626  {
627  //check, which image pairs are already connected by control points
628  std::vector<HuginBase::UIntSet> connectedImages(_panoramaInfo->getNrOfImages());
630  for(HuginBase::CPVector::const_iterator it=cps.begin();it!=cps.end(); ++it)
631  {
632  if((*it).mode==HuginBase::ControlPoint::X_Y)
633  {
634  connectedImages[(*it).image1Nr].insert((*it).image2Nr);
635  connectedImages[(*it).image2Nr].insert((*it).image1Nr);
636  };
637  };
638  //build dummy map
639  std::vector<size_t> imgMap(_panoramaInfo->getNrOfImages());
640  for(size_t i=0; i<_panoramaInfo->getNrOfImages(); i++)
641  {
642  imgMap[i]=i;
643  };
644  //and the final matching step
645  if(!matchPrealigned(_panoramaInfo, connectedImages, imgMap))
646  {
647  return;
648  };
649  }
650  break;
651  };
652  }
653 
654  // 5. write output
655  if (_keyPointsIdx.size() != 0)
656  {
657  //Write all keyfiles
658  TRACE_INFO(std::endl<< "--- Write Keyfiles output ---" << std::endl << std::endl);
659  for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i)
660  {
662  };
663  if(_outputGiven)
664  {
665  std::cout << std::endl << "Warning: You have given the --output switch." << std::endl
666  << "This switch is not compatible with the --writekeyfile or --kall switch." << std::endl
667  << "If you want to generate the keyfiles and" << std::endl
668  << "do the matching in the same run use the --cache switch instead." << std::endl << std::endl;
669  };
670  }
671  else
672  {
674  TRACE_INFO(std::endl<< "--- Write Project output ---" << std::endl);
675  writeOutput();
676  TRACE_INFO("Written output to " << _outputFile << std::endl << std::endl);
677  };
678 }
679 
680 bool PanoDetector::match(std::vector<HuginBase::UIntSet> &checkedPairs)
681 {
682  // 3. prepare matches
683  RunnableVector queue;
684  MatchData_t matchesData;
685  unsigned int aLen = _filesData.size();
687  {
688  aLen = _linearMatchLen;
689  }
690 
691  if (aLen >= _filesData.size())
692  {
693  aLen = _filesData.size() - 1;
694  }
695 
696  for (unsigned int i1 = 0; i1 < _filesData.size(); ++i1)
697  {
698  unsigned int aEnd = i1 + 1 + aLen;
699  if (_filesData.size() < aEnd)
700  {
701  aEnd = _filesData.size();
702  }
703 
704  for (unsigned int i2 = (i1+1); i2 < aEnd; ++i2)
705  {
706  if(set_contains(checkedPairs[i1], i2))
707  {
708  continue;
709  };
710  // create a new entry in the matches map
711  matchesData.push_back(MatchData());
712 
713  MatchData& aM = matchesData.back();
714  aM._i1 = &(_filesData[i1]);
715  aM._i2 = &(_filesData[i2]);
716 
717  checkedPairs[i1].insert(i2);
718  checkedPairs[i2].insert(i1);
719  }
720  }
721  // 4. find matches
722  TRACE_INFO(std::endl<< "--- Find pair-wise matches ---" << std::endl);
723  for (size_t i = 0; i < matchesData.size(); ++i)
724  {
725  queue.push_back(new MatchDataRunnable(matchesData[i], *this));
726  };
727  RunQueue(queue);
728 
729  // Add detected matches to _panoramaInfo
730  for (size_t i = 0; i < matchesData.size(); ++i)
731  {
732  const MatchData& aM = matchesData[i];
733  for (size_t j = 0; j < aM._matches.size(); ++j)
734  {
735  const lfeat::PointMatchPtr& aPM = aM._matches[j];
736  _panoramaInfo->addCtrlPoint(HuginBase::ControlPoint(aM._i1->_number, aPM->_img1_x, aPM->_img1_y,
737  aM._i2->_number, aPM->_img2_x, aPM->_img2_y));
738  };
739  };
740  return true;
741 };
742 
744 {
746  if(_prefix.empty())
747  {
748  // Get the current working directory:
749  char* buffer;
750 #ifdef _WIN32
751 #define getcwd _getcwd
752 #endif
753  if((buffer=getcwd(NULL,0))!=NULL)
754  {
755  _prefix.append(buffer);
756  free(buffer);
758  }
759  };
761  {
762  return false;
763  }
764 
765  // Create a copy of panoramaInfo that will be used to define
766  // image options
768 
769  // create a hash set for all known control points
770  {
772  for (auto& cp : allCps)
773  {
774  _cpsHashSet.insert(cp.getCPString());
775  };
776  }
777  // Add images found in the project file to _filesData
778  const unsigned int nImg = _panoramaInfo->getNrOfImages();
779  unsigned int imgWithKeyfile=0;
780  for (unsigned int imgNr = 0; imgNr < nImg; ++imgNr)
781  {
782  // insert the image in the map
783  _filesData.insert(std::make_pair(imgNr, ImgData()));
784 
785  // get the data
786  ImgData& aImgData = _filesData[imgNr];
787 
788  // get a copy of image info
790 
791  // set the name
792  aImgData._name = img.getFilename();
793 
794  // modify image position in the copy
795  img.setYaw(0);
796  img.setRoll(0);
797  img.setPitch(0);
798  img.setX(0);
799  img.setY(0);
800  img.setZ(0);
801  img.setActive(true);
802  _panoramaInfoCopy.setImage(imgNr,img);
803 
804  // Number pointing to image info in _panoramaInfo
805  aImgData._number = imgNr;
806 
807  bool needsremap=(img.getHFOV()>=65 && img.getProjection() != HuginBase::SrcPanoImage::FISHEYE_STEREOGRAPHIC);
808  // set image detection size
809  if(needsremap)
810  {
811  _filesData[imgNr]._detectWidth = std::max(img.getSize().width(),img.getSize().height());
812  _filesData[imgNr]._detectHeight = std::max(img.getSize().width(),img.getSize().height());
813  _filesData[imgNr].SetSizeMode(ImgData::REMAPPED);
814  }
815  else
816  {
817  _filesData[imgNr]._detectWidth = img.getSize().width();
818  _filesData[imgNr]._detectHeight = img.getSize().height();
819  };
820 
821  // don't downscale if downscale image is smaller than 1000 pixel
822  if (_downscale && std::min(img.getSize().width(), img.getSize().height()) > 2000)
823  {
824  _filesData[imgNr]._detectWidth >>= 1;
825  _filesData[imgNr]._detectHeight >>= 1;
826  if (!_filesData[imgNr].NeedsRemapping())
827  {
828  _filesData[imgNr].SetSizeMode(ImgData::DOWNSCALED);
829  };
830  }
831 
832  // set image remapping options
833  if (aImgData.GetSizeMode() == ImgData::REMAPPED)
834  {
836  aImgData._projOpts.setHFOV(250);
837  aImgData._projOpts.setVFOV(250);
838  aImgData._projOpts.setWidth(250);
839  aImgData._projOpts.setHeight(250);
840 
841  // determine size of output image.
842  // The old code did not work with images with images with a FOV
843  // approaching 180 degrees
844  vigra::Rect2D roi=estimateOutputROI(_panoramaInfoCopy,aImgData._projOpts,imgNr);
845  double scalefactor = std::max((double)_filesData[imgNr]._detectWidth / roi.width(),
846  (double)_filesData[imgNr]._detectHeight / roi.height() );
847 
848  // resize output canvas
849  vigra::Size2D canvasSize((int)aImgData._projOpts.getWidth() * scalefactor,
850  (int)aImgData._projOpts.getHeight() * scalefactor);
851  aImgData._projOpts.setWidth(canvasSize.width(), false);
852  aImgData._projOpts.setHeight(canvasSize.height());
853 
854  // set roi to cover the remapped input image
855  roi *= scalefactor;
856  _filesData[imgNr]._detectWidth = roi.width();
857  _filesData[imgNr]._detectHeight = roi.height();
858  aImgData._projOpts.setROI(roi);
859  }
860 
861  // Specify if the image has an associated keypoint file
862 
863  aImgData._keyfilename = getKeyfilenameFor(_keypath,aImgData._name);
865  if(aImgData._hasakeyfile)
866  {
867  imgWithKeyfile++;
868  };
869  }
870  //update masks, convert positive masks into negative masks
871  //because positive masks works only if the images are on the final positions
873 
874  //if all images has keyfile, we don't need to load celeste model file
875  if(nImg==imgWithKeyfile)
876  {
877  _celeste=false;
878  };
879  return true;
880 }
881 
883 {
884  if(!_keyPointsIdx.empty())
885  {
886  for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i)
887  {
888  if(_filesData[_keyPointsIdx[i]]._loadFail)
889  {
890  return false;
891  };
892  };
893  }
894  else
895  {
896  for (unsigned int aFileN = 0; aFileN < _filesData.size(); ++aFileN)
897  {
898  if(_filesData[aFileN]._loadFail)
899  {
900  return false;
901  };
902  };
903  };
904  return true;
905 }
906 
908 {
909  for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB)
910  {
911  if (aB->second._hasakeyfile)
912  {
913  remove(aB->second._keyfilename.c_str());
914  };
915  };
916 };
917 
919 {
920  std::vector<HuginBase::UIntVector> stacks = HuginBase::getSortedStacks(_panoramaInfo);
921  //get image with median exposure for search with cp generator
922  for (size_t i = 0; i < stacks.size(); ++i)
923  {
924  size_t index = 0;
925  if (_panoramaInfo->getImage(*(stacks[i].begin())).getExposureValue() != _panoramaInfo->getImage(*(stacks[i].rbegin())).getExposureValue())
926  {
927  index = stacks[i].size() / 2;
928  };
929  _image_layer.insert(stacks[i][index]);
930  if (stacks[i].size()>1)
931  {
932  //build list for stacks, consider only unlinked stacks
933  if (!_panoramaInfo->getImage(*(stacks[i].begin())).YawisLinked())
934  {
935  _image_stacks.push_back(stacks[i]);
936  };
937  };
938  };
939 };
940 
942 {
943  RunnableVector queue;
944  MatchData_t matchesData;
945  //step 1
946  std::vector<HuginBase::UIntSet> checkedImagePairs(_panoramaInfo->getNrOfImages());
947  for (size_t i = 0; i < _image_stacks.size();i++)
948  {
949  //build match list for stacks
950  for(unsigned int j=0; j<_image_stacks[i].size()-1; j++)
951  {
952  const size_t img1 = _image_stacks[i][j];
953  const size_t img2 = _image_stacks[i][j + 1];
954  matchesData.push_back(MatchData());
955  MatchData& aM=matchesData.back();
956  if (img1 < img2)
957  {
958  aM._i1 = &(_filesData[img1]);
959  aM._i2 = &(_filesData[img2]);
960  }
961  else
962  {
963  aM._i1 = &(_filesData[img2]);
964  aM._i2 = &(_filesData[img1]);
965  };
966  checkedImagePairs[img1].insert(img2);
967  checkedImagePairs[img2].insert(img1);
968  };
969  };
970  //build match data list for image pairs
971  if(_image_layer.size()>1)
972  {
973  for (HuginBase::UIntSet::const_iterator it = _image_layer.begin(); it != _image_layer.end(); ++it)
974  {
975  const size_t img1 = *it;
976  HuginBase::UIntSet::const_iterator it2 = it;
977  ++it2;
978  if (it2 != _image_layer.end())
979  {
980  const size_t img2 = *it2;
981  matchesData.push_back(MatchData());
982  MatchData& aM = matchesData.back();
983  if (img1 < img2)
984  {
985  aM._i1 = &(_filesData[img1]);
986  aM._i2 = &(_filesData[img2]);
987  }
988  else
989  {
990  aM._i1 = &(_filesData[img2]);
991  aM._i2 = &(_filesData[img1]);
992  };
993  checkedImagePairs[img1].insert(img2);
994  checkedImagePairs[img2].insert(img1);
995  };
996  };
997  };
998  TRACE_INFO(std::endl<< "--- Find matches ---" << std::endl);
999  for (size_t i = 0; i < matchesData.size(); ++i)
1000  {
1001  queue.push_back(new MatchDataRunnable(matchesData[i], *this));
1002  };
1003  RunQueue(queue);
1004 
1005  // Add detected matches to _panoramaInfo
1006  for (size_t i = 0; i < matchesData.size(); ++i)
1007  {
1008  const MatchData& aM = matchesData[i];
1009  for (size_t j = 0; j < aM._matches.size(); ++j)
1010  {
1011  const lfeat::PointMatchPtr& aPM = aM._matches[j];
1012  _panoramaInfo->addCtrlPoint(HuginBase::ControlPoint(aM._i1->_number, aPM->_img1_x, aPM->_img1_y,
1013  aM._i2->_number, aPM->_img2_x, aPM->_img2_y));
1014  };
1015  };
1016 
1017  // step 2: connect all image groups
1018  queue.clear();
1019  matchesData.clear();
1021  HuginGraph::ImageGraph graph(mediumPano);
1022  const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
1023  const size_t n = comps.size();
1024  if(n>1)
1025  {
1026  std::vector<unsigned int> ImagesGroups;
1027  for(size_t i=0; i<n; i++)
1028  {
1029  HuginBase::UIntSet::iterator imgIt = _image_layer.begin();
1030  std::advance(imgIt, *(comps[i].begin()));
1031  ImagesGroups.push_back(*imgIt);
1032  if(comps[i].size()>1)
1033  {
1034  imgIt = _image_layer.begin();
1035  std::advance(imgIt, *(comps[i].rbegin()));
1036  ImagesGroups.push_back(*imgIt);
1037  }
1038  };
1039  for(unsigned int i=0; i<ImagesGroups.size()-1; i++)
1040  {
1041  for(unsigned int j=i+1; j<ImagesGroups.size(); j++)
1042  {
1043  size_t img1=ImagesGroups[i];
1044  size_t img2=ImagesGroups[j];
1045  //skip already checked image pairs
1046  if(set_contains(checkedImagePairs[img1],img2))
1047  {
1048  continue;
1049  };
1050  matchesData.push_back(MatchData());
1051  MatchData& aM = matchesData.back();
1052  if (img1 < img2)
1053  {
1054  aM._i1 = &(_filesData[img1]);
1055  aM._i2 = &(_filesData[img2]);
1056  }
1057  else
1058  {
1059  aM._i1 = &(_filesData[img2]);
1060  aM._i2 = &(_filesData[img1]);
1061  };
1062  checkedImagePairs[img1].insert(img2);
1063  checkedImagePairs[img2].insert(img1);
1064  };
1065  };
1066  TRACE_INFO(std::endl<< "--- Find matches in images groups ---" << std::endl);
1067  for (size_t i = 0; i < matchesData.size(); ++i)
1068  {
1069  queue.push_back(new MatchDataRunnable(matchesData[i], *this));
1070  };
1071  RunQueue(queue);
1072 
1073  for (size_t i = 0; i < matchesData.size(); ++i)
1074  {
1075  const MatchData& aM = matchesData[i];
1076  for (size_t j = 0; j < aM._matches.size(); ++j)
1077  {
1078  const lfeat::PointMatchPtr& aPM = aM._matches[j];
1079  _panoramaInfo->addCtrlPoint(HuginBase::ControlPoint(aM._i1->_number, aPM->_img1_x, aPM->_img1_y,
1080  aM._i2->_number, aPM->_img2_x, aPM->_img2_y));
1081  };
1082  };
1083  };
1084  // step 3: now connect all overlapping images
1085  queue.clear();
1086  matchesData.clear();
1088  HuginGraph::ImageGraph graph2(optPano);
1089  if(graph2.IsConnected())
1090  {
1091  if(_image_layer.size()>2)
1092  {
1093  //reset translation parameters
1094  HuginBase::VariableMapVector varMapVec = optPano.getVariables();
1095  for(size_t i=0; i<varMapVec.size(); i++)
1096  {
1097  map_get(varMapVec[i], "TrX").setValue(0);
1098  map_get(varMapVec[i], "TrY").setValue(0);
1099  map_get(varMapVec[i], "TrZ").setValue(0);
1100  };
1101  optPano.updateVariables(varMapVec);
1102  //next steps happens only when all images are connected;
1103  //now optimize panorama
1104  HuginBase::PanoramaOptions opts = optPano.getOptions();
1106  opts.optimizeReferenceImage=0;
1107  // calculate proper scaling, 1:1 resolution.
1108  // Otherwise optimizer distances are meaningless.
1109  opts.setWidth(30000, false);
1110  opts.setHeight(15000);
1111 
1112  optPano.setOptions(opts);
1114  opts.setWidth(w);
1115  opts.setHeight(w/2);
1116  optPano.setOptions(opts);
1117 
1118  //generate optimize vector, optimize only yaw and pitch
1119  HuginBase::OptimizeVector optvars;
1120  for (unsigned i=0; i < optPano.getNrOfImages(); i++)
1121  {
1122  std::set<std::string> imgopt;
1123  if(i==opts.optimizeReferenceImage)
1124  {
1125  //optimize only anchors pitch, not yaw
1126  imgopt.insert("p");
1127  }
1128  else
1129  {
1130  imgopt.insert("p");
1131  imgopt.insert("y");
1132  };
1133  optvars.push_back(imgopt);
1134  }
1135  optPano.setOptimizeVector(optvars);
1136 
1137  // remove vertical and horizontal control points
1138  HuginBase::CPVector cps = optPano.getCtrlPoints();
1139  HuginBase::CPVector newCP;
1140  for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
1141  {
1142  if (it->mode == HuginBase::ControlPoint::X_Y)
1143  {
1144  newCP.push_back(*it);
1145  }
1146  }
1147  optPano.setCtrlPoints(newCP);
1148 
1149  if (getVerbose() < 2)
1150  {
1151  PT_setProgressFcn(ptProgress);
1152  PT_setInfoDlgFcn(ptinfoDlg);
1153  };
1154  //in a first step do a pairwise optimisation
1155  HuginBase::AutoOptimise::autoOptimise(optPano, false);
1156  //now the final optimisation
1157  HuginBase::PTools::optimize(optPano);
1158  if (getVerbose() < 2)
1159  {
1160  PT_setProgressFcn(NULL);
1161  PT_setInfoDlgFcn(NULL);
1162  };
1163 
1164  //now match overlapping images
1165  std::vector<size_t> imgMap(_image_layer.begin(), _image_layer.end());
1166  if(!matchPrealigned(&optPano, checkedImagePairs, imgMap, false))
1167  {
1168  return false;
1169  };
1170  };
1171  }
1172  else
1173  {
1174  if(!match(checkedImagePairs))
1175  {
1176  return false;
1177  };
1178  };
1179  return true;
1180 };
1181 
1182 bool PanoDetector::matchPrealigned(HuginBase::Panorama* pano, std::vector<HuginBase::UIntSet> &connectedImages, std::vector<size_t> imgMap, bool exactOverlap)
1183 {
1184  RunnableVector queue;
1185  MatchData_t matchesData;
1186  HuginBase::Panorama tempPano = pano->duplicate();
1187  if(!exactOverlap)
1188  {
1189  // increase hfov by 25 % to handle narrow overlaps (or even no overlap) better
1190  HuginBase::VariableMapVector varMapVec = tempPano.getVariables();
1191  for(size_t i=0; i<tempPano.getNrOfImages(); i++)
1192  {
1193  HuginBase::Variable& hfovVar = map_get(varMapVec[i], "v");
1194  double newHFOV = 1.25 * hfovVar.getValue();
1195  switch (tempPano.getImage(i).getProjection())
1196  {
1197  // range checking
1199  newHFOV = std::min(170.0, newHFOV);
1200  break;
1201  default:
1202  newHFOV = std::min(360.0, newHFOV);
1203  break;
1204  }
1205  hfovVar.setValue(newHFOV);
1206  };
1207  tempPano.updateVariables(varMapVec);
1208  };
1209  HuginBase::CalculateImageOverlap overlap(&tempPano);
1210  overlap.calculate(10);
1211  for(size_t i=0; i<tempPano.getNrOfImages()-1; i++)
1212  {
1213  for(size_t j=i+1; j<tempPano.getNrOfImages(); j++)
1214  {
1215  if(set_contains(connectedImages[imgMap[i]],imgMap[j]))
1216  {
1217  continue;
1218  };
1219  if(overlap.getOverlap(i,j)>0)
1220  {
1221  matchesData.push_back(MatchData());
1222  MatchData& aM = matchesData.back();
1223  aM._i1 = &(_filesData[imgMap[i]]);
1224  aM._i2 = &(_filesData[imgMap[j]]);
1225  connectedImages[imgMap[i]].insert(imgMap[j]);
1226  connectedImages[imgMap[j]].insert(imgMap[i]);
1227  };
1228  };
1229  };
1230 
1231  TRACE_INFO(std::endl<< "--- Find matches for overlapping images ---" << std::endl);
1232  for (size_t i = 0; i < matchesData.size(); ++i)
1233  {
1234  queue.push_back(new MatchDataRunnable(matchesData[i], *this));
1235  };
1236  RunQueue(queue);
1237 
1238  // Add detected matches to _panoramaInfo
1239  for (size_t i = 0; i < matchesData.size(); ++i)
1240  {
1241  const MatchData& aM = matchesData[i];
1242  for (size_t j = 0; j < aM._matches.size(); ++j)
1243  {
1244  const lfeat::PointMatchPtr& aPM = aM._matches[j];
1245  _panoramaInfo->addCtrlPoint(HuginBase::ControlPoint(aM._i1->_number, aPM->_img1_x, aPM->_img1_y,
1246  aM._i2->_number, aPM->_img2_x, aPM->_img2_y));
1247  };
1248  };
1249 
1250  return true;
1251 };
virtual void run()
double _celesteThreshold
Definition: PanoDetector.h:354
void destroySVMmodel(struct svm_model *&model)
frees the resource of model
Definition: Celeste.cpp:60
std::string _inputFile
Definition: PanoDetector.h:364
WriteKeyPointsRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
LoadKeypointsDataRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
declaration of functions to handle stacks and layers
SizeMode GetSizeMode() const
Definition: PanoDetector.h:438
void RunQueue(std::vector< Runnable * > &queue)
MatchingStrategy _matchingStrategy
Definition: PanoDetector.h:345
bool checkLoadSuccess()
MatchingStrategy getMatchingStrategy() const
Definition: PanoDetector.h:232
#define srandom
void setHeight(unsigned int h)
set panorama height
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
std::string _prefix
Definition: PanoDetector.h:357
ImgDataRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
virtual void run()
void CleanupKeyfiles()
void setCores(int iCores)
Definition: PanoDetector.h:308
const PanoDetector & _panoDetector
const PanoDetector & _panoDetector
static bool LoadKeypoints(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
vigra::Rect2D estimateOutputROI(const PanoramaData &pano, const PanoramaOptions &opts, unsigned i, const double maxLength)
static bool MakeKeyPointDescriptorsInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
Somewhere to specify what variables belong to what.
unsigned int getHeight() const
get panorama height
HuginBase::PanoramaOptions _projOpts
Definition: PanoDetector.h:401
bool IsConnected()
check if all images are connected
Definition: ImageGraph.cpp:128
Contains functions to transform whole images.
int _ransacDistanceThres
Definition: PanoDetector.h:339
int getVerbose() const
Definition: PanoDetector.h:115
a variable has a value and a name.
static int ptinfoDlg(int command, char *argument)
Definition: icpfind.cpp:103
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
static int ptProgress(int command, char *argument)
Definition: icpfind.cpp:99
void calculate(unsigned int steps)
does the calculation, for each image steps*steps points are extracted and tested with all other image...
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
MatchDataRunnable(PanoDetector::MatchData &iMatchData, const PanoDetector &iPanoDetector)
bool matchPrealigned(HuginBase::Panorama *pano, std::vector< HuginBase::UIntSet > &connectedImages, std::vector< size_t > imgMap, bool exactOverlap=true)
does only matches image pairs which overlaps and don&#39;t have control points
bool matchMultiRow()
represents a control point
Definition: ControlPoint.h:38
virtual void updateVariables(const VariableMapVector &vars)
Set the variables.
Definition: Panorama.cpp:171
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition: Panorama.cpp:297
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition: ImageGraph.h:50
std::vector< Runnable * > RunnableVector
Panorama duplicate() const
duplicate the panorama
Definition: Panorama.cpp:1653
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
const PanoDetector & _panoDetector
std::vector< VariableMap > VariableMapVector
static bool FilterKeyPointsInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
Model for a panorama.
Definition: Panorama.h:152
std::string GetDataDir()
returns the full path to the data directory
Definition: utils.cpp:441
bool loadSVMmodel(struct svm_model *&model, std::string &model_file)
loads the SVM model from file
Definition: Celeste.cpp:45
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
Definition: Panorama.cpp:381
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
std::vector< HuginBase::UIntVector > _image_stacks
vector with image numbers of all stacks, contains only the unlinked stacks
Definition: PanoDetector.h:377
VariableMapVector getVariables() const
get variables of this panorama
Definition: Panorama.cpp:118
int _kdTreeSearchSteps
Definition: PanoDetector.h:333
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
void buildMultiRowImageSets()
search for image layer and image stacks for the multirow matching step
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be &#39;add&#39; method?)
Definition: Panorama.cpp:449
Map::mapped_type & map_get(Map &m, const typename Map::key_type &key)
get a map element.
Definition: stl_utils.h:98
std::set< std::string > _cpsHashSet
Definition: PanoDetector.h:369
virtual void run()=0
platform/compiler specific stuff.
static double calcOptimalScale(PanoramaData &panorama)
static bool FindMatchesInPair(MatchData &ioMatchData, const PanoDetector &iPanoDetector)
PanoDetector::ImgData & _imgData
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Definition: Panorama.cpp:2023
PanoDetector::MatchData & _matchData
bool loadProject()
double _kdTreeSecondDistance
Definition: PanoDetector.h:334
ImgData_t _filesData
Definition: PanoDetector.h:477
static bool RansacMatchesInPair(MatchData &ioMatchData, const PanoDetector &iPanoDetector)
HuginBase::UIntSet _image_layer
image set contains only the images with the median exposure of each stack
Definition: PanoDetector.h:375
std::vector< HuginBase::UIntVector > getSortedStacks(const HuginBase::Panorama *pano)
returns vector of UIntVector with image numbers of each stack sorted by exposure
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition: utils.cpp:130
static bool RemapBackKeypoints(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
bool match(std::vector< HuginBase::UIntSet > &checkedPairs)
double getValue() const
std::map< int, ImgData >::iterator ImgDataIt_t
Definition: PanoDetector.h:446
virtual ~Runnable()
std::string includeTrailingPathSep(std::string path)
void setROI(const vigra::Rect2D &val)
static bool FreeMemoryInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
!! from PTOptimise.h 1951
lfeat::PointMatchVector_t _matches
Definition: PanoDetector.h:452
#define TRACE_IMG(X)
void updateMasks(bool convertPosMaskToNeg=false)
updates all active masks
Definition: Panorama.cpp:988
void printFilenames()
#define TRACE_INFO(x)
Definition: Tracer.h:26
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
HuginBase::Panorama _panoramaInfoCopy
Definition: PanoDetector.h:368
struct celeste::svm_model * svmModel
Definition: PanoDetector.h:478
unsigned int getWidth() const
HuginBase::RANSACOptimizer::Mode _ransacMode
Definition: PanoDetector.h:337
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
static bool FilterMatchesInPair(MatchData &ioMatchData, const PanoDetector &iPanoDetector)
lfeat::KeyPointVect_t _kp
Definition: PanoDetector.h:406
PanoDetector::ImgData & _imgData
std::string _keypath
Definition: PanoDetector.h:356
Components GetComponents()
find all connected components
Definition: ImageGraph.cpp:101
definitions of classes to calculate overlap between different images
static bool AnalyzeImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
bool LoadSVMModel()
bool _writeAllKeyPoints
Definition: PanoDetector.h:324
std::string _keyfilename
Definition: PanoDetector.h:404
std::string _outputFile
Definition: PanoDetector.h:362
static T max(T x, T y)
Definition: svm.cpp:65
unsigned long long getTotalMemory()
returns the total memory in byte
Definition: Utils.cpp:65
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
std::vector< std::set< std::string > > OptimizeVector
class for calculating overlap of images
HuginBase::Panorama * _panoramaInfo
Definition: PanoDetector.h:367
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
void writeKeyfile(ImgData &imgInfo)
unsigned int GetPhysicalCPUCount()
return the number of physical cpu cores
Definition: Utils.cpp:126
const PanoDetector & _panoDetector
std::vector< int > _keyPointsIdx
Definition: PanoDetector.h:325
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
std::string getKeyfilenameFor(std::string keyfilesPath, std::string filename)
returns the filename for the keyfile for a given image
Panorama image options.
std::shared_ptr< PointMatch > PointMatchPtr
Definition: PointMatch.h:52
void setImage(std::size_t nr, const SrcPanoImage &img)
set a panorama image, counting starts with 0
Definition: Panorama.h:218
PanoDetector::ImgData & _imgData
std::vector< MatchData > MatchData_t
Definition: PanoDetector.h:455
static T min(T x, T y)
Definition: svm.cpp:62
void setCeleste(bool iCeleste)
Definition: PanoDetector.h:280
#define TRACE_PAIR(X)
static bool FindKeyPointsInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
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
void setValue(double v)
static bool BuildKDTreesInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
static void autoOptimise(PanoramaData &pano, bool optRoll=true)
void printDetails()
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition: ImageGraph.h:44