pto_var.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00011 /*  This program is free software; you can redistribute it and/or
00012  *  modify it under the terms of the GNU General Public
00013  *  License as published by the Free Software Foundation; either
00014  *  version 2 of the License, or (at your option) any later version.
00015  *
00016  *  This software is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  *  General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public
00022  *  License along with this software. If not, see
00023  *  <http://www.gnu.org/licenses/>.
00024  *
00025  */
00026 
00027 #include <fstream>
00028 #include <sstream>
00029 #include <getopt.h>
00030 #include <panodata/Panorama.h>
00031 #include <panodata/ImageVariableTranslate.h>
00032 #include <panodata/ImageVariableGroup.h>
00033 #include <panodata/StandardImageVariableGroups.h>
00034 #include "hugin_utils/utils.h"
00035 #include "panodata/ParseExp.h"
00036 
00037 // parse a single variable and put result in struct ParseVar
00038 void ParseSingleOptVar(Parser::ParseVarVec& varVec, const std::string& s, std::ostream& errorStream)
00039 {
00040     // parse following regex ([!]?)([a-zA-Z]{1,3})(\\d*?) 
00041     std::string tempString(s);
00042     Parser::ParseVar var;
00043     var.flag = (tempString[0] == '!');
00044     if (var.flag)
00045     {
00046         tempString.erase(0, 1);
00047     };
00048     if (Parser::ParseVarNumber(tempString, var))
00049     {
00050         varVec.push_back(var);
00051     }
00052     else
00053     {
00054         errorStream << "The expression \"" << tempString << "\" is not a valid image variable." << std::endl;
00055     };
00056 };
00057 
00058 void ParseSingleLinkVar(Parser::ParseVarVec& varVec, const std::string& s, std::ostream& errorStream)
00059 {
00060     // parse following regex ([a-zA-Z]{1,3})(\\d+?)
00061     Parser::ParseVar var;
00062     if (Parser::ParseVarNumber(s, var))
00063     {
00064         if (var.imgNr >= 0)
00065         {
00066             varVec.push_back(var);
00067         }
00068         else
00069         {
00070             errorStream << "The expression \"" << s << "\" does not contain a valid image number." << std::endl;
00071         }
00072     }
00073     else
00074     {
00075         errorStream << "The expression \"" << s << "\" is not a valid image variable." << std::endl;
00076     };
00077 };
00078 
00079 // adds given varname to optVec
00080 // does some additional checking:
00081 //   1. don't add y,p,r for anchor image
00082 //   2. handle vignetting and EMoR parameters as group
00083 void AddToOptVec(HuginBase::OptimizeVector& optVec, std::string varname, size_t imgNr,
00084                  std::set<size_t> refImgs, bool linkRefImgsYaw, bool linkRefImgsPitch, bool linkRefImgsRoll, std::vector<std::set<std::string> > groupedVars)
00085 {
00086     if(varname=="y")
00087     {
00088         if(!set_contains(refImgs, imgNr) || linkRefImgsYaw)
00089         {
00090             optVec[imgNr].insert(varname);
00091         };
00092     }
00093     else
00094     {
00095         if(varname=="p")
00096         {
00097             if(!set_contains(refImgs, imgNr) || linkRefImgsPitch)
00098             {
00099                 optVec[imgNr].insert(varname);
00100             };
00101         }
00102         else
00103         {
00104             if(varname=="r")
00105             {
00106                 if(!set_contains(refImgs, imgNr) || linkRefImgsRoll)
00107                 {
00108                     optVec[imgNr].insert(varname);
00109                 };
00110             }
00111             else
00112             {
00113                 if(varname=="TrX" || varname=="TrY" || varname=="TrZ" || varname=="Tpy" || varname=="Tpp")
00114                 {
00115                     if(!set_contains(refImgs, imgNr))
00116                     {
00117                         optVec[imgNr].insert(varname);
00118                     };
00119                 }
00120                 else
00121                 {
00122                     for(size_t i=0; i<groupedVars.size(); i++)
00123                     {
00124                         if(set_contains(groupedVars[i], varname))
00125                         {
00126                             for(std::set<std::string>::const_iterator it=groupedVars[i].begin(); it!=groupedVars[i].end(); ++it)
00127                             {
00128                                 optVec[imgNr].insert(*it);
00129                             };
00130                             return;
00131                         };
00132                     };
00133                     optVec[imgNr].insert(varname);
00134                 };
00135             };
00136         };
00137     };
00138 };
00139 
00140 // remove given variable from optvec, handle also correct grouped variables
00141 void RemoveFromOptVec(HuginBase::OptimizeVector& optVec, std::string varname, size_t imgNr, std::vector<std::set<std::string> > groupedVars)
00142 {
00143     for(size_t i=0; i<groupedVars.size(); i++)
00144     {
00145         if(set_contains(groupedVars[i], varname))
00146         {
00147             for(std::set<std::string>::const_iterator it=groupedVars[i].begin(); it!=groupedVars[i].end(); ++it)
00148             {
00149                 optVec[imgNr].erase(*it);
00150             };
00151             return;
00152         };
00153     };
00154     optVec[imgNr].erase(varname);
00155 };
00156 
00157 // link or unlink the parsed image variables
00158 void UnLinkVars(HuginBase::Panorama& pano, Parser::ParseVarVec parseVec, bool link)
00159 {
00160     for(size_t i=0; i<parseVec.size(); i++)
00161     {
00162         //skip invalid image numbers
00163         if(parseVec[i].imgNr<0 || parseVec[i].imgNr>=(int)pano.getNrOfImages())
00164         {
00165             continue;
00166         };
00167 
00168         //convert to ImageVariableGroup::IVE_name format
00169         std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
00170 #define image_variable( name, type, default_value ) \
00171     if (HuginBase::PTOVariableConverterFor##name::checkApplicability(parseVec[i].varname))\
00172     {\
00173         variables.insert(HuginBase::ImageVariableGroup::IVE_##name);\
00174     };
00175 #include "panodata/image_variables.h"
00176 #undef image_variable
00177 
00178         if(!variables.empty())
00179         {
00180             //lens variable
00181             if(set_contains(HuginBase::StandardImageVariableGroups::getLensVariables(), *variables.begin()))
00182             {
00183                 HuginBase::ImageVariableGroup group(HuginBase::StandardImageVariableGroups::getLensVariables(), pano);
00184                 if (link)
00185                 {
00186                     std::cout << "Linking";
00187                     group.linkVariableImage(*variables.begin(), parseVec[i].imgNr);
00188                 }
00189                 else
00190                 {
00191                     std::cout << "Unlinking";
00192                     group.unlinkVariableImage(*variables.begin(), parseVec[i].imgNr);
00193                     group.updatePartNumbers();
00194                 }
00195                 std::cout << " image variable " << parseVec[i].varname << " for image " << parseVec[i].imgNr << std::endl;
00196             }
00197             else
00198             {
00199                 //stack variables
00200                 // handle yaw, pitch, roll, TrX, TrY and TrZ always together
00201                 if(set_contains(HuginBase::StandardImageVariableGroups::getStackVariables(), *variables.begin()))
00202                 {
00203                     HuginBase::ImageVariableGroup group(HuginBase::StandardImageVariableGroups::getStackVariables(), pano);
00204                     if (link)
00205                     {
00206                         std::cout << "Linking";
00207                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Yaw, parseVec[i].imgNr);
00208                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Pitch, parseVec[i].imgNr);
00209                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Roll, parseVec[i].imgNr);
00210                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_X, parseVec[i].imgNr);
00211                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Y, parseVec[i].imgNr);
00212                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Z, parseVec[i].imgNr);
00213                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw, parseVec[i].imgNr);
00214                         group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch, parseVec[i].imgNr);
00215                     }
00216                     else
00217                     {
00218                         std::cout << "Unlinking";
00219                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Yaw, parseVec[i].imgNr);
00220                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Pitch, parseVec[i].imgNr);
00221                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Roll, parseVec[i].imgNr);
00222                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_X, parseVec[i].imgNr);
00223                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Y, parseVec[i].imgNr);
00224                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Z, parseVec[i].imgNr);
00225                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw, parseVec[i].imgNr);
00226                         group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch, parseVec[i].imgNr);
00227                         group.updatePartNumbers();
00228                     }
00229                     std::cout << " image position (ypr, TrXYZ, Tpyp) for image " << parseVec[i].imgNr << std::endl;
00230                 }
00231                 else
00232                 {
00233                     std::cerr << "Warning: " << parseVec[i].varname << " is not a valid linkable variable." << std::endl;
00234                 };
00235             };
00236         };
00237     };
00238 };
00239 
00240 static void usage(const char* name)
00241 {
00242     std::cout << name << ": change image variables inside pto files" << std::endl
00243          << name << " version " << hugin_utils::GetHuginVersion() << std::endl
00244          << std::endl
00245          << "Usage:  " << name << " [options] --opt|--link|--unlink|--set varlist input.pto" << std::endl
00246          << std::endl
00247          << "     -o, --output=file.pto  Output Hugin PTO file. Default: <filename>_var.pto" << std::endl
00248          << "     -h, --help             Shows this help" << std::endl
00249          << std::endl
00250          << "     --opt varlist          Change optimizer variables" << std::endl
00251          << "     --modify-opt           Modify the existing optimizer variables" << std::endl
00252          << "                            (without pto_var will start with an" << std::endl
00253          << "                             empty variables set)" << std::endl
00254          << "                            Examples:" << std::endl
00255          << "           --opt=y,p,r        Optimize yaw, pitch and roll of all images" << std::endl
00256          << "                              (special treatment for anchor image applies)" << std::endl
00257          << "           --opt=v0,b2        Optimize hfov of image 0 and barrel distortion" << std::endl
00258          << "                              of image 2" << std::endl
00259          << "           --opt=v,!v0        Optimize field of view for all images except" << std::endl
00260          << "                              for the first image" << std::endl
00261          << "           --opt=!a,!b,!c     Don't optimise distortion (works only with" << std::endl
00262          << "                              switch --modify-opt together)" << std::endl
00263          << std::endl
00264          << "     --link varlist         Link given variables" << std::endl
00265          << "                            Example:" << std::endl
00266          << "           --link=v3          Link hfov of image 3" << std::endl
00267          << "           --link=a1,b1,c1    Link distortions parameter for image 1" << std::endl
00268          << std::endl
00269          << "     --unlink varlist       Unlink given variables" << std::endl
00270          << "                            Examples:" << std::endl
00271          << "           --unlink=v5        Unlink hfov for image 5" << std::endl
00272          << "           --unlink=a2,b2,c2  Unlink distortions parameters for image 2" << std::endl
00273          << std::endl
00274          << "     --set varlist          Sets variables to new values" << std::endl
00275          << "                            Examples:" << std::endl
00276          << "           --set=y0=0,r0=0,p0=0  Resets position of image 0" << std::endl
00277          << "           --set=Vx4=-10,Vy4=10  Sets vignetting offset for image 4" << std::endl
00278          << "           --set=v=20            Sets the field of view to 20 for all images" << std::endl
00279          << "           --set=y=val+20        Increase yaw by 20 deg for all images" << std::endl
00280          << "           --set=v=val*1.1       Increase fov by 10 % for all images" << std::endl
00281          << "           --set=y=i*20          Set yaw to 0, 20, 40, ..." << std::endl
00282          << "     --set-from-file filename  Sets variables to new values" << std::endl
00283          << "                               It reads the varlist from a file" << std::endl
00284          << std::endl;
00285 }
00286 
00287 int main(int argc, char* argv[])
00288 {
00289     // parse arguments
00290     const char* optstring = "o:h";
00291 
00292     enum
00293     {
00294         SWITCH_OPT=1000,
00295         SWITCH_LINK,
00296         SWITCH_UNLINK,
00297         SWITCH_SET,
00298         SWITCH_SET_FILE,
00299         OPT_MODIFY_OPTVEC
00300     };
00301     static struct option longOptions[] =
00302     {
00303         {"output", required_argument, NULL, 'o' },
00304         {"opt", required_argument, NULL, SWITCH_OPT },
00305         {"link", required_argument, NULL, SWITCH_LINK },
00306         {"unlink", required_argument, NULL, SWITCH_UNLINK },
00307         {"set", required_argument, NULL, SWITCH_SET },
00308         {"set-from-file", required_argument, NULL, SWITCH_SET_FILE },
00309         {"modify-opt", no_argument, NULL, OPT_MODIFY_OPTVEC },
00310         {"help", no_argument, NULL, 'h' },
00311         0
00312     };
00313 
00314     Parser::ParseVarVec optVars;
00315     Parser::ParseVarVec linkVars;
00316     Parser::ParseVarVec unlinkVars;
00317     std::string setVars;
00318     bool modifyOptVec=false;
00319     int c;
00320     std::string output;
00321     while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
00322     {
00323         switch (c)
00324         {
00325             case 'o':
00326                 output = optarg;
00327                 break;
00328             case 'h':
00329                 usage(hugin_utils::stripPath(argv[0]).c_str());
00330                 return 0;
00331             case SWITCH_OPT:
00332                 Parser::ParseVariableString(optVars, std::string(optarg), std::cerr, ParseSingleOptVar);
00333                 break;
00334             case SWITCH_LINK:
00335                 Parser::ParseVariableString(linkVars, std::string(optarg), std::cerr, ParseSingleLinkVar);
00336                 break;
00337             case SWITCH_UNLINK:
00338                 Parser::ParseVariableString(unlinkVars, std::string(optarg), std::cerr, ParseSingleLinkVar);
00339                 break;
00340             case SWITCH_SET:
00341                 setVars = std::string(optarg);
00342                 break;
00343             case SWITCH_SET_FILE:
00344                 {
00345                     std::ifstream ifs(optarg);
00346                     if(ifs.is_open())
00347                     {
00348                         std::ostringstream contents;
00349                         contents << ifs.rdbuf();
00350                         ifs.close();
00351                         setVars = contents.str();
00352                     }
00353                     else
00354                     {
00355                         std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not open file " << optarg << std::endl;
00356                         return 1;
00357                     };
00358                 };
00359                 break;
00360             case OPT_MODIFY_OPTVEC:
00361                 modifyOptVec=true;
00362                 break;
00363             case ':':
00364             case '?':
00365                 // missing argument or invalid switch
00366                 return 1;
00367                 break;
00368             default:
00369                 // this should not happen
00370                 abort();
00371 
00372         }
00373     }
00374 
00375     if (argc - optind != 1)
00376     {
00377         if (argc - optind < 1)
00378         {
00379             std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
00380         }
00381         else
00382         {
00383             std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
00384         };
00385         return 1;
00386     };
00387 
00388     if(optVars.empty() && linkVars.empty() && unlinkVars.empty() && setVars.empty())
00389     {
00390         std::cerr << hugin_utils::stripPath(argv[0]) << ": no variables to modify given" << std::endl;
00391         return 1;
00392     };
00393 
00394     std::string input=argv[optind];
00395     // read panorama
00396     HuginBase::Panorama pano;
00397     std::ifstream prjfile(input.c_str());
00398     if (!prjfile.good())
00399     {
00400         std::cerr << "could not open script : " << input << std::endl;
00401         return 1;
00402     }
00403     pano.setFilePrefix(hugin_utils::getPathPrefix(input));
00404     AppBase::DocumentData::ReadWriteError err = pano.readData(prjfile);
00405     if (err != AppBase::DocumentData::SUCCESSFUL)
00406     {
00407         std::cerr << "error while parsing panos tool script: " << input << std::endl;
00408         std::cerr << "AppBase::DocumentData::ReadWriteError code: " << err << std::endl;
00409         return 1;
00410     }
00411 
00412     if(pano.getNrOfImages()==0)
00413     {
00414         std::cerr << "error: project file does not contains any image" << std::endl;
00415         std::cerr << "aborting processing" << std::endl;
00416         return 1;
00417     };
00418 
00419     //link/unlink variables
00420     if(!linkVars.empty())
00421     {
00422         std::cout << "Linking image variables" << std::endl;
00423         UnLinkVars(pano, linkVars, true);
00424         std::cout << std::endl;
00425     };
00426 
00427     if(!unlinkVars.empty())
00428     {
00429         std::cout << "Unlinking image variables" << std::endl;
00430         UnLinkVars(pano, unlinkVars, false);
00431         std::cout << std::endl;
00432     };
00433 
00434     // set variables to new value
00435     if(!setVars.empty())
00436     {
00437         std::cout << "Setting image variables" << std::endl;
00438         Parser::PanoParseExpression(pano, setVars);
00439         std::cout << std::endl;
00440     };
00441 
00442     // update optimzer vector
00443     if(!optVars.empty())
00444     {
00445         std::cout << "Updating optimizer variables" << std::endl;
00446         std::set<size_t> refImgs=pano.getRefImages();
00447         bool linkRefImgsYaw=false;
00448         bool linkRefImgsPitch=false;
00449         bool linkRefImgsRoll=false;
00450         pano.checkRefOptStatus(linkRefImgsYaw, linkRefImgsPitch, linkRefImgsRoll);
00451 
00452         //simplify handling of variable groups
00453         std::vector<std::set<std::string> > groupedVars;
00454         std::set<std::string> varSet;
00455         varSet.insert("Vb");
00456         varSet.insert("Vc");
00457         varSet.insert("Vd");
00458         groupedVars.push_back(varSet);
00459         varSet.clear();
00460         varSet.insert("Vx");
00461         varSet.insert("Vy");
00462         groupedVars.push_back(varSet);
00463         varSet.clear();
00464         varSet.insert("Ra");
00465         varSet.insert("Rb");
00466         varSet.insert("Rc");
00467         varSet.insert("Rd");
00468         varSet.insert("Re");
00469         groupedVars.push_back(varSet);
00470 
00471         HuginBase::OptimizeVector optVec;
00472         if(modifyOptVec)
00473         {
00474             optVec=pano.getOptimizeVector();
00475         };
00476         if(optVec.size()!=pano.getNrOfImages())
00477         {
00478             optVec.resize(pano.getNrOfImages());
00479         };
00480         for(size_t i=0; i<optVars.size(); i++)
00481         {
00482             //skip invalid image numbers
00483             if(optVars[i].imgNr>=(int)pano.getNrOfImages())
00484             {
00485                 continue;
00486             };
00487             if(optVars[i].imgNr==-1)
00488             {
00489                 for(size_t imgNr=0; imgNr<pano.getNrOfImages(); imgNr++)
00490                 {
00491                     if(optVars[i].flag)
00492                     {
00493                         RemoveFromOptVec(optVec, optVars[i].varname, imgNr, groupedVars);
00494                     }
00495                     else
00496                     {
00497                         AddToOptVec(optVec, optVars[i].varname, imgNr, refImgs, linkRefImgsYaw, linkRefImgsPitch, linkRefImgsRoll, groupedVars);
00498                     };
00499                 };
00500             }
00501             else
00502             {
00503                 if(optVars[i].flag)
00504                 {
00505                     RemoveFromOptVec(optVec, optVars[i].varname, optVars[i].imgNr, groupedVars);
00506                 }
00507                 else
00508                 {
00509                     AddToOptVec(optVec, optVars[i].varname, optVars[i].imgNr, refImgs, true, true, true, groupedVars);
00510                 };
00511             };
00512         };
00513         pano.setOptimizerSwitch(0);
00514         pano.setPhotometricOptimizerSwitch(0);
00515         pano.setOptimizeVector(optVec);
00516         std::cout << "Optimizer variables:" << std::endl;
00517         for (size_t i = 0; i < optVec.size(); ++i)
00518         {
00519             std::cout << "Image " << i << ": ";
00520             std::copy(optVec[i].begin(), optVec[i].end(), std::ostream_iterator<std::string>(std::cout, " "));
00521             std::cout << std::endl;
00522         };
00523         std::cout << std::endl;
00524     };
00525 
00526     //write output
00527     HuginBase::UIntSet imgs;
00528     fill_set(imgs,0, pano.getNrOfImages()-1);
00529     // Set output .pto filename if not given
00530     if (output=="")
00531     {
00532         output=input.substr(0,input.length()-4).append("_var.pto");
00533     }
00534     std::ofstream of(output.c_str());
00535     pano.printPanoramaScript(of, pano.getOptimizeVector(), pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input));
00536     std::cout << std::endl << "Written output to " << output << std::endl;
00537     return 0;
00538 }

Generated on 24 Nov 2017 for Hugintrunk by  doxygen 1.4.7