53 #include <hugin_config.h>
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);}}
69 std::string pathWithSep(path);
71 if(pathWithSep[pathWithSep.length()-1]!=
'\\' || pathWithSep[pathWithSep.length()-1]!=
'/')
73 pathWithSep.append(
"\\");
76 if(pathWithSep[pathWithSep.length()-1]!=
'/')
78 pathWithSep.append(
"/");
86 std::string newfilename;
87 if(keyfilesPath.empty())
97 newfilename.append(
".key");
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)
125 std::cout <<
"Linear match length must be at least 1." << std::endl;
134 std::cout <<
"In test mode you must provide exactly 2 images." << std::endl;
144 std::cout <<
"Input file : " <<
_inputFile << std::endl;
147 std::cout <<
"Output file(s) : keyfile(s) for images";
157 std::cout <<
"Output file(s) : keyfiles for all images in project" << std::endl;
161 std::cout <<
"Output file : " <<
_outputFile << std::endl;
166 std::cout <<
"Path to keyfiles : " <<
_keypath << std::endl;
170 std::cout <<
"Cleanup temporary files." << std::endl;
174 std::cout <<
"Automatically cache keypoints files to disc." << std::endl;
176 std::cout <<
"Input image options" << std::endl;
177 std::cout <<
" Downscale to half-size : " << (
_downscale?
"yes":
"no") << std::endl;
180 std::cout <<
"Celeste options" << std::endl;
184 std::cout <<
"Sieve 1 Options" << std::endl;
187 std::cout <<
" Size : " <<
_sieve1Size << std::endl;
189 std::cout <<
"KDTree Options" << std::endl;
192 std::cout <<
"Matching Options" << std::endl;
196 std::cout <<
" Mode : All pairs" << std::endl;
199 std::cout <<
" Mode : Linear match with length of " <<
_linearMatchLen <<
" image" << std::endl;
202 std::cout <<
" Mode : Multi row" << std::endl;
205 std::cout <<
" Mode : Prealigned positions" << std::endl;
209 std::cout <<
"RANSAC Options" << std::endl;
210 std::cout <<
" Mode : ";
214 std::cout <<
"auto" << std::endl;
217 std::cout <<
"homography" << std::endl;
220 std::cout <<
"roll, pitch, yaw" << std::endl;
223 std::cout <<
"roll, pitch, yaw, fov" << std::endl;
226 std::cout <<
"roll, pitch, yaw, fov, distortion" << std::endl;
229 std::cout <<
" Iterations : " <<
_ransacIters << std::endl;
231 std::cout <<
"Minimum matches per image pair: " <<
_minimumMatches << std::endl;
232 std::cout <<
"Sieve 2 Options" << std::endl;
235 std::cout <<
" Size : " <<
_sieve2Size << std::endl;
241 std::cout << std::endl <<
"Project contains the following images:" << std::endl;
247 name=name.substr(
_prefix.length(),name.length()-
_prefix.length());
249 std::cout <<
"Image " << i << std::endl <<
" Imagefile: " << name << std::endl;
250 bool writeKeyfileForImage=
false;
253 for(
unsigned j=0; j<
_keyPointsIdx.size() && !writeKeyfileForImage; j++)
263 name=name.substr(
_prefix.length(),name.length()-
_prefix.length());
265 std::cout <<
" Keyfile : " << name;
266 if(writeKeyfileForImage)
268 std::cout <<
" (will be generated)" << std::endl;
272 std::cout << (
_filesData[i]._hasakeyfile?
" (will be loaded)":
" (will be generated)") << std::endl;
275 std::cout <<
" Remapped : " << (
_filesData[i].NeedsRemapping()?
"yes":
"no") << std::endl;
283 virtual void run() = 0;
382 std::string model_file = (
"celeste.model");
383 std::ifstream test(model_file.c_str());
387 install_path_model.append(model_file);
388 std::ifstream test2(install_path_model.c_str());
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;
395 model_file = install_path_model;
409 #pragma omp parallel for schedule(dynamic)
410 for (
int i = 0; i < queue.size(); ++i)
415 while (!queue.empty())
425 srandom((
unsigned int)time(NULL));
447 unsigned long maxImageSize=0;
448 bool withRemap=
false;
451 if(!aB->second._hasakeyfile)
453 maxImageSize=std::max<unsigned long>(aB->second._detectWidth*aB->second._detectHeight,maxImageSize);
454 if(aB->second.NeedsRemapping())
471 if (maxImageSize != 0)
473 unsigned long long maxCores;
493 std::cout <<
"\nThe available memory does not allow running " <<
_cores <<
" threads parallel.\n"
494 <<
"Running cpfind with " << maxCores <<
" threads.\n";
499 omp_set_num_threads(
_cores);
500 std::cout <<
"Using " <<
_cores <<
" threads" << std::endl;
506 TRACE_INFO(
"\nLoading Celeste model file...\n");
524 std::string s=vigra::impexListExtensions();
530 TRACE_INFO(std::endl <<
"--- Analyze Images ---" << std::endl);
539 TRACE_INFO(std::endl <<
"--- Analyze Images ---" << std::endl);
550 for (HuginBase::UIntSet::const_iterator it = imagesToAnalyse.begin(); it != imagesToAnalyse.end(); ++it)
566 if (aB->second._hasakeyfile)
587 TRACE_INFO(
"One or more images failed to load. Exiting.");
593 TRACE_INFO(std::endl <<
"--- Cache keyfiles to disc ---" << std::endl);
596 if (!aB->second._hasakeyfile)
598 TRACE_INFO(
"i" << aB->second._number <<
" : Caching keypoints..." << std::endl);
630 for(HuginBase::CPVector::const_iterator it=cps.begin();it!=cps.end(); ++it)
634 connectedImages[(*it).image1Nr].insert((*it).image2Nr);
635 connectedImages[(*it).image2Nr].insert((*it).image1Nr);
658 TRACE_INFO(std::endl<<
"--- Write Keyfiles output ---" << std::endl << std::endl);
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;
674 TRACE_INFO(std::endl<<
"--- Write Project output ---" << std::endl);
696 for (
unsigned int i1 = 0; i1 <
_filesData.size(); ++i1)
698 unsigned int aEnd = i1 + 1 + aLen;
704 for (
unsigned int i2 = (i1+1); i2 < aEnd; ++i2)
717 checkedPairs[i1].insert(i2);
718 checkedPairs[i2].insert(i1);
722 TRACE_INFO(std::endl<<
"--- Find pair-wise matches ---" << std::endl);
723 for (
size_t i = 0; i < matchesData.size(); ++i)
730 for (
size_t i = 0; i < matchesData.size(); ++i)
733 for (
size_t j = 0; j < aM.
_matches.size(); ++j)
737 aM.
_i2->
_number, aPM->_img2_x, aPM->_img2_y));
751 #define getcwd _getcwd
753 if((buffer=getcwd(NULL,0))!=NULL)
772 for (
auto& cp : allCps)
779 unsigned int imgWithKeyfile=0;
780 for (
unsigned int imgNr = 0; imgNr < nImg; ++imgNr)
792 aImgData.
_name = img.getFilename();
811 _filesData[imgNr]._detectWidth =
std::max(img.getSize().width(),img.getSize().height());
812 _filesData[imgNr]._detectHeight =
std::max(img.getSize().width(),img.getSize().height());
817 _filesData[imgNr]._detectWidth = img.getSize().width();
818 _filesData[imgNr]._detectHeight = img.getSize().height();
846 (double)
_filesData[imgNr]._detectHeight / roi.height() );
857 _filesData[imgNr]._detectHeight = roi.height();
875 if(nImg==imgWithKeyfile)
896 for (
unsigned int aFileN = 0; aFileN <
_filesData.size(); ++aFileN)
911 if (aB->second._hasakeyfile)
913 remove(aB->second._keyfilename.c_str());
922 for (
size_t i = 0; i < stacks.size(); ++i)
927 index = stacks[i].size() / 2;
930 if (stacks[i].size()>1)
966 checkedImagePairs[img1].insert(img2);
967 checkedImagePairs[img2].insert(img1);
975 const size_t img1 = *it;
976 HuginBase::UIntSet::const_iterator it2 = it;
980 const size_t img2 = *it2;
993 checkedImagePairs[img1].insert(img2);
994 checkedImagePairs[img2].insert(img1);
998 TRACE_INFO(std::endl<<
"--- Find matches ---" << std::endl);
999 for (
size_t i = 0; i < matchesData.size(); ++i)
1006 for (
size_t i = 0; i < matchesData.size(); ++i)
1009 for (
size_t j = 0; j < aM.
_matches.size(); ++j)
1013 aM.
_i2->
_number, aPM->_img2_x, aPM->_img2_y));
1019 matchesData.clear();
1023 const size_t n = comps.size();
1026 std::vector<unsigned int> ImagesGroups;
1027 for(
size_t i=0; i<n; i++)
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)
1035 std::advance(imgIt, *(comps[i].rbegin()));
1036 ImagesGroups.push_back(*imgIt);
1039 for(
unsigned int i=0; i<ImagesGroups.size()-1; i++)
1041 for(
unsigned int j=i+1; j<ImagesGroups.size(); j++)
1043 size_t img1=ImagesGroups[i];
1044 size_t img2=ImagesGroups[j];
1062 checkedImagePairs[img1].insert(img2);
1063 checkedImagePairs[img2].insert(img1);
1066 TRACE_INFO(std::endl<<
"--- Find matches in images groups ---" << std::endl);
1067 for (
size_t i = 0; i < matchesData.size(); ++i)
1073 for (
size_t i = 0; i < matchesData.size(); ++i)
1076 for (
size_t j = 0; j < aM.
_matches.size(); ++j)
1080 aM.
_i2->
_number, aPM->_img2_x, aPM->_img2_y));
1086 matchesData.clear();
1095 for(
size_t i=0; i<varMapVec.size(); i++)
1097 map_get(varMapVec[i],
"TrX").setValue(0);
1098 map_get(varMapVec[i],
"TrY").setValue(0);
1099 map_get(varMapVec[i],
"TrZ").setValue(0);
1122 std::set<std::string> imgopt;
1133 optvars.push_back(imgopt);
1140 for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
1144 newCP.push_back(*it);
1160 PT_setProgressFcn(NULL);
1161 PT_setInfoDlgFcn(NULL);
1174 if(!
match(checkedImagePairs))
1194 double newHFOV = 1.25 * hfovVar.
getValue();
1195 switch (tempPano.
getImage(i).getProjection())
1199 newHFOV =
std::min(170.0, newHFOV);
1202 newHFOV =
std::min(360.0, newHFOV);
1225 connectedImages[imgMap[i]].insert(imgMap[j]);
1226 connectedImages[imgMap[j]].insert(imgMap[i]);
1231 TRACE_INFO(std::endl<<
"--- Find matches for overlapping images ---" << std::endl);
1232 for (
size_t i = 0; i < matchesData.size(); ++i)
1239 for (
size_t i = 0; i < matchesData.size(); ++i)
1242 for (
size_t j = 0; j < aM.
_matches.size(); ++j)
1246 aM.
_i2->
_number, aPM->_img2_x, aPM->_img2_y));
void destroySVMmodel(struct svm_model *&model)
frees the resource of model
WriteKeyPointsRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
LoadKeypointsDataRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
bool FileExists(const std::string &filename)
checks if file exists
declaration of functions to handle stacks and layers
SizeMode GetSizeMode() const
void RunQueue(std::vector< Runnable * > &queue)
MatchingStrategy _matchingStrategy
MatchingStrategy getMatchingStrategy() const
void setHeight(unsigned int h)
set panorama height
double getOverlap(unsigned int i, unsigned int j) const
returns the overlap for 2 images with number i and j
ImgDataRunnable(PanoDetector::ImgData &iImageData, const PanoDetector &iPanoDetector)
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
void setCores(int iCores)
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
bool IsConnected()
check if all images are connected
Contains functions to transform whole images.
a variable has a value and a name.
static int ptinfoDlg(int command, char *argument)
bool set_contains(const _Container &c, const typename _Container::key_type &key)
static int ptProgress(int command, char *argument)
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
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't have control points
represents a control point
virtual void updateVariables(const VariableMapVector &vars)
Set the variables.
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
std::vector< Runnable * > RunnableVector
Panorama duplicate() const
duplicate the panorama
std::set< unsigned int > UIntSet
const PanoDetector & _panoDetector
std::vector< VariableMap > VariableMapVector
static bool FilterKeyPointsInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
std::string GetDataDir()
returns the full path to the data directory
bool loadSVMmodel(struct svm_model *&model, std::string &model_file)
loads the SVM model from file
unsigned int addCtrlPoint(const ControlPoint &point)
add a new control point.
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
std::vector< HuginBase::UIntVector > _image_stacks
vector with image numbers of all stacks, contains only the unlinked stacks
VariableMapVector getVariables() const
get variables of this panorama
std::size_t getNrOfImages() const
number of images.
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 'add' method?)
Map::mapped_type & map_get(Map &m, const typename Map::key_type &key)
get a map element.
std::set< std::string > _cpsHashSet
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...
PanoDetector::MatchData & _matchData
double _kdTreeSecondDistance
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
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
static bool RemapBackKeypoints(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
bool match(std::vector< HuginBase::UIntSet > &checkedPairs)
std::map< int, ImgData >::iterator ImgDataIt_t
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
void updateMasks(bool convertPosMaskToNeg=false)
updates all active masks
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
HuginBase::Panorama _panoramaInfoCopy
struct celeste::svm_model * svmModel
unsigned int getWidth() const
HuginBase::RANSACOptimizer::Mode _ransacMode
const PanoramaOptions & getOptions() const
returns the options for this panorama
static bool FilterMatchesInPair(MatchData &ioMatchData, const PanoDetector &iPanoDetector)
lfeat::KeyPointVect_t _kp
PanoDetector::ImgData & _imgData
Components GetComponents()
find all connected components
definitions of classes to calculate overlap between different images
static bool AnalyzeImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
unsigned long long getTotalMemory()
returns the total memory in byte
std::vector< ControlPoint > CPVector
std::vector< std::set< std::string > > OptimizeVector
class for calculating overlap of images
HuginBase::Panorama * _panoramaInfo
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
void writeKeyfile(ImgData &imgInfo)
unsigned int GetPhysicalCPUCount()
return the number of physical cpu cores
const PanoDetector & _panoDetector
std::vector< int > _keyPointsIdx
All variables of a source image.
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
std::shared_ptr< PointMatch > PointMatchPtr
void setImage(std::size_t nr, const SrcPanoImage &img)
set a panorama image, counting starts with 0
PanoDetector::ImgData & _imgData
std::vector< MatchData > MatchData_t
void setCeleste(bool iCeleste)
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)
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
static bool BuildKDTreesInImage(ImgData &ioImgInfo, const PanoDetector &iPanoDetector)
static void autoOptimise(PanoramaData &pano, bool optRoll=true)
unsigned int optimizeReferenceImage
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...