From: <hug...@li...> - 2010-06-24 16:48:38
|
details: http://hugin.hg.sourceforge.net/hgweb/hugin/hugin/hgrepo/h/hu/hugin/hugin/rev/f41a4c1ff971 changeset: 4092:f41a4c1ff971 user: Antoine date: Thu Jun 24 18:47:54 2010 +0200 description: New usage for the panomatic command line. Tests needed. BUG: too few matches when using keyfiles. diffstat: src/libpanomatic/localfeatures/KeyPointIO.cpp | 2 + src/libpanomatic/panomatic/PanoDetector.cpp | 220 +++++++++++++--------- src/libpanomatic/panomatic/PanoDetector.h | 51 ++-- src/libpanomatic/panomatic/PanoDetectorLogic.cpp | 86 ++++---- src/libpanomatic/panomatic/main.cpp | 78 ++----- 5 files changed, 224 insertions(+), 213 deletions(-) diffs (truncated from 711 to 500 lines): diff -r e22b7586b33a -r f41a4c1ff971 src/libpanomatic/localfeatures/KeyPointIO.cpp --- a/src/libpanomatic/localfeatures/KeyPointIO.cpp Sun Jun 20 17:30:51 2010 +0200 +++ b/src/libpanomatic/localfeatures/KeyPointIO.cpp Thu Jun 24 18:47:54 2010 +0200 @@ -134,6 +134,8 @@ void DescPerfFormatWriter::writeFooter() { + o << _image.filename << endl; + o << _image.width << " " << _image.height << endl; } diff -r e22b7586b33a -r f41a4c1ff971 src/libpanomatic/panomatic/PanoDetector.cpp --- a/src/libpanomatic/panomatic/PanoDetector.cpp Sun Jun 20 17:30:51 2010 +0200 +++ b/src/libpanomatic/panomatic/PanoDetector.cpp Thu Jun 24 18:47:54 2010 +0200 @@ -20,12 +20,11 @@ using namespace hugin_utils; -PanoDetector::PanoDetector() : _loadKeypoints(false), _outputFile("default0.oto"), - _loadProject(false), - _gradDescriptor(false), - _sieve1Width(10), _sieve1Height(10), _sieve1Size(10), +PanoDetector::PanoDetector() : _outputFile("default.pto"), + _writeAllKeyPoints(false), + _sieve1Width(10), _sieve1Height(10), _sieve1Size(30), _kdTreeSearchSteps(40), _kdTreeSecondDistance(0.15), _sieve2Width(5), _sieve2Height(5), - _sieve2Size(1), _test(false), _cores(utils::getCPUCount()), _ransacIters(1000), _ransacDistanceThres(25), + _sieve2Size(2), _test(false), _cores(utils::getCPUCount()), _ransacIters(1000), _ransacDistanceThres(25), _minimumMatches(4), _linearMatch(false), _linearMatchLen(1), _downscale(true) { _panoramaInfo = new Panorama(); @@ -56,24 +55,30 @@ } void PanoDetector::printDetails() -{ - //cout << "\tNumber of keys : " << _numKeys << endl; - cout << "Output file : " << _outputFile << endl; +{ + cout << "Input file : " << _inputFile << endl; + if (_writeAllKeyPoints) + { + cout << "Output files : one keyfile per image" << endl; + } else if (_keyPointsIdx.size() != 0) { + cout << "Output file(s) : keyfile(s) for images"; + for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i) + cout << " " << _keyPointsIdx[i] ; + cout << endl; + } else { + cout << "Output file : " << _outputFile << endl; + } cout << "Number of CPU : " << _cores << endl << endl; - if (_loadKeypoints) { - cout << "loading keypoints from file"; - } else { - cout << "Input image options" << endl; - cout << " Downscale to half-size : " << (_downscale?"yes":"no") << endl; - if (_gradDescriptor) { - cout << "Gradient based description" << endl; - } - cout << "Sieve 1 Options" << endl; - cout << " Width : " << _sieve1Width << endl; - cout << " Height : " << _sieve1Height << endl; - cout << " Size : " << _sieve1Size << endl; - cout << " ==> Maximum keypoints per image : " << _sieve1Size * _sieve1Height * _sieve1Width << endl; - } + cout << "Input image options" << endl; + cout << " Downscale to half-size : " << (_downscale?"yes":"no") << endl; + if (_gradDescriptor) { + cout << "Gradient based description" << endl; + } + cout << "Sieve 1 Options" << endl; + cout << " Width : " << _sieve1Width << endl; + cout << " Height : " << _sieve1Height << endl; + cout << " Size : " << _sieve1Size << endl; + cout << " ==> Maximum keypoints per image : " << _sieve1Size * _sieve1Height * _sieve1Width << endl; cout << "KDTree Options" << endl; cout << " Search steps : " << _kdTreeSearchSteps << endl; cout << " Second match distance : " << _kdTreeSecondDistance << endl; @@ -92,21 +97,9 @@ cout << " Height : " << _sieve2Height << endl; cout << " Size : " << _sieve2Size << endl; cout << " ==> Maximum matches per image pair : " << _sieve2Size * _sieve2Height * _sieve2Width << endl; - - if(!_loadProject && !_loadKeypoints) - { - cout << "Input Images :" << endl; - for (unsigned int i = 0; i < _filesData.size(); ++i) - { - cout << " - " << _filesData[i]._name << endl; - } - } - if (_loadProject) - cout << "Input Project File : " << _inputProjectFile << endl; - } -// definition of a runnable class for ImgData +// definition of a runnable class for image data class ImgDataRunnable : public Runnable { public: @@ -126,8 +119,28 @@ const PanoDetector& _panoDetector; PanoDetector::ImgData& _imgData; }; + +// definition of a runnable class for writeKeyPoints +class WriteKeyPointsRunnable : public Runnable +{ +public: + WriteKeyPointsRunnable(PanoDetector::ImgData& iImageData, const PanoDetector& iPanoDetector) : + _imgData(iImageData), _panoDetector(iPanoDetector) {}; -// definition of a runnable class for loadkeys + void run() + { + if (!PanoDetector::AnalyzeImage(_imgData, _panoDetector)) return; + PanoDetector::FindKeyPointsInImage(_imgData, _panoDetector); + PanoDetector::FilterKeyPointsInImage(_imgData, _panoDetector); + PanoDetector::MakeKeyPointDescriptorsInImage(_imgData, _panoDetector); + PanoDetector::FreeMemoryInImage(_imgData, _panoDetector); + } +private: + const PanoDetector& _panoDetector; + PanoDetector::ImgData& _imgData; +}; + +// definition of a runnable class for keypoints data class LoadKeypointsDataRunnable : public Runnable { public: @@ -170,23 +183,34 @@ srandom((unsigned int)time(NULL)); PoolExecutor aExecutor(_cores); - // 1. prepare images - // if a pto file was given as input, we add its images to _files. - if(_loadProject) - { - if(!loadProject()) return; - } + // 1. Load the input project file + TRACE_INFO(endl<< "--- Prepare Images ---" << endl); + if(!loadProject()) return; // 2. run analysis of images TRACE_INFO(endl<< "--- Analyze Images ---" << endl); try { - for (unsigned int i = 0; i < _filesData.size(); ++i) - if (_loadKeypoints) { - aExecutor.execute(new LoadKeypointsDataRunnable(_filesData[i], *this)); - } else { - aExecutor.execute(new ImgDataRunnable(_filesData[i], *this)); - } + if (_keyPointsIdx.size() != 0) { + for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i) + aExecutor.execute(new WriteKeyPointsRunnable(_filesData[_keyPointsIdx[i]], *this)); + + } else if (_writeAllKeyPoints) { + for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB) + aExecutor.execute(new WriteKeyPointsRunnable(aB->second, *this)); + + } else { + for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB) + { + if (aB->second._hasakeyfile) { + aExecutor.execute(new LoadKeypointsDataRunnable(aB->second, *this)); + + } else { + aExecutor.execute(new ImgDataRunnable(aB->second, *this)); + + } + } + } aExecutor.wait(); } catch(Synchronization_Exception& e) @@ -201,76 +225,91 @@ TRACE_INFO("One or more images failed to load. Exiting."); return; } - - // 3. prepare matches - prepareMatches(); + + // Detect matches if writeKeyPoints wasn't set + if(!_writeAllKeyPoints && _keyPointsIdx.size() == 0) + { + // 3. prepare matches + prepareMatches(); - // 4. find matches - TRACE_INFO(endl<< "--- Find matches ---" << endl); - try - { - BOOST_FOREACH(MatchData& aMD, _matchesData) - aExecutor.execute(new MatchDataRunnable(aMD, *this)); - aExecutor.wait(); - } - catch(Synchronization_Exception& e) - { - TRACE_ERROR(e.what() << endl); - return; + // 4. find matches + TRACE_INFO(endl<< "--- Find matches ---" << endl); + try + { + BOOST_FOREACH(MatchData& aMD, _matchesData) + aExecutor.execute(new MatchDataRunnable(aMD, *this)); + aExecutor.wait(); + } + catch(Synchronization_Exception& e) + { + TRACE_ERROR(e.what() << endl); + return; + } + + // Add detected matches to _panoramaInfo + double scale = _downscale ? 2.0:1.0; + BOOST_FOREACH(MatchData& aM, _matchesData) + BOOST_FOREACH(lfeat::PointMatchPtr& aPM, aM._matches) + _panoramaInfo->addCtrlPoint(ControlPoint(aM._i1->_number, scale*aPM->_img1_x, scale*aPM->_img1_y, + aM._i2->_number, scale*aPM->_img2_x, scale*aPM->_img2_y)); } - // 5. write output - TRACE_INFO(endl<< "--- Write output ---" << endl); - writeOutput(); - -} + // 5. write output + if(_writeAllKeyPoints) + { + TRACE_INFO(endl<< "--- Write Keyfiles output ---" << endl << endl); + for (ImgDataIt_t aB = _filesData.begin(); aB != _filesData.end(); ++aB) + writeKeyfile(aB->second); -void PanoDetector::addFileData(int nr, const std::string& iFile) -{ - // insert the image in the vector - _filesData.push_back(ImgData()); - // get the data - ImgData& aImgData = _filesData.back(); - - // set the name - aImgData._name = iFile; + } else if (_keyPointsIdx.size() != 0) { + TRACE_INFO(endl<< "--- Write Keyfiles output ---" << endl << endl); + for (unsigned int i = 0; i < _keyPointsIdx.size(); ++i) + writeKeyfile(_filesData[_keyPointsIdx[i]]); - // set the number - aImgData._number = nr; + } else { + TRACE_INFO(endl<< "--- Write Project output ---" << endl << endl); + writeOutput(); + } } bool PanoDetector::loadProject() { - ifstream ptoFile(_inputProjectFile.c_str()); + ifstream ptoFile(_inputFile.c_str()); if (ptoFile.bad()) { - cerr << "ERROR: could not open file: '" << _inputProjectFile << "'!" << endl; + cerr << "ERROR: could not open file: '" << _inputFile << "'!" << endl; return false; } - _panoramaInfo->setFilePrefix(hugin_utils::getPathPrefix(_inputProjectFile)); + _panoramaInfo->setFilePrefix(hugin_utils::getPathPrefix(_inputFile)); AppBase::DocumentData::ReadWriteError err = _panoramaInfo->readData(ptoFile); if (err != AppBase::DocumentData::SUCCESSFUL) { - cerr << "ERROR: couldn't parse panos tool script: '" << _inputProjectFile << "'!" << endl; + cerr << "ERROR: couldn't parse panos tool script: '" << _inputFile << "'!" << endl; return false; } - // Add images found in the project file to _files + // Add images found in the project file to _filesData int nImg = _panoramaInfo->getNrOfImages(); for (unsigned int imgNr = 0; imgNr < nImg; ++imgNr) { // get image info SrcPanoImage img_info = _panoramaInfo->getImage(imgNr); - // insert the image in the vector - _filesData.push_back(ImgData()); - + // insert the image in the map + _filesData.insert(make_pair(imgNr, ImgData())); + // get the data - ImgData& aImgData = _filesData.back(); + ImgData& aImgData = _filesData[imgNr]; // set the name aImgData._name = img_info.getFilename(); // Number pointing to image info in _panoramaInfo aImgData._number = imgNr; + + // Specify if the image has an associated keypoint file TODO + std::string keyfilename = aImgData._name; + keyfilename.append(".key"); + ifstream keyfile(keyfilename.c_str()); + aImgData._hasakeyfile = keyfile.good(); } return true; @@ -287,7 +326,6 @@ return true; } - void PanoDetector::prepareMatches() { int aLen = _filesData.size(); @@ -313,5 +351,5 @@ aM._i2 = &(_filesData[i2]); } } -} - +} + diff -r e22b7586b33a -r f41a4c1ff971 src/libpanomatic/panomatic/PanoDetector.h --- a/src/libpanomatic/panomatic/PanoDetector.h Sun Jun 20 17:30:51 2010 +0200 +++ b/src/libpanomatic/panomatic/PanoDetector.h Thu Jun 24 18:47:54 2010 +0200 @@ -61,13 +61,14 @@ // accessors inline Panorama * getPanoramaInfo() const {return _panoramaInfo; } + + inline void setKeyPointsIdx(std::vector<int> keyPointsIdx) { _keyPointsIdx = keyPointsIdx; } + inline std::vector<int> getKeyPointsIdx() const { return _keyPointsIdx; } + inline void setWriteAllKeyPoints(bool writeAllKeyPoints=true) { _writeAllKeyPoints = writeAllKeyPoints; } + inline bool getWriteAllKeyPoints() const { return _writeAllKeyPoints; } inline void setGradientDescriptor(bool grad=true) { _gradDescriptor = grad; } inline bool getGradientDescriptor() const { return _gradDescriptor; } - inline void setLoadKeypoints(bool loadKeypoints) { _loadKeypoints = loadKeypoints; } - inline bool getLoadKeypoints() const { return _loadKeypoints; } - inline void setLoadProject(bool loadProject) { _loadProject = loadProject; } - inline bool getLoadProject() const { return _loadProject; } inline void setSieve1Width(int iWidth) { _sieve1Width = iWidth; } inline void setSieve1Height(int iHeight) { _sieve1Height = iHeight; } @@ -104,13 +105,11 @@ inline void setDownscale(bool iDown) { _downscale = iDown; } // inline void setNumberOfKeys(int iNumKeys) { _numKeys = iNumKeys; } - inline void setOutputFile(const std::string& iOutputFile) { _outputFile = iOutputFile; } - inline void setInputProjectFile(const std::string& iInputProjectFile) { _inputProjectFile = iInputProjectFile; } + inline void setOutputFile(const std::string& outputFile) { _outputFile = outputFile; } + inline void setInputFile(const std::string& inputFile) { _inputFile = inputFile; } inline void setTest(bool iTest) { _test = iTest; } inline bool getTest() const { return _test; } - inline void setCores(int iCores) { _cores = iCores; } - - void addFileData(int nr, const std::string& iFile); + inline void setCores(int iCores) { _cores = iCores; } // predeclaration struct ImgData; @@ -118,9 +117,10 @@ private: // options - - bool _loadKeypoints; - bool _loadProject; + + bool _writeAllKeyPoints; + std::vector<int> _keyPointsIdx; + bool _gradDescriptor; int _sieve1Width; @@ -147,35 +147,32 @@ // list of files std::string _outputFile; - std::string _inputProjectFile; + std::string _inputFile; // Store panorama information - Panorama* _panoramaInfo; - - // size of images + Panorama* _panoramaInfo; void prepareImages(); bool loadProject(); bool checkLoadSuccess(); - void prepareMatches(); + void prepareMatches(); void writeOutput(); - + void writeKeyfile(ImgData& imgInfo); // internals public: struct ImgData { std::string _name; - std::string _realImageName; ///< The real image name, differs from _name when loading keypoint files. - //TODO remove and place in _panoramaInfo->getImage(_number) + int _number; int _detectWidth; - int _detectHeight; - int _origWidth; //TODO: remove and place in _panoramaInfo->getImage(_number) - int _origHeight; // TODO: remove and place in _panoramaInfo->getImage(_number) + int _detectHeight; - lfeat::Image _ii; + lfeat::Image _ii; + + bool _hasakeyfile; lfeat::KeyPointVect_t _kp; int _descLength; bool _loadFail; @@ -185,8 +182,8 @@ KPKDTreePtr _kd; }; - typedef std::vector<ImgData> ImgData_t; - typedef std::vector<ImgData>::iterator ImgDataIt_t; + typedef std::map<int, ImgData> ImgData_t; + typedef std::map<int, ImgData>::iterator ImgDataIt_t; struct MatchData { @@ -210,7 +207,7 @@ static bool FindMatchesInPair(MatchData& ioMatchData, const PanoDetector& iPanoDetector); static bool RansacMatchesInPair(MatchData& ioMatchData, const PanoDetector& iPanoDetector); - static bool FilterMatchesInPair(MatchData& ioMatchData, const PanoDetector& iPanoDetector); + static bool FilterMatchesInPair(MatchData& ioMatchData, const PanoDetector& iPanoDetector); private: ImgData_t _filesData; diff -r e22b7586b33a -r f41a4c1ff971 src/libpanomatic/panomatic/PanoDetectorLogic.cpp --- a/src/libpanomatic/panomatic/PanoDetectorLogic.cpp Sun Jun 20 17:30:51 2010 +0200 +++ b/src/libpanomatic/panomatic/PanoDetectorLogic.cpp Thu Jun 24 18:47:54 2010 +0200 @@ -90,19 +90,17 @@ bool PanoDetector::LoadKeypoints(ImgData& ioImgInfo, const PanoDetector& iPanoDetector) { TRACE_IMG("Loading keypoints..."); - - ImageInfo info = lfeat::loadKeypoints(ioImgInfo._name, ioImgInfo._kp); + + std::string keyfilename = ioImgInfo._name; + keyfilename.append(".key"); + + ImageInfo info = lfeat::loadKeypoints(keyfilename, ioImgInfo._kp); ioImgInfo._loadFail = (info.filename.size() == 0); // update ImgData ioImgInfo._detectWidth = info.width; ioImgInfo._detectHeight = info.height; ioImgInfo._descLength = info.dimensions; - - // Create image info - SrcPanoImage img_info = SrcPanoImage(info.filename); - //add image info to panorama Info - ioImgInfo._number = iPanoDetector.getPanoramaInfo()->addImage(img_info); return true; } @@ -114,16 +112,9 @@ { ioImgInfo._loadFail = false; - //get image basic info + //get image info vigra::ImageImportInfo aImageInfo(ioImgInfo._name.c_str()); - if(!iPanoDetector.getLoadProject()) - { - //if no project was loaded, get image additional info - SrcPanoImage img_info = SrcPanoImage(ioImgInfo._name); - ioImgInfo._number = iPanoDetector.getPanoramaInfo()->addImage(img_info); - } - int aNewImgWidth = aImageInfo.width(); int aNewImgHeight = aImageInfo.height(); @@ -463,40 +454,14 @@ // make an extractor and pull the points SieveExtractorMatch aSieveExt(ioMatchData._matches); - aSieve.extract(aSieveExt); + aSieve.extract(aSieveExt); TRACE_PAIR("Kept " << ioMatchData._matches.size() << " matches."); |