From: <hug...@li...> - 2011-01-19 23:37:03
|
branch: details: http://hugin.hg.sourceforge.net/hgweb/hugin/hugin/hgrepo/h/hu/hugin/hugin/rev/5ee34e49ebb4 changeset: 4862:5ee34e49ebb4 user: Pablo d'Angelo <pab...@we...> date: Wed Jan 19 14:07:41 2011 +0100 description: Some more work on the fisheye ransac. diffstat: src/hugin_base/algorithms/optimizer/PTOptimizer.cpp | 65 ++++++++++++-------- src/hugin_base/algorithms/optimizer/PTOptimizer.h | 4 +- src/hugin_base/vigra_ext/VigQuotientEstimator.h | 3 +- src/hugin_base/vigra_ext/ransac.h | 16 +++- src/hugin_cpfind/cpfind/PanoDetector.h | 2 + src/hugin_cpfind/cpfind/PanoDetectorLogic.cpp | 56 ++++++++++------- 6 files changed, 90 insertions(+), 56 deletions(-) Unterschiede (325 Zeilen): diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_base/algorithms/optimizer/PTOptimizer.cpp --- a/src/hugin_base/algorithms/optimizer/PTOptimizer.cpp Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_base/algorithms/optimizer/PTOptimizer.cpp Wed Jan 19 14:07:41 2011 +0100 @@ -90,6 +90,7 @@ int i=0; BOOST_FOREACH(const std::string & v, m_optvars) { m_initParams[i] = m_localPano->getImage(m_li2).getVar(v); + DEBUG_DEBUG("get init var: " << v << ": " << m_initParams[i]); i++; } } @@ -123,11 +124,10 @@ int i=0; BOOST_FOREACH(const std::string & v, m_optvars) { pano->updateVariable(m_li2, Variable(v, p[i])); + DEBUG_DEBUG("set var: " << v << ": " << p[i]); i++; } - - // optimize parameters using panotools (or use a custom made optimizer here?) PTools::optimize(*pano); @@ -135,9 +135,9 @@ i=0; BOOST_FOREACH(const std::string & v, m_optvars) { p[i] = pano->getImage(m_li2).getVar(v); + DEBUG_DEBUG("get var: " << v << ": " << p[i]); i++; } - return true; } @@ -149,9 +149,9 @@ int i=0; BOOST_FOREACH(const std::string & v, m_optvars) { pano->updateVariable(m_li2, Variable(v, p[i])); + DEBUG_DEBUG("set var (i2): " << v << ": " << p[i]<< " var (i1):" << pano->getImage(m_li1).getVar(v)); i++; } - // TODO: argh, this is slow, we should really construct this only once // and reuse it for all calls... PTools::Transform trafo_i1_to_pano; @@ -159,22 +159,26 @@ PTools::Transform trafo_pano_to_i2; trafo_pano_to_i2.createTransform(m_localPano->getImage(m_li2),m_localPano->getOptions()); - double x2,y2,xt,yt; + double x1,y1,x2,y2,xt,yt,x2t,y2t; if (cp.image1Nr == m_li1) { - trafo_i1_to_pano.transform(xt, yt, cp.x1, cp.y1); + x1 = cp.x1; + y1 = cp.y1; + x2 = cp.x2; + y2 = cp.y2; } else { - trafo_i1_to_pano.transform(xt, yt, cp.x2, cp.y2); + x1 = cp.x2; + y1 = cp.y2; + x2 = cp.x1; + y2 = cp.y1; } - trafo_pano_to_i2.transform(x2, y2, xt, yt); + trafo_i1_to_pano.transformImgCoord(xt, yt, x1, y1); + trafo_pano_to_i2.transformImgCoord(x2t, y2t, xt, yt); // compute error in pixels... - if (cp.image1Nr == m_li1) { - x2 -= cp.x2; - y2 -= cp.y2; - } else { - x2 -= cp.x1; - y2 -= cp.y1; - } - return hypot(x2,y2) < m_maxError; + x2t -= x2; + y2t -= y2; + double e = hypot(x2,y2); + DEBUG_DEBUG("Error i1 (0 " << x1 << " " << y1 << ") -> ("<< xt <<" "<< yt<<") -> i2 (1 "<<x2t<<", "<<y2t<<"), real ("<<x2<<", "<<y2<<") pano error: " << e) + return e < m_maxError; } ~PTOptEstimator() @@ -201,24 +205,35 @@ }; -std::vector<double> RANSACOptimizer::findInliers(PanoramaData & pano, int i1, int i2, double maxError, - const std::set<std::string> & optvec) +std::vector<int> RANSACOptimizer::findInliers(PanoramaData & pano, int i1, int i2, double maxError, + const std::set<std::string> & optvars) { - PTOptEstimator estimator(pano, i1, i2, maxError, optvec); + PTOptEstimator estimator(pano, i1, i2, maxError, optvars); - std::vector<double> parameters(estimator.m_initParams); - std::vector<const ControlPoint *> inliers = Ransac::compute(parameters, estimator, estimator.m_xy_cps, 0.99, 0.1); + std::vector<double> parameters(estimator.m_initParams.size()); + std::copy(estimator.m_initParams.begin(),estimator.m_initParams.end(), parameters.begin()); + std::vector<int> inlier_idx; + DEBUG_DEBUG("Number of control points: " << estimator.m_xy_cps.size() << " Initial parameter[0]" << parameters[0]); + std::vector<const ControlPoint *> inliers = Ransac::compute(parameters, inlier_idx, estimator, estimator.m_xy_cps, 0.99, 0.1); + DEBUG_DEBUG("Number of inliers:" << inliers.size() << "optimized parameter[0]" << parameters[0]); - printf("Found %d inliers\n", inliers.size()); - + // set parameters in pano object + int i=0; + BOOST_FOREACH(const std::string & v, optvars) { + pano.updateVariable(i2, Variable(v, parameters[i])); + i++; + } + + // return updated parameter vector + // TODO: remove bad control points from pano - return parameters; + return inlier_idx; } bool RANSACOptimizer::runAlgorithm() { - o_parameters = findInliers(o_panorama, o_i1, o_i2, o_maxError, o_optvec); + o_inliers = findInliers(o_panorama, o_i1, o_i2, o_maxError, o_optvec); return true; // let's hope so. } diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_base/algorithms/optimizer/PTOptimizer.h --- a/src/hugin_base/algorithms/optimizer/PTOptimizer.h Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_base/algorithms/optimizer/PTOptimizer.h Wed Jan 19 14:07:41 2011 +0100 @@ -84,7 +84,7 @@ virtual bool modifiesPanoramaData() const { return true; } - std::vector<double> findInliers(PanoramaData & pano, int i1, int i2, double maxError, const std::set<std::string> & optvec); + static std::vector<int> findInliers(PanoramaData & pano, int i1, int i2, double maxError, const std::set<std::string> & optvec); /// calls PTools::optimize() virtual bool runAlgorithm(); @@ -93,7 +93,7 @@ int o_i1, o_i2; double o_maxError; std::set<std::string> o_optvec; - std::vector<double> o_parameters; + std::vector<int> o_inliers; }; diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_base/vigra_ext/VigQuotientEstimator.h --- a/src/hugin_base/vigra_ext/VigQuotientEstimator.h Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_base/vigra_ext/VigQuotientEstimator.h Wed Jan 19 14:07:41 2011 +0100 @@ -399,7 +399,8 @@ for (int i=0; i < 3; i++) vigCoeff[i] = vigCoeff2[i]; #else - std::vector<const PointPair *> inliers = Ransac::compute(vigCoeff, vqEst, points, 0.99, 0.3); + std::vector<int> inliers_idx; + std::vector<const PointPair *> inliers = Ransac::compute(vigCoeff, inliers_idx, vqEst, points, 0.99, 0.3); res.nUsedPoints = inliers.size(); #endif diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_base/vigra_ext/ransac.h --- a/src/hugin_base/vigra_ext/ransac.h Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_base/vigra_ext/ransac.h Wed Jan 19 14:07:41 2011 +0100 @@ -90,7 +90,8 @@ * @return Array with inliers */ template<class Estimator, class S, class T> - static std::vector<const T*> compute(S & parameters, + static std::vector<const T*> compute(S & parameters, + std::vector<int> & inliers, const Estimator & paramEstimator , const std::vector<T> &data, double desiredProbabilityForNoOutliers, @@ -170,10 +171,11 @@ template<class Estimator, class S, class T> std::vector<const T *> Ransac::compute(S ¶meters, - const Estimator & paramEstimator, - const std::vector<T> &data, - double desiredProbabilityForNoOutliers, - double maximalOutlierPercentage) + std::vector<int> & inliers, + const Estimator & paramEstimator, + const std::vector<T> &data, + double desiredProbabilityForNoOutliers, + double maximalOutlierPercentage) { unsigned int numDataObjects = (int) data.size(); unsigned int numForEstimate = paramEstimator.numForEstimate(); @@ -299,8 +301,10 @@ //compute the least squares estimate using the largest sub set if(numVotesForBest > 0) { for(j=0; j<(int)numDataObjects; j++) { - if(bestVotes[j]) + if(bestVotes[j]) { leastSquaresEstimateData.push_back(&(data[j])); + inliers.push_back(j); + } } paramEstimator.leastSquaresEstimate(leastSquaresEstimateData,parameters); } diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_cpfind/cpfind/PanoDetector.h --- a/src/hugin_cpfind/cpfind/PanoDetector.h Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_cpfind/cpfind/PanoDetector.h Wed Jan 19 14:07:41 2011 +0100 @@ -196,6 +196,8 @@ void writeOutput(); void writeKeyfile(ImgData& imgInfo); + ZThread::FastMutex aPanoMutex; + // internals public: struct ImgData diff -r af3ce2680309 -r 5ee34e49ebb4 src/hugin_cpfind/cpfind/PanoDetectorLogic.cpp --- a/src/hugin_cpfind/cpfind/PanoDetectorLogic.cpp Wed Jan 19 06:55:46 2011 +0100 +++ b/src/hugin_cpfind/cpfind/PanoDetectorLogic.cpp Wed Jan 19 14:07:41 2011 +0100 @@ -42,6 +42,7 @@ #include "Tracer.h" #include <algorithms/nona/ComputeImageROI.h> +#include <algorithms/optimizer/PTOptimizer.h> #include <nona/RemappedPanoImage.h> #include <nona/ImageRemapper.h> @@ -513,7 +514,6 @@ trafo1.createTransform(iPanoDetector._panoramaInfoCopy.getSrcImage(ioImgInfo._number), ioImgInfo._projOpts); - double xout,yout; int dx1 = ioImgInfo._projOpts.getROI().left(); int dy1 = ioImgInfo._projOpts.getROI().top(); @@ -640,7 +640,7 @@ } -#if 0 +#if 1 // new code with proper fisheye aware ransac bool PanoDetector::RansacMatchesInPair(MatchData& ioMatchData, const PanoDetector& iPanoDetector) { @@ -666,16 +666,26 @@ int pano_i2 = ioMatchData._i2->_number; imgs.insert(pano_i1); imgs.insert(pano_i2); - Panorama * panoSubset = iPanoDetector._panoramaInfo->getSubset(imgs); + int pano_local_i1 = 0; + int pano_local_i2 = 1; + if (pano_i1 > pano_i2) { + pano_local_i1 = 1; + pano_local_i2 = 0; + } + + PanoramaData *panoSubset = iPanoDetector._panoramaInfo->getNewSubset(imgs); // create control point vector CPVector controlPoints(ioMatchData._matches.size()); int i=0; BOOST_FOREACH(PointMatchPtr& aM, ioMatchData._matches) - for (int i=0; i < ioMatchData._matches) { - controlPoints[i] = ControlPoint(pano_i1, aM->_img1_x, aM->_img1_y, - pano_i2, aM->_img2_x, aM->_img2_y); + { + controlPoints[i] = ControlPoint(pano_local_i1, aM->_img1_x, aM->_img1_y, + pano_local_i2, aM->_img2_x, aM->_img2_y); + i++; } + + panoSubset->setCtrlPoints(controlPoints); // perform ransac matching. // optimize positions of second image. @@ -683,30 +693,32 @@ optvars.insert("r"); optvars.insert("p"); optvars.insert("y"); - std::vector<int> inliers = RANSACOptimizer::findInliers(*panoSubset, pano_i1, pano_i2, - iPanoDetector.getRansacDistanceThreshold(), - optvars); + cout << "*****************************" << std::endl; + std::vector<int> inliers = HuginBase::RANSACOptimizer::findInliers(*panoSubset, pano_local_i1, pano_local_i2, + iPanoDetector.getRansacDistanceThreshold(), + optvars); - TRACE_PAIR("Removed " << aRemovedMatches.size() << " matches. " << ioMatchData._matches.size() << " remaining."); + cout << "*****************************" << std::endl; + cout << "Removed " << controlPoints.size() - inliers.size() << " matches. " << inliers.size() << " remaining." << endl; + TRACE_PAIR("Removed " << controlPoints.size() - inliers.size() << " matches. " << inliers.size() << " remaining."); - PointMatchVector_t aRemovedMatches; + // keep only inlier matches + PointMatchVector_t aInlierMatches; + aInlierMatches.reserve(inliers.size()); - Ransac aRansacFilter; - aRansacFilter.setIterations(iPanoDetector.getRansacIterations()); - int thresholdDistance=iPanoDetector.getRansacDistanceThreshold(); - //increase RANSAC distance if the image were remapped to not exclude - //too much points in this case - if(ioMatchData._i1->_needsremap || ioMatchData._i2->_needsremap) - thresholdDistance*=5; - aRansacFilter.setDistanceThreshold(thresholdDistance); - aRansacFilter.filter(ioMatchData._matches, aRemovedMatches); - - TRACE_PAIR("Removed " << aRemovedMatches.size() << " matches. " << ioMatchData._matches.size() << " remaining."); + BOOST_FOREACH(int idx, inliers) + { + aInlierMatches.push_back(ioMatchData._matches[idx]); + } + ioMatchData._matches = aInlierMatches; + /* if (iPanoDetector.getTest()) TestCode::drawRansacMatches(ioMatchData._i1->_name, ioMatchData._i2->_name, ioMatchData._matches, aRemovedMatches, aRansacFilter, iPanoDetector.getDownscale()); + */ + delete panoSubset; return true; } |