PTOptimizer.cpp

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

Generated on 22 Oct 2014 for Hugintrunk by  doxygen 1.4.7