CPVector AutoPanoSiftMultiRow::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs, int nFeatures, int & ret_value, wxWindow *parent) { CPVector cps; if (imgs.size() < 2) { return cps; }; std::vector<wxString> keyFiles(pano.getNrOfImages()); //generate cp for every consecutive image pair unsigned int counter=0; for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ) { if(counter==imgs.size()-1) break; counter++; UIntSet ImagePair; ImagePair.clear(); ImagePair.insert(*it); it++; ImagePair.insert(*it); AutoPanoSift matcher; CPVector new_cps; new_cps.clear(); if(setting.IsTwoStepDetector()) new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, keyFiles, ret_value, parent); else new_cps=matcher.automatch(setting, pano, ImagePair, 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; }; }; // now connect all image groups // generate temporary panorama to add all found cps UIntSet allImgs; fill_set(allImgs, 0, pano.getNrOfImages()-1); Panorama optPano=pano.getSubset(allImgs); for (CPVector::const_iterator it=cps.begin();it!=cps.end();++it) optPano.addCtrlPoint(*it); CPGraph graph; createCPGraph(optPano, graph); CPComponents comps; int n = findCPComponents(graph, comps); if(n>1) { UIntSet ImagesGroups; for(unsigned int i=0;i<n;i++) { ImagesGroups.insert(*(comps[i].begin())); if(comps[i].size()>1) ImagesGroups.insert(*(comps[i].rbegin())); }; AutoPanoSift matcher; CPVector new_cps; if(setting.IsTwoStepDetector()) new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, keyFiles, ret_value, parent); else new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, ret_value, parent); if(new_cps.size()>0) AddControlPointsWithCheck(cps,new_cps,&optPano); if(ret_value!=0) { Cleanup(setting, pano, imgs, keyFiles, parent); return cps; }; createCPGraph(optPano,graph); n=findCPComponents(graph, comps); }; if(n==1 && setting.GetOption()) { //next steps happens only when all images are connected; //now optimize panorama PanoramaOptions opts = pano.getOptions(); opts.setProjection(PanoramaOptions::EQUIRECTANGULAR); // calculate proper scaling, 1:1 resolution. // Otherwise optimizer distances are meaningless. opts.setWidth(30000, false); opts.setHeight(15000); optPano.setOptions(opts); int w = optPano.calcOptimalWidth(); opts.setWidth(w); opts.setHeight(w/2); optPano.setOptions(opts); //generate optimize vector, optimize only yaw and pitch OptimizeVector optvars; const SrcPanoImage & anchorImage = optPano.getImage(opts.optimizeReferenceImage); for (unsigned i=0; i < optPano.getNrOfImages(); i++) { std::set<std::string> imgopt; if(i==opts.optimizeReferenceImage) { //optimize only anchors pitch, not yaw imgopt.insert("p"); } else { // do not optimize anchor image's stack for position. if(!optPano.getImage(i).YawisLinkedWith(anchorImage)) { imgopt.insert("p"); imgopt.insert("y"); }; }; optvars.push_back(imgopt); } optPano.setOptimizeVector(optvars); // remove vertical and horizontal control points CPVector backupOldCPS = optPano.getCtrlPoints(); CPVector backupNewCPS; for (CPVector::const_iterator it = backupOldCPS.begin(); it != backupOldCPS.end(); it++) { if (it->mode == ControlPoint::X_Y) { backupNewCPS.push_back(*it); } } optPano.setCtrlPoints(backupNewCPS); // do a first pairwise optimisation step HuginBase::AutoOptimise::autoOptimise(optPano,false); HuginBase::PTools::optimize(optPano); optPano.setCtrlPoints(backupOldCPS); //and find cp on overlapping images //work only on image pairs, which are not yet connected AutoPanoSiftPreAlign matcher; CPDetectorSetting newSetting; newSetting.SetProg(setting.GetProg()); newSetting.SetArgs(setting.GetArgs()); if(setting.IsTwoStepDetector()) { newSetting.SetProgMatcher(setting.GetProgMatcher()); newSetting.SetArgsMatcher(setting.GetArgsMatcher()); }; newSetting.SetOption(true); CPVector new_cps; if(setting.IsTwoStepDetector()) new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, keyFiles, ret_value, parent); else new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, ret_value, parent); if(new_cps.size()>0) AddControlPointsWithCheck(cps,new_cps); }; Cleanup(setting, pano, imgs, keyFiles, parent); return cps; };
CPVector AutoPanoSiftMultiRowStack::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs, int nFeatures, int & ret_value, wxWindow *parent) { CPVector cps; if (imgs.size() == 0) { return cps; }; std::vector<stack_img> stack_images; HuginBase::StandardImageVariableGroups* variable_groups = new HuginBase::StandardImageVariableGroups(pano); for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); it++) { unsigned int stack_nr=variable_groups->getStacks().getPartNumber(*it); //check, if this stack is already in list bool found=false; unsigned int index=0; for(index=0;index<stack_images.size();index++) { found=(stack_images[index].layer_nr==stack_nr); if(found) break; }; if(!found) { //new stack stack_images.resize(stack_images.size()+1); index=stack_images.size()-1; //add new stack stack_images[index].layer_nr=stack_nr; }; //add new image unsigned int new_image_index=stack_images[index].images.size(); stack_images[index].images.resize(new_image_index+1); stack_images[index].images[new_image_index].img_nr=*it; stack_images[index].images[new_image_index].ev=pano.getImage(*it).getExposure(); }; delete variable_groups; //get image with median exposure for search with cp generator UIntSet images_layer; for(unsigned int i=0;i<stack_images.size();i++) { std::sort(stack_images[i].images.begin(),stack_images[i].images.end(),sort_img_ev); unsigned int index=0; if(stack_images[i].images[0].ev!=stack_images[i].images[stack_images[i].images.size()-1].ev) { index=stack_images[i].images.size() / 2; }; images_layer.insert(stack_images[i].images[index].img_nr); }; ret_value=0; //work on all stacks if(!setting.GetProgStack().IsEmpty()) { CPDetectorSetting stack_setting; stack_setting.SetType(CPDetector_AutoPanoSift); stack_setting.SetProg(setting.GetProgStack()); stack_setting.SetArgs(setting.GetArgsStack()); for(unsigned int i=0;i<stack_images.size();i++) { UIntSet images_stack; images_stack.clear(); for(unsigned int j=0;j<stack_images[i].images.size();j++) images_stack.insert(stack_images[i].images[j].img_nr); if(images_stack.size()>1) { AutoPanoSift matcher; CPVector new_cps=matcher.automatch(stack_setting, pano, images_stack, nFeatures, ret_value, parent); if(new_cps.size()>0) AddControlPointsWithCheck(cps,new_cps); if(ret_value!=0) { std::vector<wxString> emptyKeyfiles; Cleanup(setting, pano, imgs, emptyKeyfiles, parent); return cps; }; }; }; } //generate cp for median exposure with multi-row algorithm if(images_layer.size()>1) { UIntSet allImgs; fill_set(allImgs, 0, pano.getNrOfImages()-1); Panorama newPano=pano.getSubset(allImgs); if(cps.size()>0) for (CPVector::const_iterator it=cps.begin();it!=cps.end();++it) newPano.addCtrlPoint(*it); AutoPanoSiftMultiRow matcher; CPVector new_cps=matcher.automatch(setting, newPano, images_layer, nFeatures, ret_value, parent); if(new_cps.size()>0) AddControlPointsWithCheck(cps,new_cps); }; return cps; };