PTOptimizer.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00028 #include "PTOptimizer.h"
00029 
00030 #include "ImageGraph.h"
00031 #include "panodata/StandardImageVariableGroups.h"
00032 #include <panotools/PanoToolsOptimizerWrapper.h>
00033 #include <panotools/PanoToolsInterface.h>
00034 #include <algorithms/basic/CalculateCPStatistics.h>
00035 #include <algorithms/nona/CenterHorizontally.h>
00036 #include <algorithms/nona/CalculateFOV.h>
00037 #include <algorithms/basic/LayerStacks.h>
00038 #include <vigra_ext/ransac.h>
00039 
00040 #if DEBUG
00041 #include <fstream>
00042 #include <boost/graph/graphviz.hpp>
00043 #endif
00044 
00045 namespace HuginBase {
00046 
00047 using namespace hugin_utils;
00048 
00049 bool PTOptimizer::runAlgorithm()
00050 {
00051     PTools::optimize(o_panorama);
00052     return true; // let's hope so.
00053 }
00054 
00055 // small helper class
00056 class OptVarSpec
00057 {
00058 public:
00059     OptVarSpec(int img, std::string name)
00060         : m_img(img), m_name(name)
00061     {
00062     }
00063 
00064     double get(PanoramaData & pano) const
00065     {
00066         return pano.getImage(m_img).getVar(m_name);
00067     }
00068     void set(PanoramaData & pano, double x) const
00069     {
00070         pano.updateVariable(m_img,Variable(m_name,x));
00071     }
00072     int m_img;
00073     std::string m_name;
00074 };
00075 
00077 class PTOptEstimator
00078 {
00079 
00080 public:
00081 
00082     PTOptEstimator(PanoramaData & pano, int i1, int i2, double maxError,
00083                    bool optHFOV, bool optB)
00084     {
00085         m_maxError = maxError;
00086 
00087         UIntSet imgs;
00088         imgs.insert(i1);
00089         imgs.insert(i2);
00090         m_localPano = (pano.getNewSubset(imgs)); // don't forget to delete
00091         m_li1 = (i1 < i2) ? 0 : 1;
00092         m_li2 = (i1 < i2) ? 1 : 0;
00093         // get control points
00094         m_cps  = m_localPano->getCtrlPoints();
00095         // only use 2D control points
00096     for (size_t i = 0; i < m_cps.size();++i)
00097     {
00098         const ControlPoint& kp=m_cps[i];
00099         if (kp.mode == ControlPoint::X_Y)
00100         {
00101             m_xy_cps.push_back(kp);
00102         }
00103     }
00104         
00105         if (optHFOV)
00106             m_optvars.push_back(OptVarSpec(0,std::string("v")));
00107         if (optB)
00108             m_optvars.push_back(OptVarSpec(0,std::string("b")));
00109         m_optvars.push_back(OptVarSpec(m_li2,"r"));
00110         m_optvars.push_back(OptVarSpec(m_li2,"p"));
00111         m_optvars.push_back(OptVarSpec(m_li2,"y"));
00112         if (optHFOV)
00113             m_optvars.push_back(OptVarSpec(0,"v"));
00114         if (optB)
00115             m_optvars.push_back(OptVarSpec(0,"b"));
00116 
00118         m_opt_first_pass.resize(2);
00119         m_opt_first_pass[1].insert("r");
00120         m_opt_first_pass[1].insert("p");
00121         m_opt_first_pass[1].insert("y");
00122 
00124         if (optHFOV || optB) {
00125             m_opt_second_pass = m_opt_first_pass;
00126             if (optHFOV)
00127                 m_opt_second_pass[0].insert("v");
00128             if (optB)
00129                 m_opt_second_pass[0].insert("b");
00130         }
00131 
00132         // number of points required for estimation
00133         m_numForEstimate = (m_optvars.size()+1)/2;      
00134                             
00135         // extract initial parameters from pano
00136         m_initParams.resize(m_optvars.size());
00137     for (size_t i = 0; i < m_optvars.size(); ++i)
00138     {
00139         m_initParams[i] = m_optvars[i].get(*m_localPano);
00140         DEBUG_DEBUG("get init var: " << m_optvars[i].m_name << ", " << m_optvars[i].m_img << ": " << m_initParams[i]);
00141     }
00142 }
00143 
00149     bool estimate(const std::vector<const ControlPoint *> & points, std::vector<double> & p) const
00150     {
00151         // reset to the initial parameters.
00152         p.resize(m_initParams.size());
00153         std::copy(m_initParams.begin(), m_initParams.end(), p.begin());
00154 
00155         return leastSquaresEstimate(points, p);
00156     }
00157 
00158                             
00159 
00160     bool leastSquaresEstimate(const std::vector<const ControlPoint *> & points, std::vector<double> & p) const 
00161     {
00162         // copy points into panorama object
00163         CPVector cpoints(points.size());        
00164         for (int i=0; i < points.size(); i++) {
00165             cpoints[i] = *points[i];
00166         }
00167 
00168         m_localPano->setCtrlPoints(cpoints);
00169 
00170         PanoramaData * pano = const_cast<PanoramaData *>(m_localPano);
00171         // set parameters in pano object
00172     for (size_t i = 0; i < m_optvars.size(); ++i)
00173     {
00174         m_optvars[i].set(*pano, p[i]);
00175         DEBUG_DEBUG("Initial " << m_optvars[i].m_name << ": i1:" << pano->getImage(m_li1).getVar(m_optvars[i].m_name) << ", i2: " << pano->getImage(m_li2).getVar(m_optvars[i].m_name));
00176     }
00177 
00178         m_localPano->setOptimizeVector(m_opt_first_pass);
00179         // optimize parameters using panotools (or use a custom made optimizer here?)
00180         UIntSet imgs;
00181         imgs.insert(0);
00182         imgs.insert(1);
00183         //std::cout << "Optimizing without hfov:" << std::endl;
00184         //pano->printPanoramaScript(std::cerr, m_localPano->getOptimizeVector(), pano->getOptions(), imgs, true );
00185         PTools::optimize(*pano);
00186         //std::cout << "result:" << std::endl;
00187         //pano->printPanoramaScript(std::cerr, m_localPano->getOptimizeVector(), pano->getOptions(), imgs, true );
00188 
00189         if (m_opt_second_pass.size() > 0) {
00190             m_localPano->setOptimizeVector(m_opt_second_pass);
00191             //std::cout << "Optimizing with hfov" << std::endl;
00192             //pano->printPanoramaScript(std::cerr, m_localPano->getOptimizeVector(), pano->getOptions(), imgs, true );
00193             PTools::optimize(*pano);
00194             //std::cout << "result:" << std::endl;
00195             //pano->printPanoramaScript(std::cerr, m_localPano->getOptimizeVector(), pano->getOptions(), imgs, true );
00196         }
00197 
00198         // get optimized parameters
00199     for (size_t i = 0; i < m_optvars.size(); ++i)
00200     {
00201         p[i] = m_optvars[i].get(*pano);
00202         DEBUG_DEBUG("Optimized " << m_optvars[i].m_name << ": i1:" << pano->getImage(m_li1).getVar(m_optvars[i].m_name) << ", i2: " << pano->getImage(m_li2).getVar(m_optvars[i].m_name));
00203     }
00204         return true;
00205     }
00206 
00207 
00208     bool agree(std::vector<double> &p, const ControlPoint & cp) const
00209     {
00210         PanoramaData * pano = const_cast<PanoramaData *>(m_localPano);
00211         // set parameters in pano object
00212     for (size_t i = 0; i < m_optvars.size(); ++i)
00213     {
00214         m_optvars[i].set(*pano, p[i]);
00215     }
00216         // TODO: argh, this is slow, we should really construct this only once
00217         // and reuse it for all calls...
00218         PTools::Transform trafo_i1_to_pano;
00219         trafo_i1_to_pano.createInvTransform(m_localPano->getImage(m_li1),m_localPano->getOptions());
00220         PTools::Transform trafo_pano_to_i2;
00221         trafo_pano_to_i2.createTransform(m_localPano->getImage(m_li2),m_localPano->getOptions());
00222 
00223         double x1,y1,x2,y2,xt,yt,x2t,y2t;
00224         if (cp.image1Nr == m_li1) {
00225             x1 = cp.x1;
00226             y1 = cp.y1;
00227             x2 = cp.x2;
00228             y2 = cp.y2;
00229         } else {
00230             x1 = cp.x2;
00231             y1 = cp.y2;
00232             x2 = cp.x1;
00233             y2 = cp.y1;
00234         }   
00235         trafo_i1_to_pano.transformImgCoord(xt, yt, x1, y1);
00236         trafo_pano_to_i2.transformImgCoord(x2t, y2t, xt, yt);
00237         DEBUG_DEBUG("Trafo i1 (0 " << x1 << " " << y1 << ") -> ("<< xt <<" "<< yt<<") -> i2 (1 "<<x2t<<", "<<y2t<<"), real ("<<x2<<", "<<y2<<")")
00238         // compute error in pixels...
00239         x2t -= x2;
00240         y2t -= y2;
00241         double  e = hypot(x2t,y2t);
00242         DEBUG_DEBUG("Error ("<<x2t<<", "<<y2t<<"), " << e)
00243         return  e < m_maxError;
00244     }
00245 
00246     ~PTOptEstimator()
00247     {
00248         delete m_localPano;
00249     }
00250 
00251     int numForEstimate() const
00252     {
00253         return m_numForEstimate;
00254     }
00255         
00256 public:
00257     CPVector m_xy_cps;
00258     std::vector<double> m_initParams;
00259     std::vector<OptVarSpec> m_optvars;
00260 
00261 private:
00262     int m_li1, m_li2;
00263     double m_maxError;
00264     PanoramaData * m_localPano;
00265     CPVector m_cps;    
00266     std::vector<std::set<std::string> > m_opt_first_pass;
00267     std::vector<std::set<std::string> > m_opt_second_pass;
00268     int m_numForEstimate;
00269 };
00270 
00271 
00272 std::vector<int> RANSACOptimizer::findInliers(PanoramaData & pano, int i1, int i2, double maxError, Mode rmode)
00273 {
00274     bool optHFOV = false;
00275     bool optB = false;
00276     switch (rmode) {
00277     case HOMOGRAPHY:
00278     case RPYV:
00279         optHFOV =  true;
00280         break;
00281     case RPYVB:
00282         optHFOV = true;
00283         optB = true;
00284     case AUTO:
00285     case RPY:
00286         break;
00287     }
00288 
00289     DEBUG_DEBUG("Optimizing HFOV:" << optHFOV << " b:" << optB)
00290     PTOptEstimator estimator(pano, i1, i2, maxError, optHFOV, optB);
00291 
00292     std::vector<double> parameters(estimator.m_initParams.size());
00293     std::copy(estimator.m_initParams.begin(),estimator.m_initParams.end(), parameters.begin());
00294     std::vector<int> inlier_idx;
00295     DEBUG_DEBUG("Number of control points: " << estimator.m_xy_cps.size() << " Initial parameter[0]" << parameters[0]);
00296     std::vector<const ControlPoint *> inliers = Ransac::compute(parameters, inlier_idx, estimator, estimator.m_xy_cps, 0.999, 0.3);
00297     DEBUG_DEBUG("Number of inliers:" << inliers.size() << "optimized parameter[0]" << parameters[0]);
00298 
00299     // set parameters in pano object
00300     for (size_t i = 0; i < estimator.m_optvars.size(); ++i)
00301     {
00302         // TODO: check when to use i1..
00303         pano.updateVariable(i2, Variable(estimator.m_optvars[i].m_name, parameters[i]));
00304     }
00305     
00306     
00307     // TODO: remove bad control points from pano
00308     return inlier_idx;
00309 }    
00310     
00311 
00312 bool RANSACOptimizer::runAlgorithm()
00313 {
00314     o_inliers = findInliers(o_panorama, o_i1, o_i2, o_maxError, o_mode);
00315     return true; // let's hope so.
00316 }
00317     
00318 
00319 int FindStackNumberForImage(const std::vector<UIntSet>& imageGroups, const unsigned int imgNr)
00320 {
00321     for (size_t i = 0; i < imageGroups.size(); ++i)
00322     {
00323         if (set_contains(imageGroups[i], imgNr))
00324         {
00325             return i;
00326         };
00327     };
00328     return -1;
00329 };
00330 
00331 void AutoOptimise::autoOptimise(PanoramaData& pano, bool optRoll)
00332 {
00333     CPVector cps = pano.getCtrlPoints();
00334     CPVector newCP;
00335 
00336     // remove all connected images, keep only a single image for each connected stack
00337     std::vector<UIntSet> imageGroups;
00338     UIntSet visitedImages;
00339     PanoramaData* optPano;
00340     for (size_t i = 0; i < pano.getNrOfImages(); ++i)
00341     {
00342         if (set_contains(visitedImages, i))
00343         {
00344             continue;
00345         };
00346         const SrcPanoImage& img1 = pano.getImage(i);
00347         UIntSet imgs;
00348         imgs.insert(i);
00349         visitedImages.insert(i);
00350         if (img1.YawisLinked() && i + 1 < pano.getNrOfImages())
00351         {
00352             for (size_t j = i + 1; j < pano.getNrOfImages(); ++j)
00353             {
00354                 if (img1.YawisLinkedWith(pano.getImage(j)))
00355                 {
00356                     imgs.insert(j);
00357                     visitedImages.insert(j);
00358                 }
00359             }
00360         };
00361         imageGroups.push_back(imgs);
00362     };
00363     UIntSet singleStackImgs;
00364     for (size_t i = 0; i < imageGroups.size(); ++i)
00365     {
00366         singleStackImgs.insert(*imageGroups[i].begin());
00367     };
00368     // new generate subpano
00369     optPano = pano.getNewSubset(singleStackImgs);
00370     // translate now reference image
00371     int newRefImage = FindStackNumberForImage(imageGroups, pano.getOptions().optimizeReferenceImage);
00372     if (newRefImage != -1)
00373     {
00374         PanoramaOptions opts = optPano->getOptions();
00375         opts.optimizeReferenceImage = newRefImage;
00376         optPano->setOptions(opts);
00377     };
00378     // remove all vertical and horizontal cp, also remap all cps to new subpano
00379     // all cps from removed images will be mapped to first image of corresponding stack
00380     for (CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
00381     {
00382         if (it->mode == ControlPoint::X_Y)
00383         {
00384             ControlPoint cp (*it);
00385             int newImg1 = FindStackNumberForImage(imageGroups, cp.image1Nr);
00386             int newImg2 = FindStackNumberForImage(imageGroups, cp.image2Nr);
00387             if (newImg1 != -1 && newImg2 != -1 && newImg1 != newImg2)
00388             {
00389                 cp.image1Nr = newImg1;
00390                 cp.image2Nr = newImg2;
00391                 newCP.push_back(cp);
00392             };
00393         };
00394     };
00395     optPano->setCtrlPoints(newCP);
00396 
00397     // DGSW FIXME - Unreferenced
00398     //  unsigned nImg = unsigned(pano.getNrOfImages());
00399     // build a graph over all overlapping images
00400     CPGraph graph;
00401     createCPGraph(*optPano,graph);
00402     
00403 #if DEBUG
00404     {
00405         std::ofstream gfile("cp_graph.dot");
00406         // output doxygen graph
00407         boost::write_graphviz(gfile, graph);
00408     }
00409 #endif
00410     std::set<std::string> optvars;
00411     if(optRoll)
00412     {
00413         optvars.insert("r");
00414     };
00415     optvars.insert("p");
00416     optvars.insert("y");
00417     
00418     unsigned int startImg = optPano->getOptions().optimizeReferenceImage;
00419     
00420     // start a breadth first traversal of the graph, and optimize
00421     // the links found (every vertex just once.)
00422     
00423     OptimiseVisitor optVisitor(*optPano, optvars);
00424     
00425     boost::queue<boost::graph_traits<CPGraph>::vertex_descriptor> qu;
00426     boost::breadth_first_search(graph, startImg,
00427                                 color_map(get(boost::vertex_color, graph)).
00428                                 visitor(optVisitor));
00429 
00430     // now translate to found positions to initial pano
00431     for (size_t i = 0; i < optPano->getNrOfImages(); ++i)
00432     {
00433         pano.updateVariables(*imageGroups[i].begin(), optPano->getImageVariables(i));
00434     };
00435     delete optPano;
00436     /*
00437 #ifdef DEBUG
00438      // print optimized script to cout
00439      DEBUG_DEBUG("after local optim:");
00440      VariableMapVector vars = optVisitor.getVariables();
00441      for (unsigned v=0; v < pano.getNrOfImages(); v++) {
00442          printVariableMap(std::cerr, vars[v]);
00443          std::cerr << std::endl;
00444      }
00445 #endif
00446      
00447      // apply variables to input panorama
00448      pano.updateVariables(optVisitor.getVariables());
00449      
00450 #ifdef DEBUG
00451      UIntSet allImg;
00452      fill_set(allImg,0, pano.getNrOfImages()-1);
00453      // print optimized script to cout
00454      DEBUG_DEBUG("after updateVariables():");
00455      pano.printPanoramaScript(std::cerr, pano.getOptimizeVector(), pano.getOptions(), allImg, false);
00456 #endif
00457      */
00458 }
00459 
00460 
00461 void SmartOptimise::smartOptimize(PanoramaData& optPano)
00462 {
00463     // use m-estimator with sigma 2
00464     PanoramaOptions opts = optPano.getOptions();
00465     double oldSigma = opts.huberSigma;
00466     opts.huberSigma = 2;
00467     optPano.setOptions(opts);
00468     
00469     // remove vertical and horizontal control points
00470     CPVector cps = optPano.getCtrlPoints();
00471     CPVector newCP;
00472     for (CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it) {
00473         if (it->mode == ControlPoint::X_Y)
00474         {
00475             newCP.push_back(*it);
00476         }
00477     }
00478     optPano.setCtrlPoints(newCP);
00479     AutoOptimise::autoOptimise(optPano);
00480     
00481     // do global optimisation of position with all control points.
00482     optPano.setCtrlPoints(cps);
00483     OptimizeVector optvars = createOptVars(optPano, OPT_POS, optPano.getOptions().optimizeReferenceImage);
00484     optPano.setOptimizeVector(optvars);
00485     PTools::optimize(optPano);
00486     
00487     //Find lenses.
00488     StandardImageVariableGroups variable_groups(optPano);
00489     
00490     // allow parameter evaluation.
00491     // this could be probably done in better way because this
00492     // will optimize them also in case they are intentionally set to 0
00493     double origLensPar[5];
00494     origLensPar[0] = const_map_get(optPano.getImageVariables(0),"a").getValue();
00495     origLensPar[1] = const_map_get(optPano.getImageVariables(0),"b").getValue();
00496     origLensPar[2] = const_map_get(optPano.getImageVariables(0),"c").getValue();
00497     origLensPar[3] = const_map_get(optPano.getImageVariables(0),"d").getValue();
00498     origLensPar[4] = const_map_get(optPano.getImageVariables(0),"e").getValue();
00499     bool alreadyCalibrated = false;
00500     for (int i = 0; i < 5; i++) {
00501         if (origLensPar[i] != 0) {
00502                 alreadyCalibrated = true;
00503                 break;
00504         }
00505     }
00506     bool singleStack=false;
00507     if(!alreadyCalibrated) {
00508         UIntSet images;
00509         fill_set(images, 0, optPano.getNrOfImages()-1);
00510         std::vector<UIntSet> stacks = getHDRStacks(optPano, images, optPano.getOptions());
00511         singleStack = (stacks.size() == 1);
00512     };
00513     // check if lens parameter values were loaded from ini file
00514     // and should not be changed
00515     // also don't optimize lens parameters for single stack projects
00516     if (!alreadyCalibrated && !singleStack) {
00517         //---------------------------------------------------------------
00518         // Now with lens distortion
00519         
00520         // force inherit for all d/e values
00521         for (unsigned i=0; i< variable_groups.getLenses().getNumberOfParts(); i++)
00522         {
00523             variable_groups.getLenses().linkVariablePart(ImageVariableGroup::IVE_RadialDistortion, i);
00524             variable_groups.getLenses().linkVariablePart(ImageVariableGroup::IVE_RadialDistortionCenterShift, i);
00525         }
00526         
00527         int optmode = OPT_POS;
00528         double origHFOV = const_map_get(optPano.getImageVariables(0),"v").getValue();
00529         
00530         // determine which parameters to optimize
00531         double rmin, rmax, rmean, rvar, rq10, rq90;
00532         CalculateCPStatisticsRadial::calcCtrlPntsRadiStats(optPano, rmin, rmax, rmean, rvar, rq10, rq90);
00533         
00534         DEBUG_DEBUG("Ctrl Point radi statistics: min:" << rmin << " max:" << rmax << " mean:" << rmean << " var:" << rvar << " q10:" << rq10 << " q90:" << rq90);
00535         
00536         if (origHFOV > 60) {
00537             // only optimize principal point if the hfov is high enough for sufficient perspective effects
00538             optmode |= OPT_DE;
00539         }
00540         
00541         // heuristics for distortion and fov optimisation
00542         if ( (rq90 - rq10) >= 1.2) {
00543             // very well distributed control points 
00544             // TODO: other criterion when to optimize HFOV, too
00545             optmode |= OPT_AC | OPT_B;
00546         } else if ( (rq90 - rq10) > 1.0) {
00547             optmode |= OPT_AC | OPT_B;
00548         } else {
00549             optmode |= OPT_B;
00550         }
00551         
00552         // check if this is a 360 deg pano.
00553         CenterHorizontally(optPano).run();
00554         //FDiff2D fov = CalculateFOV(optPano).run<CalculateFOV>().getResultFOV();
00555             FDiff2D fov = CalculateFOV::calcFOV(optPano);
00556         
00557         if (fov.x >= 150) {
00558             // optimize HFOV for 150 deg panos
00559             optmode |= OPT_HFOV;
00560         }
00561         
00562         DEBUG_DEBUG("second optimization: " << optmode);
00563 
00564         // save old variables, might be needed if optimization went wrong
00565         VariableMapVector oldVars = optPano.getVariables();
00566         DEBUG_DEBUG("oldVars[0].b: " << const_map_get(oldVars[0],"b").getValue());
00567         optvars = createOptVars(optPano, optmode, optPano.getOptions().optimizeReferenceImage);
00568         optPano.setOptimizeVector(optvars);
00569         // global optimisation.
00570         DEBUG_DEBUG("before opt 1: newVars[0].b: " << const_map_get(optPano.getVariables()[0],"b").getValue());
00571         PTools::optimize(optPano);
00572         // --------------------------------------------------------------
00573         // do some plausibility checks and reoptimize with less variables
00574         // if something smells fishy
00575         bool smallHFOV = false;
00576         bool highDist = false;
00577         bool highShift = false;
00578         const VariableMapVector & vars = optPano.getVariables();
00579         DEBUG_DEBUG("after opt 1: newVars[0].b: " << const_map_get(vars[0],"b").getValue());
00580         DEBUG_DEBUG("after opt 1: oldVars[0].b: " << const_map_get(oldVars[0],"b").getValue());
00581         for (VariableMapVector::const_iterator it = vars.begin() ; it != vars.end(); ++it)
00582         {
00583             if (const_map_get(*it,"v").getValue() < 1.0) smallHFOV = true;
00584             if (fabs(const_map_get(*it,"a").getValue()) > 0.2) highDist = true;
00585             if (fabs(const_map_get(*it,"b").getValue()) > 0.2) highDist = true;
00586             if (fabs(const_map_get(*it,"c").getValue()) > 0.2) highDist = true;
00587             if (fabs(const_map_get(*it,"d").getValue()) > 1000) highShift = true;
00588             if (fabs(const_map_get(*it,"e").getValue()) > 1000) highShift = true;
00589         }
00590 
00591         if (smallHFOV || highDist || highShift) {
00592             DEBUG_DEBUG("Optimization with strange result. status: HFOV: " << smallHFOV << " dist:" << highDist << " shift:" << highShift);
00593             // something seems to be wrong
00594             if (smallHFOV) {
00595                 // do not optimize HFOV
00596                 optmode &= ~OPT_HFOV;
00597             }
00598             if (highDist) {
00599                 optmode &= ~OPT_AC;
00600             }
00601             if (highShift) {
00602                 optmode &= ~OPT_DE;
00603             }
00604             
00605             // revert and redo optimisation
00606             DEBUG_DEBUG("oldVars[0].b: " << const_map_get(oldVars[0],"b").getValue());
00607             optPano.updateVariables(oldVars);
00608             DEBUG_DEBUG("before opt 2: newVars[0].b: " << const_map_get(optPano.getVariables()[0],"b").getValue());
00609             optvars = createOptVars(optPano, optmode, optPano.getOptions().optimizeReferenceImage);
00610             optPano.setOptimizeVector(optvars);
00611             DEBUG_DEBUG("recover optimisation: " << optmode);
00612             // global optimisation.
00613             PTools::optimize(optPano);
00614     
00615             // check again, maybe b shouldn't be optimized either
00616             bool highDist = false;
00617             const VariableMapVector & vars = optPano.getVariables();
00618             DEBUG_DEBUG("after opt 2: newVars[0].b: " << const_map_get(vars[0],"b").getValue());
00619             DEBUG_DEBUG("after opt 2: oldVars[0].b: " << const_map_get(oldVars[0],"b").getValue());
00620             for (VariableMapVector::const_iterator it = vars.begin() ; it != vars.end(); ++it)
00621             {
00622                 if (fabs(const_map_get(*it,"b").getValue()) > 0.2) highDist = true;
00623             }
00624             if (highDist) {
00625                 optmode &= ~OPT_B;
00626                 DEBUG_DEBUG("recover optimisation (2): " << optmode);
00627                 // revert and redo optimisation
00628                 optPano.updateVariables(oldVars);
00629                 DEBUG_DEBUG("before opt 3: newVars[0].b: " << const_map_get(optPano.getVariables()[0],"b").getValue());
00630                 optvars = createOptVars(optPano, optmode, optPano.getOptions().optimizeReferenceImage);
00631                 optPano.setOptimizeVector(optvars);
00632                 // global optimisation.
00633                 PTools::optimize(optPano);
00634                 const VariableMapVector & vars = optPano.getVariables();
00635                 DEBUG_DEBUG("after opt 3: newVars[0].b: " << const_map_get(vars[0],"b").getValue());
00636                 DEBUG_DEBUG("after opt 3: oldVars[0].b: " << const_map_get(oldVars[0],"b").getValue());
00637 
00638             }
00639         }
00640     }
00641     opts.huberSigma = oldSigma;
00642     optPano.setOptions(opts);
00643 }
00644 
00645 OptimizeVector SmartOptimizerStub::createOptVars(const PanoramaData& optPano, int mode, unsigned anchorImg)
00646 {
00647     OptimizeVector optvars;
00648     const SrcPanoImage & anchorImage = optPano.getImage(anchorImg);
00649     for (unsigned i=0; i < optPano.getNrOfImages(); i++) {
00650         std::set<std::string> imgopt;
00651         // do not optimize anchor image's stack for position.
00652         const SrcPanoImage & iImage = optPano.getImage(i);
00653         if (!iImage.RollisLinkedWith(anchorImage) &&
00654             !iImage.PitchisLinkedWith(anchorImage) &&
00655             !iImage.YawisLinkedWith(anchorImage))
00656         {
00657             if (mode & OPT_POS) {
00658                 imgopt.insert("r");
00659                 imgopt.insert("p");
00660                 imgopt.insert("y");
00661             }
00662         }
00663         //we need to optimize roll and pitch to level the pano
00664         //possible after introduction of line finder
00665         if((i==anchorImg) && (mode & OPT_POS))
00666         {
00667             imgopt.insert("r");
00668             imgopt.insert("p");
00669         };
00670         // do not optimise anchor image for exposure.
00671         if (i!=anchorImg)
00672         {
00673             if (mode & OPT_EXP) {
00674                 imgopt.insert("Eev");
00675             }
00676             if (mode & OPT_WB) {
00677                 imgopt.insert("Er");
00678                 imgopt.insert("Eb");
00679             }
00680         }
00681         if (mode & OPT_HFOV) {
00682             imgopt.insert("v");
00683         }
00684         if (mode & OPT_B)
00685             imgopt.insert("b");
00686         if (mode & OPT_AC) {
00687             imgopt.insert("a");
00688             imgopt.insert("c");
00689         }
00690         if (mode & OPT_DE) {
00691             imgopt.insert("d");
00692             imgopt.insert("e");
00693         }
00694         if (mode & OPT_GT) {
00695             imgopt.insert("g");
00696             imgopt.insert("t");
00697         }
00698         if (mode & OPT_VIG) {
00699             imgopt.insert("Vb");
00700             imgopt.insert("Vc");
00701             imgopt.insert("Vd");
00702         }
00703         if (mode & OPT_VIGCENTRE) {
00704             imgopt.insert("Vx");
00705             imgopt.insert("Vy");
00706         }
00707         if (mode & OPT_RESP) {
00708             imgopt.insert("Ra");
00709             imgopt.insert("Rb");
00710             imgopt.insert("Rc");
00711             imgopt.insert("Rd");
00712             imgopt.insert("Re");
00713         }
00714         optvars.push_back(imgopt);
00715     }
00716     
00717     return optvars;
00718 }
00719 
00720 } //namespace

Generated on 27 Aug 2015 for Hugintrunk by  doxygen 1.4.7