CPVector AutoCtrlPointCreator::readUpdatedControlPoints(const std::string & file, PT::Panorama & pano) { ifstream stream(file.c_str()); if (! stream.is_open()) { DEBUG_ERROR("Could not open autopano output: " << file); return CPVector(); } Panorama tmpp; PanoramaMemento newPano; int ptoVersion = 0; newPano.loadPTScript(stream, ptoVersion, ""); tmpp.setMemento(newPano); // create mapping between the panorama images. map<unsigned int, unsigned int> imgMapping; for (unsigned int ni = 0; ni < tmpp.getNrOfImages(); ni++) { std::string nname = stripPath(tmpp.getImage(ni).getFilename()); for (unsigned int oi=0; oi < pano.getNrOfImages(); oi++) { std::string oname = stripPath(pano.getImage(oi).getFilename()); if (nname == oname) { // insert image imgMapping[ni] = oi; break; } } if (! set_contains(imgMapping, ni)) { DEBUG_ERROR("Could not find image " << ni << ", name: " << tmpp.getImage(ni).getFilename() << " in autopano output"); return CPVector(); } } // get control points CPVector ctrlPoints = tmpp.getCtrlPoints(); // make sure they are in correct order for (CPVector::iterator it= ctrlPoints.begin(); it != ctrlPoints.end(); ++it) { (*it).image1Nr = imgMapping[(*it).image1Nr]; (*it).image2Nr = imgMapping[(*it).image2Nr]; } return ctrlPoints; }
CPVector AutoCtrlPointCreator::readUpdatedControlPoints(const std::string & file, PT::Panorama & pano, const PT::UIntSet & imgs) { ifstream stream(file.c_str()); if (! stream.is_open()) { DEBUG_ERROR("Could not open control point detector output: " << file); return CPVector(); } Panorama tmpp; PanoramaMemento newPano; int ptoVersion = 0; newPano.loadPTScript(stream, ptoVersion, ""); tmpp.setMemento(newPano); //check if sizes matches if(tmpp.getNrOfImages()!=imgs.size()) { return CPVector(); }; // create mapping between the panorama images. vector<size_t> imgMapping(imgs.size()); size_t i=0; for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();it++) { imgMapping[i++]=*it; }; // get control points CPVector ctrlPoints = tmpp.getCtrlPoints(); // make sure they are in correct order for (CPVector::iterator it= ctrlPoints.begin(); it != ctrlPoints.end(); ++it) { (*it).image1Nr = imgMapping[(*it).image1Nr]; (*it).image2Nr = imgMapping[(*it).image2Nr]; } return ctrlPoints; }
int main(int argc, char *argv[]) { // parse arguments const char * optstring = "alho:npqsv:m"; int c; string output; bool doPairwise = false; bool doAutoOpt = false; bool doNormalOpt = false; bool doLevel = false; bool chooseProj = false; bool quiet = false; bool doPhotometric = false; double hfov = 0.0; while ((c = getopt (argc, argv, optstring)) != -1) { switch (c) { case 'o': output = optarg; break; case 'h': usage(argv[0]); return 0; case 'p': doPairwise = true; break; case 'a': doAutoOpt = true; break; case 'n': doNormalOpt = true; break; case 'l': doLevel = true; break; case 's': chooseProj = true; break; case 'q': quiet = true; break; case 'v': hfov = atof(optarg); break; case 'm': doPhotometric = true; break; default: abort (); } } if (argc - optind != 1) { usage(argv[0]); return 1; } const char * scriptFile = argv[optind]; Panorama pano; if (scriptFile[0] == '-') { DocumentData::ReadWriteError err = pano.readData(std::cin); if (err != DocumentData::SUCCESSFUL) { cerr << "error while reading script file from stdin." << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } } else { ifstream prjfile(scriptFile); if (!prjfile.good()) { cerr << "could not open script : " << scriptFile << endl; return 1; } pano.setFilePrefix(hugin_utils::getPathPrefix(scriptFile)); DocumentData::ReadWriteError err = pano.readData(prjfile); if (err != DocumentData::SUCCESSFUL) { cerr << "error while parsing panos tool script: " << scriptFile << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } } if (pano.getNrOfImages() == 0) { cerr << "Panorama should consist of at least one image" << endl; return 1; } // for bad HFOV (from autopano-SIFT) for (unsigned i=0; i < pano.getNrOfImages(); i++) { SrcPanoImage img = pano.getSrcImage(i); if (img.getProjection() == SrcPanoImage::RECTILINEAR && img.getHFOV() >= 180) { // something is wrong here, try to read from exif data double focalLength = 0; double cropFactor = 0; cerr << "HFOV of image " << img.getFilename() << " invalid, trying to read EXIF tags" << endl; bool ok = img.readEXIF(focalLength, cropFactor, true, false); if (! ok) { if (hfov) { img.setHFOV(hfov); } else { cerr << "EXIF reading failed, please specify HFOV with -v" << endl; return 1; } } pano.setSrcImage(i, img); } } if(pano.getNrOfCtrlPoints()==0 && (doPairwise || doAutoOpt || doNormalOpt)) { cerr << "Panorama have to have control points to optimise positions" << endl; return 1; }; if (doPairwise && ! doAutoOpt) { // do pairwise optimisation set<string> optvars; optvars.insert("r"); optvars.insert("p"); optvars.insert("y"); AutoOptimise::autoOptimise(pano); // do global optimisation if (!quiet) std::cerr << "*** Pairwise position optimisation" << endl; PTools::optimize(pano); } else if (doAutoOpt) { if (!quiet) std::cerr << "*** Adaptive geometric optimisation" << endl; SmartOptimise::smartOptimize(pano); } else if (doNormalOpt) { if (!quiet) std::cerr << "*** Optimising parameters specified in PTO file" << endl; PTools::optimize(pano); } else { if (!quiet) std::cerr << "*** Geometric parameters not optimized" << endl; } if (doLevel) { bool hasVerticalLines=false; CPVector allCP=pano.getCtrlPoints(); if(allCP.size()>0 && (doPairwise || doAutoOpt || doNormalOpt)) { for(size_t i=0;i<allCP.size() && !hasVerticalLines;i++) { hasVerticalLines=(allCP[i].mode==ControlPoint::X); }; }; // straighten only if there are no vertical control points if(hasVerticalLines) { cout << "Skipping automatic leveling because of existing vertical control points." << endl; } else { StraightenPanorama(pano).run(); CenterHorizontally(pano).run(); }; } if (chooseProj) { PanoramaOptions opts = pano.getOptions(); double hfov, vfov; CalculateFitPanorama fitPano = CalculateFitPanorama(pano); fitPano.run(); opts.setHFOV(fitPano.getResultHorizontalFOV()); opts.setHeight(roundi(fitPano.getResultHeight())); vfov = opts.getVFOV(); hfov = opts.getHFOV(); // avoid perspective projection if field of view > 100 deg double mf = 100; if (vfov < mf) { // cylindrical or rectilinear if (hfov < mf) { opts.setProjection(PanoramaOptions::RECTILINEAR); } else { opts.setProjection(PanoramaOptions::CYLINDRICAL); } } // downscale pano a little double sizeFactor = 0.7; pano.setOptions(opts); double w = CalculateOptimalScale::calcOptimalScale(pano); opts.setWidth(roundi(opts.getWidth()*w*sizeFactor), true); pano.setOptions(opts); } if(doPhotometric) { // photometric estimation PanoramaOptions opts = pano.getOptions(); int nPoints = 200; int pyrLevel=3; bool randomPoints = true; nPoints = nPoints * pano.getNrOfImages(); std::vector<vigra_ext::PointPairRGB> points; ProgressDisplay *progressDisplay; if(!quiet) progressDisplay=new StreamProgressDisplay(std::cout); else progressDisplay=new DummyProgressDisplay(); try { loadImgsAndExtractPoints(pano, nPoints, pyrLevel, randomPoints, *progressDisplay, points, !quiet); } catch (std::exception & e) { cerr << "caught exception: " << e.what() << endl; return 1; }; if(!quiet) cout << "\rSelected " << points.size() << " points" << endl; if (points.size() == 0) { cerr << "Error: no overlapping points found, exiting" << endl; return 1; } progressDisplay->startSubtask("Photometric Optimization", 0.0); // first, ensure that vignetting and response coefficients are linked const HuginBase::ImageVariableGroup::ImageVariableEnum vars[] = { HuginBase::ImageVariableGroup::IVE_EMoRParams, HuginBase::ImageVariableGroup::IVE_ResponseType, HuginBase::ImageVariableGroup::IVE_VigCorrMode, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCoeff, HuginBase::ImageVariableGroup::IVE_RadialVigCorrCenterShift }; HuginBase::StandardImageVariableGroups variable_groups(pano); HuginBase::ImageVariableGroup & lenses = variable_groups.getLenses(); for (size_t i = 0; i < lenses.getNumberOfParts(); i++) { std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> links_needed; links_needed.clear(); for (int v = 0; v < 5; v++) { if (!lenses.getVarLinkedInPart(vars[v], i)) { links_needed.insert(vars[v]); } }; if (!links_needed.empty()) { std::set<HuginBase::ImageVariableGroup::ImageVariableEnum>::iterator it; for (it = links_needed.begin(); it != links_needed.end(); it++) { lenses.linkVariablePart(*it, i); } } } HuginBase::SmartPhotometricOptimizer::PhotometricOptimizeMode optmode = HuginBase::SmartPhotometricOptimizer::OPT_PHOTOMETRIC_LDR; if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) { optmode = HuginBase::SmartPhotometricOptimizer::OPT_PHOTOMETRIC_HDR; } SmartPhotometricOptimizer photoOpt(pano, progressDisplay, pano.getOptimizeVector(), points, optmode); photoOpt.run(); // calculate the mean exposure. opts.outputExposureValue = CalculateMeanExposure::calcMeanExposure(pano); pano.setOptions(opts); progressDisplay->finishSubtask(); delete progressDisplay; }; // write result OptimizeVector optvec = pano.getOptimizeVector(); UIntSet imgs; fill_set(imgs,0, pano.getNrOfImages()-1); if (output != "") { ofstream of(output.c_str()); pano.printPanoramaScript(of, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(scriptFile)); } else { pano.printPanoramaScript(cout, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(scriptFile)); } return 0; }
CPVector AutoPanoSiftPreAlign::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs, int nFeatures, std::vector<wxString> &keyFiles, int & ret_value, wxWindow *parent) { CPVector cps; if (imgs.size()<2) return cps; DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages()); vector<UIntSet> usedImages; usedImages.resize(pano.getNrOfImages()); if(setting.GetOption()) { //only work on not connected image pairs CPVector oldCps=pano.getCtrlPoints(); for(unsigned i=0;i<oldCps.size();i++) { if(oldCps[i].mode==ControlPoint::X_Y) { usedImages[oldCps[i].image1Nr].insert(oldCps[i].image2Nr); usedImages[oldCps[i].image2Nr].insert(oldCps[i].image1Nr); }; }; }; HuginBase::CalculateImageOverlap overlap(&pano); overlap.calculate(10); for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();it++) { UIntSet images; images.clear(); images.insert(*it); UIntSet::const_iterator it2=it; for(++it2;it2!=imgs.end();it2++) { //check if this image pair was yet used if(set_contains(usedImages[*it2],*it)) continue; //now check position if(overlap.getOverlap(*it,*it2)>0) { images.insert(*it2); }; }; if(images.size()<2) continue; //remember image pairs for later for(UIntSet::const_iterator img_it=images.begin();img_it!=images.end();img_it++) for(UIntSet::const_iterator img_it2=images.begin();img_it2!=images.end();img_it2++) usedImages[*img_it].insert(*img_it2); AutoPanoSift matcher; CPVector new_cps; if(setting.IsTwoStepDetector()) new_cps=matcher.automatch(setting, pano, images, nFeatures, keyFiles, ret_value, parent); else new_cps=matcher.automatch(setting, pano, images, nFeatures, ret_value, parent); if(new_cps.size()>0) AddControlPointsWithCheck(cps,new_cps); if(ret_value!=0) { Cleanup(setting, pano, imgs, keyFiles, parent); return cps; }; }; Cleanup(setting, pano, imgs, keyFiles, parent); return cps; };
int main(int argc, char* argv[]) { // parse arguments const char* optstring = "o:t:h"; enum { MINOVERLAP=1000 }; static struct option longOptions[] = { {"output", required_argument, NULL, 'o' }, {"template", required_argument, NULL, 't'}, {"help", no_argument, NULL, 'h' }, 0 }; int c; int optionIndex = 0; string output; string templateFile; while ((c = getopt_long (argc, argv, optstring, longOptions,&optionIndex)) != -1) { switch (c) { case 'o': output = optarg; break; case 't': templateFile = optarg; if(!hugin_utils::FileExists(templateFile)) { cerr << "Error: Template \"" << templateFile << "\" not found." << endl; return 1; }; break; case 'h': usage(argv[0]); return 0; case ':': cerr <<"Option " << longOptions[optionIndex].name << " requires a parameter" << endl; return 1; break; case '?': break; default: abort (); } } if (argc - optind == 0) { cout << "Error: No project file given." << endl; return 1; }; if (argc - optind != 1) { cout << "Error: pto_template can only work on one project file at one time" << endl; return 1; }; if (templateFile.length()==0) { cerr << "Error: No template given." << endl; return 1; }; string input=argv[optind]; // read panorama Panorama pano; ifstream prjfile(input.c_str()); if (!prjfile.good()) { cerr << "Error: could not open script : " << input << endl; return 1; } pano.setFilePrefix(hugin_utils::getPathPrefix(input)); DocumentData::ReadWriteError err = pano.readData(prjfile); if (err != DocumentData::SUCCESSFUL) { cerr << "Error while parsing panos tool script: " << input << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } if(pano.getNrOfImages()==0) { cerr << "Error: project file does not contains any image" << endl; cerr << "aborting processing" << endl; return 1; }; Panorama newPano; ifstream templateStream(templateFile.c_str()); if (!templateStream.good()) { cerr << "Error: could not open template script : " << templateFile << endl; return 1; } newPano.setFilePrefix(hugin_utils::getPathPrefix(templateFile)); err = newPano.readData(templateStream); if (err != DocumentData::SUCCESSFUL) { cerr << "Error while parsing template script: " << templateFile << endl; cerr << "DocumentData::ReadWriteError code: " << err << endl; return 1; } if (pano.getNrOfImages() != newPano.getNrOfImages()) { cerr << "Error: template expects " << newPano.getNrOfImages() << " images," << endl << " current project contains " << pano.getNrOfImages() << " images" << endl << " Could not apply template" << endl; return false; } // check image sizes, and correct parameters if required. for (unsigned int i = 0; i < newPano.getNrOfImages(); i++) { // check if image size is correct const SrcPanoImage & oldSrcImg = pano.getImage(i); SrcPanoImage newSrcImg = newPano.getSrcImage(i); // just keep the file name newSrcImg.setFilename(oldSrcImg.getFilename()); if (oldSrcImg.getSize() != newSrcImg.getSize()) { // adjust size properly. newSrcImg.resize(oldSrcImg.getSize()); } newPano.setSrcImage(i, newSrcImg); } // keep old control points. newPano.setCtrlPoints(pano.getCtrlPoints()); //write output UIntSet imgs; fill_set(imgs, 0, newPano.getNrOfImages()-1); // Set output .pto filename if not given if (output=="") { output=input.substr(0,input.length()-4).append("_template.pto"); } ofstream of(output.c_str()); newPano.printPanoramaScript(of, newPano.getOptimizeVector(), newPano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input)); cout << endl << "Written output to " << output << endl; return 0; }