Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pto_var.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This software is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public
22  * License along with this software. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include <fstream>
28 #include <sstream>
29 #include <getopt.h>
30 #include <panodata/Panorama.h>
34 #include "hugin_utils/utils.h"
35 #include "panodata/ParseExp.h"
36 
37 // parse a single variable and put result in struct ParseVar
38 void ParseSingleOptVar(Parser::ParseVarVec& varVec, const std::string& s, std::ostream& errorStream)
39 {
40  // parse following regex ([!]?)([a-zA-Z]{1,3})(\\d*?)
41  std::string tempString(s);
42  Parser::ParseVar var;
43  var.flag = (tempString[0] == '!');
44  if (var.flag)
45  {
46  tempString.erase(0, 1);
47  };
48  if (Parser::ParseVarNumber(tempString, var))
49  {
50  varVec.push_back(var);
51  }
52  else
53  {
54  errorStream << "The expression \"" << tempString << "\" is not a valid image variable." << std::endl;
55  };
56 };
57 
58 void ParseSingleLinkVar(Parser::ParseVarVec& varVec, const std::string& s, std::ostream& errorStream)
59 {
60  // parse following regex ([a-zA-Z]{1,3})(\\d+?)
61  Parser::ParseVar var;
62  if (Parser::ParseVarNumber(s, var))
63  {
64  if (var.imgNr >= 0)
65  {
66  varVec.push_back(var);
67  }
68  else
69  {
70  errorStream << "The expression \"" << s << "\" does not contain a valid image number." << std::endl;
71  }
72  }
73  else
74  {
75  errorStream << "The expression \"" << s << "\" is not a valid image variable." << std::endl;
76  };
77 };
78 
79 // adds given varname to optVec
80 // does some additional checking:
81 // 1. don't add y,p,r for anchor image
82 // 2. handle vignetting and EMoR parameters as group
83 void AddToOptVec(HuginBase::OptimizeVector& optVec, std::string varname, size_t imgNr,
84  std::set<size_t> refImgs, bool linkRefImgsYaw, bool linkRefImgsPitch, bool linkRefImgsRoll, std::vector<std::set<std::string> > groupedVars)
85 {
86  if(varname=="y")
87  {
88  if(!set_contains(refImgs, imgNr) || linkRefImgsYaw)
89  {
90  optVec[imgNr].insert(varname);
91  };
92  }
93  else
94  {
95  if(varname=="p")
96  {
97  if(!set_contains(refImgs, imgNr) || linkRefImgsPitch)
98  {
99  optVec[imgNr].insert(varname);
100  };
101  }
102  else
103  {
104  if(varname=="r")
105  {
106  if(!set_contains(refImgs, imgNr) || linkRefImgsRoll)
107  {
108  optVec[imgNr].insert(varname);
109  };
110  }
111  else
112  {
113  if(varname=="TrX" || varname=="TrY" || varname=="TrZ" || varname=="Tpy" || varname=="Tpp")
114  {
115  if(!set_contains(refImgs, imgNr))
116  {
117  optVec[imgNr].insert(varname);
118  };
119  }
120  else
121  {
122  for(size_t i=0; i<groupedVars.size(); i++)
123  {
124  if(set_contains(groupedVars[i], varname))
125  {
126  for(std::set<std::string>::const_iterator it=groupedVars[i].begin(); it!=groupedVars[i].end(); ++it)
127  {
128  optVec[imgNr].insert(*it);
129  };
130  return;
131  };
132  };
133  optVec[imgNr].insert(varname);
134  };
135  };
136  };
137  };
138 };
139 
140 // remove given variable from optvec, handle also correct grouped variables
141 void RemoveFromOptVec(HuginBase::OptimizeVector& optVec, std::string varname, size_t imgNr, std::vector<std::set<std::string> > groupedVars)
142 {
143  for(size_t i=0; i<groupedVars.size(); i++)
144  {
145  if(set_contains(groupedVars[i], varname))
146  {
147  for(std::set<std::string>::const_iterator it=groupedVars[i].begin(); it!=groupedVars[i].end(); ++it)
148  {
149  optVec[imgNr].erase(*it);
150  };
151  return;
152  };
153  };
154  optVec[imgNr].erase(varname);
155 };
156 
157 // link or unlink the parsed image variables
158 void UnLinkVars(HuginBase::Panorama& pano, Parser::ParseVarVec parseVec, bool link)
159 {
160  for(size_t i=0; i<parseVec.size(); i++)
161  {
162  //skip invalid image numbers
163  if(parseVec[i].imgNr<0 || parseVec[i].imgNr>=(int)pano.getNrOfImages())
164  {
165  continue;
166  };
167 
168  //convert to ImageVariableGroup::IVE_name format
169  std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> variables;
170 #define image_variable( name, type, default_value ) \
171  if (HuginBase::PTOVariableConverterFor##name::checkApplicability(parseVec[i].varname))\
172  {\
173  variables.insert(HuginBase::ImageVariableGroup::IVE_##name);\
174  };
176 #undef image_variable
177 
178  if(!variables.empty())
179  {
180  //lens variable
182  {
184  if (link)
185  {
186  std::cout << "Linking";
187  group.linkVariableImage(*variables.begin(), parseVec[i].imgNr);
188  }
189  else
190  {
191  std::cout << "Unlinking";
192  group.unlinkVariableImage(*variables.begin(), parseVec[i].imgNr);
193  group.updatePartNumbers();
194  }
195  std::cout << " image variable " << parseVec[i].varname << " for image " << parseVec[i].imgNr << std::endl;
196  }
197  else
198  {
199  //stack variables
200  // handle yaw, pitch, roll, TrX, TrY and TrZ always together
202  {
204  if (link)
205  {
206  std::cout << "Linking";
207  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Yaw, parseVec[i].imgNr);
208  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Pitch, parseVec[i].imgNr);
209  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Roll, parseVec[i].imgNr);
210  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_X, parseVec[i].imgNr);
211  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Y, parseVec[i].imgNr);
212  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_Z, parseVec[i].imgNr);
213  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw, parseVec[i].imgNr);
214  group.linkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch, parseVec[i].imgNr);
215  }
216  else
217  {
218  std::cout << "Unlinking";
219  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Yaw, parseVec[i].imgNr);
220  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Pitch, parseVec[i].imgNr);
221  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Roll, parseVec[i].imgNr);
222  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_X, parseVec[i].imgNr);
223  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Y, parseVec[i].imgNr);
224  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_Z, parseVec[i].imgNr);
225  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlaneYaw, parseVec[i].imgNr);
226  group.unlinkVariableImage(HuginBase::ImageVariableGroup::IVE_TranslationPlanePitch, parseVec[i].imgNr);
227  group.updatePartNumbers();
228  }
229  std::cout << " image position (ypr, TrXYZ, Tpyp) for image " << parseVec[i].imgNr << std::endl;
230  }
231  else
232  {
233  std::cerr << "Warning: " << parseVec[i].varname << " is not a valid linkable variable." << std::endl;
234  };
235  };
236  };
237  };
238  // update optimize variables, e.g. the link has changed and the new unlinked variables need
239  // to be added to optimize vector
240  pano.updateOptimizeVector();
241 };
242 
243 // parse number, take an optional % sign into account
244 // in case of a relativ value the result is normed to 1
245 bool ParseCoordinateRelativ(const std::string& s, double& val, bool& relativ)
246 {
247  size_t pos = s.find('%');
248  relativ = (pos != std::string::npos);
249  if (relativ)
250  {
251  if (pos < s.length() - 1)
252  {
253  // there are characters afters the percent sign
254  // this is not supported
255  return false;
256  };
257  if( hugin_utils::stringToDouble(s.substr(0, pos), val))
258  {
259  val /= 100.0;
260  return true;
261  };
262  }
263  else
264  {
265  // enforce integer values
266  int intValue;
267  if (hugin_utils::stringToInt(s, intValue))
268  {
269  val = intValue;
270  return true;
271  };
272  };
273  return false;
274 }
275 
276 // parse given crop string s and set corresponding crop in pano for images in UIntSet
277 void SetCropToImages(const std::string& s, HuginBase::Panorama& pano, HuginBase::UIntSet& imgs)
278 {
279  std::vector<std::string> coords = hugin_utils::SplitString(s, ",");
280  if (coords.size() == 2)
281  {
282  // only 2 coordinates, take them as width and height and activate autocenter crop
283  double width, height;
284  bool relWidth = false;
285  bool relHeight = false;
286  if (ParseCoordinateRelativ(coords[0], width, relWidth) && ParseCoordinateRelativ(coords[1], height, relHeight))
287  {
288  for (auto& i : imgs)
289  {
290  HuginBase::SrcPanoImage img = pano.getSrcImage(i);
291  vigra::Rect2D cropRect;
292  cropRect.setSize(relWidth ? (img.getWidth()*width) : width, relHeight ? (img.getHeight()*height) : height);
293  img.setCropRect(cropRect);
294  img.setAutoCenterCrop(true);
295  pano.setSrcImage(i, img);
296  pano.changeFinished();
297  // print result
298  std::cout << "Set crop for image " << i << " to " << pano.getImage(i).getCropRect() << std::endl;
299  };
300  }
301  else
302  {
303  std::cerr << "Could not parse crop string \"" << s << "\"." << std::endl;
304  return;
305  };
306  }
307  else
308  {
309  if (coords.size() == 4)
310  {
311  // we got 4 coordinates
312  int left, right, top, bottom;
313  if (hugin_utils::stringToInt(coords[0], left) && hugin_utils::stringToInt(coords[1], right) &&
314  hugin_utils::stringToInt(coords[2], top) && hugin_utils::stringToInt(coords[3], bottom))
315  {
316  vigra::Rect2D cropRect;
317  if (right > left && bottom > top)
318  {
319  cropRect.setUpperLeft(vigra::Point2D(left, top));
320  cropRect.setLowerRight(vigra::Point2D(right, bottom));
321  }
322  else
323  {
324  std::cerr << "Crop \"" << s << "\" is an invalid crop area." << std::endl;
325  return;
326  };
327  for (auto& i : imgs)
328  {
329  HuginBase::SrcPanoImage img = pano.getSrcImage(i);
330  img.setAutoCenterCrop(false);
331  img.setCropRect(cropRect);
332  pano.setSrcImage(i, img);
333  pano.changeFinished();
334  // print result
335  std::cout << "Set crop for image " << i << " to " << pano.getImage(i).getCropRect() << std::endl;
336  };
337  }
338  else
339  {
340  std::cerr << "Could not parse crop values \"" << s << "\"." << std::endl;
341  return;
342  };
343  }
344  else
345  {
346  std::cerr << "Invalid coordinates \"" << s << "\"." << std::endl;
347  return;
348  }
349  };
350  return;
351 }
352 
353 // set the crop from the string
354 void SetCrop(HuginBase::Panorama& pano, const std::string& crop)
355 {
356  // split string at ';'
357  std::vector<std::string> splitResult = hugin_utils::SplitString(crop, ";");
358  // now process each sub-string
359  for (auto& s : splitResult)
360  {
361  std::string subString = hugin_utils::StrTrim(s);
362  if (subString.empty())
363  {
364  continue;
365  };
366  size_t pos = subString.find("=");
367  if(subString[0]=='i' && pos==std::string::npos)
368  {
369  std::cerr << "Crop expression \"" << s << "\" is not a valid crop." << std::endl;
370  continue;
371  };
372  if (subString[0] == 'i')
373  {
374  if (pos < 2)
375  {
376  std::cerr << "Crop expression \"" << s << "\" does not contain a valid image number."<< std::endl;
377  continue;
378  };
379  unsigned int imgNr;
380  if(!hugin_utils::stringToUInt(subString.substr(1, pos-1), imgNr))
381  {
382  std::cerr << "Crop expression \"" << s << "\" does not contain a valid image number." << std::endl;
383  continue;
384  };
385  if (imgNr >= pano.getNrOfImages())
386  {
387  std::cerr << "Pano does not contain image with number " << imgNr << std::endl;
388  continue;
389  };
390  HuginBase::UIntSet imgs;
391  imgs.insert(imgNr);
392  SetCropToImages(subString.substr(pos + 1), pano, imgs);
393  }
394  else
395  {
396  // update crop for all images
397  HuginBase::UIntSet imgs;
398  fill_set(imgs, 0, pano.getNrOfImages() - 1);
399  SetCropToImages(subString, pano, imgs);
400  };
401  };
402 };
403 
404 // activate or deactive images
405 void EnableImages(HuginBase::Panorama& pano, const std::string& imageList, const bool enable)
406 {
407  // split string at ','
408  std::vector<std::string> imagesString = hugin_utils::SplitString(imageList, ",");
409  for (auto& img : imagesString)
410  {
411  if (img.empty())
412  {
413  continue;
414  };
415  int imgNr;
416  // convert to int and check results
417  if (hugin_utils::stringToInt(img, imgNr))
418  {
419  if (imgNr >= 0 && imgNr < pano.getNrOfImages())
420  {
421  pano.activateImage(imgNr, enable);
422  std::cout << (enable ? "Enabling" : "Disabling") << " image " << imgNr << std::endl;
423  }
424  else
425  {
426  std::cerr << "Pano does not contain image with number " << imgNr << (enable ? " to activate." : " to disable.") << std::endl;
427  };
428  }
429  else
430  {
431  std::cerr << (enable ? "Enable images: " : "Disable images: ") <<
432  "string " << img << " can't be parsed as valid number." << std::endl;
433  };
434  };
435 };
436 
437 static void usage(const char* name)
438 {
439  std::cout << name << ": change image variables inside pto files" << std::endl
440  << name << " version " << hugin_utils::GetHuginVersion() << std::endl
441  << std::endl
442  << "Usage: " << name << " [options] --opt|--link|--unlink|--set varlist input.pto" << std::endl
443  << std::endl
444  << " -o, --output=file.pto Output Hugin PTO file. Default: <filename>_var.pto" << std::endl
445  << " -h, --help Shows this help" << std::endl
446  << std::endl
447  << " --opt varlist Change optimizer variables" << std::endl
448  << " --modify-opt Modify the existing optimizer variables" << std::endl
449  << " (without pto_var will start with an" << std::endl
450  << " empty variables set)" << std::endl
451  << " Examples:" << std::endl
452  << " --opt=y,p,r Optimize yaw, pitch and roll of all images" << std::endl
453  << " (special treatment for anchor image applies)" << std::endl
454  << " --opt=v0,b2 Optimize hfov of image 0 and barrel distortion" << std::endl
455  << " of image 2" << std::endl
456  << " --opt=v,!v0 Optimize field of view for all images except" << std::endl
457  << " for the first image" << std::endl
458  << " --opt=!a,!b,!c Don't optimise distortion (works only with" << std::endl
459  << " switch --modify-opt together)" << std::endl
460  << std::endl
461  << " --link varlist Link given variables" << std::endl
462  << " Example:" << std::endl
463  << " --link=v3 Link hfov of image 3" << std::endl
464  << " --link=a1,b1,c1 Link distortions parameter for image 1" << std::endl
465  << std::endl
466  << " --unlink varlist Unlink given variables" << std::endl
467  << " Examples:" << std::endl
468  << " --unlink=v5 Unlink hfov for image 5" << std::endl
469  << " --unlink=a2,b2,c2 Unlink distortions parameters for image 2" << std::endl
470  << std::endl
471  << " --set varlist Sets variables to new values" << std::endl
472  << " Examples:" << std::endl
473  << " --set=y0=0,r0=0,p0=0 Resets position of image 0" << std::endl
474  << " --set=Vx4=-10,Vy4=10 Sets vignetting offset for image 4" << std::endl
475  << " --set=v=20 Sets the field of view to 20 for all images" << std::endl
476  << " --set=y=val+20 Increase yaw by 20 deg for all images" << std::endl
477  << " --set=v=val*1.1 Increase fov by 10 % for all images" << std::endl
478  << " --set=y=i*20 Set yaw to 0, 20, 40, ..." << std::endl
479  << " --set-from-file filename Sets variables to new values" << std::endl
480  << " It reads the varlist from a file" << std::endl
481  << std::endl
482  << " --crop=left,right,top,bottom Set the crop for all images" << std::endl
483  << " --crop=width,height Set the crop for all images and activate" << std::endl
484  << " autocenter for crop" << std::endl
485  << " relative values can be used with %" << std::endl
486  << " --crop=iNUM=left,right,top,bottom Set the crop for image NUM" << std::endl
487  << " --crop=iNUM=width,height Set the crop for image NUM and" << std::endl
488  << " activate autocenter for crop" << std::endl
489  << " These switches can be used several times." << std::endl
490  << std::endl
491  << " --anchor=NUM Sets the image NUM as anchor for geometric" << std::endl
492  << " optimisation." << std::endl
493  << " --color-anchor=NUM Sets the image NUM as anchor for photometric" << std::endl
494  << " optimisation." << std::endl
495  << std::endl
496  << " --enable-image=NUM1[,NUM2...] Enables images for stitching" << std::endl
497  << " --disable-image=NUM1[,NUM2...] Disables images for stitching" << std::endl
498  << std::endl;
499 }
500 
501 int main(int argc, char* argv[])
502 {
503  // parse arguments
504  const char* optstring = "o:h";
505 
506  enum
507  {
508  SWITCH_OPT=1000,
509  SWITCH_LINK,
510  SWITCH_UNLINK,
511  SWITCH_SET,
512  SWITCH_SET_FILE,
513  OPT_MODIFY_OPTVEC,
514  SWITCH_CROP,
515  SWITCH_ANCHOR,
516  SWITCH_COLOR_ANCHOR,
517  SWITCH_ENABLE_IMAGE,
518  SWITCH_DISABLE_IMAGE
519  };
520  static struct option longOptions[] =
521  {
522  {"output", required_argument, NULL, 'o' },
523  {"opt", required_argument, NULL, SWITCH_OPT },
524  {"link", required_argument, NULL, SWITCH_LINK },
525  {"unlink", required_argument, NULL, SWITCH_UNLINK },
526  {"set", required_argument, NULL, SWITCH_SET },
527  {"set-from-file", required_argument, NULL, SWITCH_SET_FILE },
528  {"modify-opt", no_argument, NULL, OPT_MODIFY_OPTVEC },
529  {"crop", required_argument, NULL, SWITCH_CROP },
530  {"anchor", required_argument, NULL, SWITCH_ANCHOR },
531  {"color-anchor", required_argument, NULL, SWITCH_COLOR_ANCHOR },
532  {"enable-image", required_argument, NULL, SWITCH_ENABLE_IMAGE },
533  {"disable-image", required_argument, NULL, SWITCH_DISABLE_IMAGE },
534  {"help", no_argument, NULL, 'h' },
535  0
536  };
537 
538  Parser::ParseVarVec optVars;
539  Parser::ParseVarVec linkVars;
540  Parser::ParseVarVec unlinkVars;
541  std::string setVars, crop, enableImages, disableImages;
542  int anchor = -1;
543  int colorAnchor = -1;
544  bool modifyOptVec=false;
545  int c;
546  std::string output;
547  while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
548  {
549  switch (c)
550  {
551  case 'o':
552  output = optarg;
553  break;
554  case 'h':
555  usage(hugin_utils::stripPath(argv[0]).c_str());
556  return 0;
557  case SWITCH_OPT:
558  Parser::ParseVariableString(optVars, std::string(optarg), std::cerr, ParseSingleOptVar);
559  break;
560  case SWITCH_LINK:
561  Parser::ParseVariableString(linkVars, std::string(optarg), std::cerr, ParseSingleLinkVar);
562  break;
563  case SWITCH_UNLINK:
564  Parser::ParseVariableString(unlinkVars, std::string(optarg), std::cerr, ParseSingleLinkVar);
565  break;
566  case SWITCH_SET:
567  if (!setVars.empty())
568  {
569  setVars.append(",");
570  };
571  setVars.append(optarg);
572  break;
573  case SWITCH_SET_FILE:
574  {
575  std::ifstream ifs(optarg);
576  if(ifs.is_open())
577  {
578  std::ostringstream contents;
579  contents << ifs.rdbuf();
580  ifs.close();
581  setVars = contents.str();
582  }
583  else
584  {
585  std::cerr << hugin_utils::stripPath(argv[0]) << ": Could not open file " << optarg << std::endl;
586  return 1;
587  };
588  };
589  break;
590  case OPT_MODIFY_OPTVEC:
591  modifyOptVec=true;
592  break;
593  case SWITCH_CROP:
594  if (!crop.empty())
595  {
596  crop.append(";");
597  };
598  crop.append(optarg);
599  break;
600  case SWITCH_ANCHOR:
601  if(hugin_utils::stringToInt(std::string(optarg), anchor))
602  {
603  if (anchor < 0)
604  {
605  std::cerr << "ERROR: Number " << anchor << " for --anchor has to be >=0." << std::endl;
606  return 1;
607  };
608  }
609  else
610  {
611  std::cerr << "ERROR: \"" << optarg << "\" is not a valid number for --anchor parameter." << std::endl;
612  return 1;
613  };
614  break;
615  case SWITCH_COLOR_ANCHOR:
616  if (hugin_utils::stringToInt(std::string(optarg), colorAnchor))
617  {
618  if (colorAnchor < 0)
619  {
620  std::cerr << "ERROR: Number " << colorAnchor << " for --color-anchor has to be >=0." << std::endl;
621  return 1;
622  };
623  }
624  else
625  {
626  std::cerr << "ERROR: \"" << optarg << "\" is not a valid number for --color-anchor parameter." << std::endl;
627  return 1;
628  };
629  break;
630  case SWITCH_ENABLE_IMAGE:
631  if (!enableImages.empty())
632  {
633  enableImages.append(",");
634  };
635  enableImages.append(optarg);
636  break;
637  case SWITCH_DISABLE_IMAGE:
638  if (!disableImages.empty())
639  {
640  disableImages.append(",");
641  };
642  disableImages.append(optarg);
643  break;
644  case ':':
645  case '?':
646  // missing argument or invalid switch
647  return 1;
648  break;
649  default:
650  // this should not happen
651  abort();
652 
653  }
654  }
655 
656  if (argc - optind != 1)
657  {
658  if (argc - optind < 1)
659  {
660  std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
661  }
662  else
663  {
664  std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
665  };
666  return 1;
667  };
668 
669  if (optVars.empty() && linkVars.empty() && unlinkVars.empty() && setVars.empty() && crop.empty() && anchor < 0 && colorAnchor < 0
670  && enableImages.empty() && disableImages.empty())
671  {
672  std::cerr << hugin_utils::stripPath(argv[0]) << ": no variables to modify given" << std::endl;
673  return 1;
674  };
675 
676  std::string input=argv[optind];
677  // read panorama
678  HuginBase::Panorama pano;
679  if (!pano.ReadPTOFile(input, hugin_utils::getPathPrefix(input)))
680  {
681  return 1;
682  };
683 
684  //link/unlink variables
685  if(!linkVars.empty())
686  {
687  std::cout << "Linking image variables" << std::endl;
688  UnLinkVars(pano, linkVars, true);
689  std::cout << std::endl;
690  };
691 
692  if(!unlinkVars.empty())
693  {
694  std::cout << "Unlinking image variables" << std::endl;
695  UnLinkVars(pano, unlinkVars, false);
696  std::cout << std::endl;
697  };
698 
699  // set variables to new value
700  if(!setVars.empty())
701  {
702  std::cout << "Setting image variables" << std::endl;
703  Parser::PanoParseExpression(pano, setVars);
704  std::cout << std::endl;
705  };
706 
707  // update anchor
708  if (anchor >= 0)
709  {
710  if (anchor >= pano.getNrOfImages())
711  {
712  std::cout << "WARNING: Image number " << anchor << " is not a valid number for the anchor image." << std::endl;
713  }
714  else
715  {
717  std::cout << "Setting optimizer anchor to image " << anchor << std::endl;
718  opts.optimizeReferenceImage = anchor;
719  pano.setOptions(opts);
720  pano.updateOptimizeVector();
721  };
722  };
723  // update color anchor
724  if (colorAnchor >= 0)
725  {
726  if (colorAnchor >= pano.getNrOfImages())
727  {
728  std::cout << "WARNING: Image number " << anchor << " is not a valid number for the color anchor image." << std::endl;
729  }
730  else
731  {
733  std::cout << "Setting color anchor to image " << colorAnchor << std::endl;
734  opts.colorReferenceImage = colorAnchor;
735  pano.setOptions(opts);
736  pano.updateOptimizeVector();
737  };
738  };
739  // update optimzer vector
740  if(!optVars.empty())
741  {
742  std::cout << "Updating optimizer variables" << std::endl;
743  std::set<size_t> refImgs=pano.getRefImages();
744  bool linkRefImgsYaw=false;
745  bool linkRefImgsPitch=false;
746  bool linkRefImgsRoll=false;
747  pano.checkRefOptStatus(linkRefImgsYaw, linkRefImgsPitch, linkRefImgsRoll);
748 
749  //simplify handling of variable groups
750  std::vector<std::set<std::string> > groupedVars;
751  std::set<std::string> varSet;
752  varSet.insert("Vb");
753  varSet.insert("Vc");
754  varSet.insert("Vd");
755  groupedVars.push_back(varSet);
756  varSet.clear();
757  varSet.insert("Vx");
758  varSet.insert("Vy");
759  groupedVars.push_back(varSet);
760  varSet.clear();
761  varSet.insert("Ra");
762  varSet.insert("Rb");
763  varSet.insert("Rc");
764  varSet.insert("Rd");
765  varSet.insert("Re");
766  groupedVars.push_back(varSet);
767 
769  if(modifyOptVec)
770  {
771  optVec=pano.getOptimizeVector();
772  };
773  if(optVec.size()!=pano.getNrOfImages())
774  {
775  optVec.resize(pano.getNrOfImages());
776  };
777  for(size_t i=0; i<optVars.size(); i++)
778  {
779  //skip invalid image numbers
780  if(optVars[i].imgNr>=(int)pano.getNrOfImages())
781  {
782  continue;
783  };
784  if(optVars[i].imgNr==-1)
785  {
786  for(size_t imgNr=0; imgNr<pano.getNrOfImages(); imgNr++)
787  {
788  if(optVars[i].flag)
789  {
790  RemoveFromOptVec(optVec, optVars[i].varname, imgNr, groupedVars);
791  }
792  else
793  {
794  AddToOptVec(optVec, optVars[i].varname, imgNr, refImgs, linkRefImgsYaw, linkRefImgsPitch, linkRefImgsRoll, groupedVars);
795  };
796  };
797  }
798  else
799  {
800  if(optVars[i].flag)
801  {
802  RemoveFromOptVec(optVec, optVars[i].varname, optVars[i].imgNr, groupedVars);
803  }
804  else
805  {
806  AddToOptVec(optVec, optVars[i].varname, optVars[i].imgNr, refImgs, true, true, true, groupedVars);
807  };
808  };
809  };
810  pano.setOptimizerSwitch(0);
812  pano.setOptimizeVector(optVec);
813  std::cout << "Optimizer variables:" << std::endl;
814  for (size_t i = 0; i < optVec.size(); ++i)
815  {
816  std::cout << "Image " << i << ": ";
817  std::copy(optVec[i].begin(), optVec[i].end(), std::ostream_iterator<std::string>(std::cout, " "));
818  std::cout << std::endl;
819  };
820  std::cout << std::endl;
821  };
822 
823  // update crop
824  if (!crop.empty())
825  {
826  std::cout << "Setting image crop" << std::endl;
827  SetCrop(pano, crop);
828  std::cout << std::endl;
829  };
830 
831  // update active/disabled images
832  if (!enableImages.empty())
833  {
834  std::cout << "Activating images" << std::endl;
835  EnableImages(pano, enableImages, true);
836  std::cout << std::endl;
837  };
838  if (!disableImages.empty())
839  {
840  std::cout << "Disabling images" << std::endl;
841  EnableImages(pano, disableImages, false);
842  std::cout << std::endl;
843  };
844 
845  //write output
846  // Set output .pto filename if not given
847  output = hugin_utils::GetOutputFilename(output, input, "var");
848  if (pano.WritePTOFile(output, hugin_utils::getPathPrefix(output)))
849  {
850  std::cout << std::endl << "Written project file " << output << std::endl;
851  };
852  return 0;
853 }
std::set< size_t > getRefImages()
returns set of reference image and images linked with reference images
Definition: Panorama.cpp:1235
void ParseVariableString(ParseVarVec &parseVec, const std::string &input, std::ostream &errorStream, void(*func)(ParseVarVec &, const std::string &, std::ostream &))
parse complete variables string
Definition: ParseExp.cpp:699
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getLensVariables()
Get the set of lens image variables.
void AddToOptVec(HuginBase::OptimizeVector &optVec, std::string varname, size_t imgNr, std::set< size_t > refImgs, bool linkRefImgsYaw, bool linkRefImgsPitch, bool linkRefImgsRoll, std::vector< std::set< std::string > > groupedVars)
Definition: pto_var.cpp:83
void updateOptimizeVector()
updates the optimize vector according to master switches
Definition: Panorama.cpp:1299
std::string StrTrim(const std::string &str)
remove trailing and leading white spaces and tabs
Definition: utils.cpp:208
void checkRefOptStatus(bool &linkRefImgsYaw, bool &linkRefImgsPitch, bool &linkRefImgsRoll)
checks if yaw/pitch/roll of reference image can be check, it depends on number and type of control po...
Definition: Panorama.cpp:1255
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition: utils.cpp:420
void SetCropToImages(const std::string &s, HuginBase::Panorama &pano, HuginBase::UIntSet &imgs)
Definition: pto_var.cpp:277
void setPhotometricOptimizerSwitch(const int newSwitch)
sets the photometric optimizer master switch
Definition: Panorama.cpp:311
IMPEX bool ParseVarNumber(const std::string &s, Parser::ParseVar &var)
parse string s and store result in ParseVar var
Somewhere to specify what variables belong to what.
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
struct to save parsed variables and optional image numbers
Definition: ParseExp.h:39
int getHeight() const
Get the height of the image in pixels.
Definition: SrcPanoImage.h:276
void setOptimizerSwitch(const int newSwitch)
set optimizer master switch
Definition: Panorama.cpp:303
Declare the ImageVariableGroup and ImageVariableGroupObserver classes.
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition: Panorama.cpp:297
bool stringToUInt(const std::string &s, unsigned int &val)
convert string to unsigned integer value, returns true, if sucessful
Definition: utils.cpp:280
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
void ParseSingleLinkVar(Parser::ParseVarVec &varVec, const std::string &s, std::ostream &errorStream)
Definition: pto_var.cpp:58
IMPEX void PanoParseExpression(HuginBase::Panorama &pano, const std::string &expression, std::ostream &statusStream=std::cout, std::ostream &errorStream=std::cerr)
parses the given expression and apply the changes to the Panorama
Model for a panorama.
Definition: Panorama.h:152
void ParseSingleOptVar(Parser::ParseVarVec &varVec, const std::string &s, std::ostream &errorStream)
Definition: pto_var.cpp:38
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
const OptimizeVector & getOptimizeVector() const
return the optimize settings stored inside panorama
Definition: Panorama.h:454
std::vector< ParseVar > ParseVarVec
Definition: ParseExp.h:48
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
int getWidth() const
Get the width of the image in pixels.
Definition: SrcPanoImage.h:266
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Definition: Panorama.cpp:2023
void activateImage(unsigned int imgNr, bool active=true)
mark an image as active or inactive.
Definition: Panorama.cpp:1575
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
Definition: utils.cpp:264
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
Definition: utils.h:114
void RemoveFromOptVec(HuginBase::OptimizeVector &optVec, std::string varname, size_t imgNr, std::vector< std::set< std::string > > groupedVars)
Definition: pto_var.cpp:141
Same as above, but use a non const panorama.
void changeFinished(bool keepDirty)
notify observers about changes in this class
Definition: Panorama.cpp:831
Convenience functions for SrcPanoImage to use on the image variables.
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
static void usage()
Definition: Main.cpp:32
void EnableImages(HuginBase::Panorama &pano, const std::string &imageList, const bool enable)
Definition: pto_var.cpp:405
void setSize(vigra::Size2D val)
Set the image size in pixels.
void SetCrop(const std::string &cropString, HuginBase::Panorama &pano, HuginBase::PanoramaOptions &options)
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:907
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
std::vector< std::set< std::string > > OptimizeVector
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
Definition: utils.cpp:294
All variables of a source image.
Definition: SrcPanoImage.h:194
Panorama image options.
This file specifies what image variables SrcPanoImg should have.
function to parse expressions from strings
bool ParseCoordinateRelativ(const std::string &s, double &val, bool &relativ)
Definition: pto_var.cpp:245
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getStackVariables()
Get the set of stack image variables.
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition: utils.cpp:160
int main(int argc, char *argv[])
Definition: Main.cpp:167