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

Generated on 5 Dec 2016 for Hugintrunk by  doxygen 1.4.7