AutoCtrlPointCreator.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00025 #include <config.h>
00026 
00027 #include "panoinc_WX.h"
00028 #include "panoinc.h"
00029 
00030 #include <fstream>
00031 #ifdef __GNUC__
00032 #include <ext/stdio_filebuf.h>
00033 #endif
00034 
00035 #include "algorithms/optimizer/ImageGraph.h"
00036 
00037 #include <hugin_utils/platform.h>
00038 #include <wx/app.h>
00039 #include "hugin/config_defaults.h"
00040 #include "panodata/StandardImageVariableGroups.h"
00041 #include "icpfind/AutoCtrlPointCreator.h"
00042 #include <algorithms/optimizer/PTOptimizer.h>
00043 #include <algorithms/basic/CalculateOverlap.h>
00044 #include <algorithms/basic/CalculateOptimalScale.h>
00045 
00046 #include "base_wx/MyExternalCmdExecDialog.h"
00047 #include "base_wx/platform.h"
00048 #include "base_wx/huginConfig.h"
00049 #include "base_wx/wxPlatform.h"
00050 #include <wx/utils.h>
00051 #ifdef __WXMSW__
00052 #include <wx/stdpaths.h>
00053 #endif
00054 
00055 // somewhere SetDesc gets defined.. this breaks wx/cmdline.h on OSX
00056 #ifdef SetDesc
00057 #undef SetDesc
00058 #endif
00059 
00060 #include <wx/cmdline.h>
00061 
00062 #if defined MAC_SELF_CONTAINED_BUNDLE
00063   #include <wx/dir.h>
00064   #include <CoreFoundation/CFBundle.h>
00065 #endif
00066 
00067 using namespace std;
00068 using namespace HuginBase;
00069 using namespace hugin_utils;
00070 
00071 void CPMessage(const wxString message,const wxString caption, wxWindow *parent)
00072 {
00073     if(parent!=NULL)
00074     {
00075         wxMessageBox(message,caption,wxOK | wxICON_ERROR,parent);
00076     }
00077     else
00078     {
00079         std::cout << message << std::endl;
00080     }
00081 };
00082 
00083 int CPExecute(wxString prog, wxString args, wxString caption, wxWindow *parent)
00084 {
00085     if(parent!=NULL)
00086     {
00087         return MyExecuteCommandOnDialog(prog, args, parent,  caption);
00088     }
00089     else
00090     {
00091         wxString cmdline=prog+wxT(" ")+args;
00092         return wxExecute(cmdline,wxEXEC_SYNC | wxEXEC_MAKE_GROUP_LEADER);
00093     };
00094 };
00095 
00096 HuginBase::CPVector AutoCtrlPointCreator::readUpdatedControlPoints(const std::string & file,
00097                                                     HuginBase::Panorama & pano, const HuginBase::UIntSet & imgs, bool reordered)
00098 {
00099     ifstream stream(file.c_str());
00100     if (! stream.is_open()) {
00101         DEBUG_ERROR("Could not open control point detector output: " << file);
00102         return HuginBase::CPVector();
00103     }
00104 
00105     Panorama tmpp;
00106     HuginBase::PanoramaMemento newPano;
00107     int ptoVersion = 0;
00108     newPano.loadPTScript(stream, ptoVersion, "");
00109     tmpp.setMemento(newPano);
00110 
00111     //check if sizes matches
00112     if(tmpp.getNrOfImages()!=imgs.size())
00113     {
00114         return HuginBase::CPVector();
00115     };
00116 
00117     // create mapping between the panorama images.
00118     map<unsigned int, unsigned int> imgMapping;
00119 
00120     // create mapping between the panorama images.
00121     if (reordered) {
00122         for (unsigned int ni = 0; ni < tmpp.getNrOfImages(); ni++) {
00123             std::string nname = stripPath(tmpp.getImage(ni).getFilename());
00124             for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();++it) {
00125                 std::string oname = stripPath(pano.getImage(*it).getFilename());
00126                 if (nname == oname) {
00127                     // insert image
00128                     imgMapping[ni] = *it;
00129                     break;
00130                 }
00131             }
00132             if (! set_contains(imgMapping, ni)) {
00133                 DEBUG_ERROR("Could not find image " << ni << ", name: " << tmpp.getImage(ni).getFilename() << " in autopano output");
00134                 return HuginBase::CPVector();
00135             }
00136         }
00137     } else {
00138         size_t i=0;
00139         for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();++it)
00140         {
00141             imgMapping[i++]=*it;
00142         };
00143     }
00144     
00145     // get control points
00146     HuginBase::CPVector ctrlPoints = tmpp.getCtrlPoints();
00147     // make sure they are in correct order
00148     for (HuginBase::CPVector::iterator it = ctrlPoints.begin(); it != ctrlPoints.end(); ++it) {
00149         (*it).image1Nr = imgMapping[(*it).image1Nr];
00150         (*it).image2Nr = imgMapping[(*it).image2Nr];
00151     }
00152 
00153     return ctrlPoints;
00154 }
00155 
00156 #if defined MAC_SELF_CONTAINED_BUNDLE
00157 wxString GetBundledProg(wxString progName)
00158 {
00159     // First check inside the bundle for (AutoCP generator "without path"), e.g. binary name with path stripped off
00160     wxFileName file(progName);
00161     // if executable contains no path, look inside bundle, if program can be found there
00162     if(file.GetPath().IsEmpty())
00163         //return MacGetPathToBundledResourceFile(MacCreateCFStringWithWxString(progName));
00164         return MacGetPathToBundledExecutableFile(MacCreateCFStringWithWxString(progName));
00165     return wxEmptyString;
00166 }
00167 #endif
00168 
00169 wxString GetProgPath(wxString progName)
00170 {
00171 #if defined MAC_SELF_CONTAINED_BUNDLE
00172     wxString bundled=GetBundledProg(progName);
00173     if(!bundled.IsEmpty())
00174         return bundled;
00175 #else 
00176 #ifdef __WXMSW__
00177     wxFileName prog(progName);
00178     if(prog.IsAbsolute())
00179     {
00180         return progName;
00181     }
00182     else
00183     {
00184         wxPathList pathlist;
00185         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
00186         pathlist.Add(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
00187         pathlist.AddEnvList(wxT("PATH"));
00188         return pathlist.FindAbsoluteValidPath(progName);
00189     };
00190 #endif
00191 #endif
00192     return progName;
00193 };
00194 
00195 bool CanStartProg(wxString progName,wxWindow* parent)
00196 {
00197 #if defined MAC_SELF_CONTAINED_BUNDLE
00198     if(!GetBundledProg(progName).IsEmpty())
00199         return true;
00200 #endif
00201     wxFileName prog(progName);
00202     bool canStart=false; 
00203     if(prog.IsAbsolute())
00204     {
00205         canStart=(prog.IsFileExecutable());
00206     }
00207     else
00208     {
00209         wxPathList pathlist;
00210 #ifdef __WXMSW__
00211         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
00212         pathlist.Add(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR));
00213 #endif
00214         pathlist.AddEnvList(wxT("PATH"));
00215         wxString path = pathlist.FindAbsoluteValidPath(progName);
00216         if(path.IsEmpty())
00217             canStart=false;
00218         else
00219         {
00220             wxFileName prog2(path);
00221             canStart=(prog2.IsFileExecutable());
00222         };
00223     };
00224     if(!canStart)
00225         CPMessage(wxString::Format(
00226         _("Could not find \"%s\" in path.\nMaybe you have not installed it properly or given a wrong path in the settings."),progName.c_str()),
00227             _("Error"),parent);
00228     return canStart;
00229 };
00230 
00231 HuginBase::CPVector AutoCtrlPointCreator::automatch(CPDetectorSetting &setting, HuginBase::Panorama & pano, const HuginBase::UIntSet & imgs,
00232                            int nFeatures, wxWindow *parent)
00233 {
00234     int return_value;
00235     return automatch(setting,pano,imgs,nFeatures,return_value,parent);
00236 };
00237 
00238 HuginBase::CPVector AutoCtrlPointCreator::automatch(CPDetectorSetting &setting,
00239                                          Panorama & pano,
00240                                          const UIntSet & imgs,
00241                                          int nFeatures,
00242                                          int & ret_value, 
00243                                          wxWindow *parent)
00244 {
00245     HuginBase::CPVector cps;
00246     CPDetectorType t = setting.GetType();
00247     //check, if the cp generators exists
00248     if(!CanStartProg(setting.GetProg(),parent))
00249         return cps;
00250     if(setting.IsTwoStepDetector())
00251         if(!CanStartProg(setting.GetProgMatcher(),parent))
00252             return cps;
00253     if(t==CPDetector_AutoPanoSiftStack || t==CPDetector_AutoPanoSiftMultiRowStack)
00254         if(!setting.GetProgStack().IsEmpty())
00255             if(!CanStartProg(setting.GetProgStack(),parent))
00256                 return cps;
00257     //change locale for correct numeric output
00258     char * p = setlocale(LC_NUMERIC,NULL);
00259     char * old_locale = strdup(p);
00260     setlocale(LC_NUMERIC,"C");
00261     switch (t) {
00262     case CPDetector_AutoPano:
00263         {
00264             // autopano@kolor
00265             AutoPanoKolor matcher;
00266             cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00267             break;
00268         }
00269     case CPDetector_AutoPanoSift:
00270         {
00271             // autopano-sift
00272             AutoPanoSift matcher;
00273             cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00274             break;
00275         }
00276     case CPDetector_AutoPanoSiftStack:
00277     {
00278         // autopano-sift with stacks
00279         AutoPanoSiftStack matcher;
00280         cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00281         break;
00282     }
00283     case CPDetector_AutoPanoSiftMultiRow:
00284     {
00285         // autopano-sift for multi-row panoramas
00286         AutoPanoSiftMultiRow matcher;
00287         cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00288         break;
00289     }
00290     case CPDetector_AutoPanoSiftMultiRowStack:
00291     {
00292         // autopano-sift for multi-row panoramas with stacks
00293         AutoPanoSiftMultiRowStack matcher;
00294         cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00295         break;
00296     }
00297     case CPDetector_AutoPanoSiftPreAlign:
00298     {
00299         // autopano-sift for panoramas with position information
00300         AutoPanoSiftPreAlign matcher;
00301         cps = matcher.automatch(setting, pano, imgs, nFeatures, ret_value, parent);
00302         break;
00303     }
00304         default:
00305             DEBUG_ERROR("Invalid autopano type");
00306     }
00307     setlocale(LC_NUMERIC,old_locale);
00308     free(old_locale);
00309     return cps;
00310 }
00311 
00312 void AutoCtrlPointCreator::Cleanup(CPDetectorSetting &setting, HuginBase::Panorama & pano, const HuginBase::UIntSet & imgs,
00313                            std::vector<wxString> &keyFiles, wxWindow *parent)
00314 {
00315     if(setting.IsTwoStepDetector())
00316     {
00317         if(keyFiles.size()>0)
00318         {
00319             for(unsigned int i=0;i<keyFiles.size();i++)
00320             {
00321                 if(wxFileExists(keyFiles[i]))
00322                 {
00323                     if(!wxRemoveFile(keyFiles[i]))
00324                     {
00325                         DEBUG_DEBUG("could not remove temporary file: " << keyFiles[i].c_str());
00326                     };
00327                 };
00328             };
00329         };
00330     }
00331     else
00332     {
00333         if(!setting.IsCleanupPossible())
00334         {
00335             return;
00336         };
00337         // create suitable command line..
00338         wxString cleanupExe = GetProgPath(setting.GetProg());
00339         wxString cleanupArgs = setting.GetArgsCleanup();
00340         if(cleanupArgs.IsEmpty())
00341         {
00342             return;
00343         };
00344     
00345         wxString ptoinfile_name = wxFileName::CreateTempFileName(wxT("ap_inproj"));
00346         cleanupArgs.Replace(wxT("%s"), ptoinfile_name);
00347         ofstream ptoinstream(ptoinfile_name.mb_str(wxConvFile));
00348         pano.printPanoramaScript(ptoinstream, pano.getOptimizeVector(), pano.getOptions(), imgs, false);
00349 
00350         int ret_value=CPExecute(cleanupExe, cleanupArgs, _("cleaning up temporary keypoint files"), parent);
00351 
00352         if(ret_value!=0)
00353         {
00354             DEBUG_DEBUG("could not cleanup temporary keypoint files");
00355         };
00356         if(!wxRemoveFile(ptoinfile_name))
00357         {
00358             DEBUG_DEBUG("could not remove temporary file: " << ptoinfile_name.c_str());
00359         };
00360     };
00361 };
00362         
00363 HuginBase::CPVector AutoPanoSift::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
00364                                      int nFeatures, int & ret_value, wxWindow *parent)
00365 {
00366     HuginBase::CPVector cps;
00367     if (imgs.size() == 0) {
00368         return cps;
00369     }
00370     // create suitable command line..
00371     wxString autopanoExe = GetProgPath(setting.GetProg());
00372     if(setting.IsTwoStepDetector())
00373     {
00374         std::vector<wxString> keyFiles(pano.getNrOfImages());
00375         cps=automatch(setting, pano, imgs, nFeatures, keyFiles, ret_value, parent);
00376         Cleanup(setting, pano, imgs, keyFiles, parent);
00377         return cps;
00378     };
00379     wxString autopanoArgs = setting.GetArgs();
00380     
00381     // TODO: create a secure temporary filename here
00382     wxString ptofile = wxFileName::CreateTempFileName(wxT("ap_res"));
00383     autopanoArgs.Replace(wxT("%o"), ptofile);
00384     wxString tmp;
00385     tmp.Printf(wxT("%d"), nFeatures);
00386     autopanoArgs.Replace(wxT("%p"), tmp);
00387 
00388     SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
00389     tmp.Printf(wxT("%f"), firstImg.getHFOV());
00390     autopanoArgs.Replace(wxT("%v"), tmp);
00391 
00392     tmp.Printf(wxT("%d"), (int) firstImg.getProjection());
00393     autopanoArgs.Replace(wxT("%f"), tmp);
00394 
00395     long idx = autopanoArgs.Find(wxT("%namefile")) ;
00396     DEBUG_DEBUG("find %namefile in '"<< autopanoArgs.mb_str(wxConvLocal) << "' returned: " << idx);
00397     bool use_namefile = idx >=0;
00398     idx = autopanoArgs.Find(wxT("%i"));
00399     DEBUG_DEBUG("find %i in '"<< autopanoArgs.mb_str(wxConvLocal) << "' returned: " << idx);
00400     bool use_params = idx >=0;
00401     idx = autopanoArgs.Find(wxT("%s"));
00402     bool use_inputscript = idx >=0;
00403 
00404     if (! (use_namefile || use_params || use_inputscript)) {
00405         CPMessage(_("Please use %namefile, %i or %s to specify the input files for the control point detector"),
00406                      _("Error in control point detector command"), parent);
00407         return cps;
00408     }
00409 
00410     wxFile namefile;
00411     wxString namefile_name;
00412     if (use_namefile) {
00413         // create temporary file with image names.
00414         namefile_name = wxFileName::CreateTempFileName(wxT("ap_imgnames"), &namefile);
00415         DEBUG_DEBUG("before replace %namefile: " << autopanoArgs.mb_str(wxConvLocal));
00416         autopanoArgs.Replace(wxT("%namefile"), namefile_name);
00417         DEBUG_DEBUG("after replace %namefile: " << autopanoArgs.mb_str(wxConvLocal));
00418         for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
00419         {
00420             namefile.Write(wxString(pano.getImage(*it).getFilename().c_str(), HUGIN_CONV_FILENAME));
00421             namefile.Write(wxT("\r\n"));
00422         }
00423         // close namefile
00424         if (namefile_name != wxString(wxT(""))) {
00425             namefile.Close();
00426         }
00427     } else {
00428         string imgFiles;
00429         for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
00430         {
00431             imgFiles.append(" ").append(quoteFilename(pano.getImage(*it).getFilename()));
00432         }
00433         autopanoArgs.Replace(wxT("%i"), wxString (imgFiles.c_str(), HUGIN_CONV_FILENAME));
00434     }
00435 
00436     wxString ptoinfile_name;
00437     if (use_inputscript) {
00438         wxFile ptoinfile;
00439         ptoinfile_name = wxFileName::CreateTempFileName(wxT("ap_inproj"));
00440         autopanoArgs.Replace(wxT("%s"), ptoinfile_name);
00441 
00442         ofstream ptoinstream(ptoinfile_name.mb_str(wxConvFile));
00443         //delete all existing control points in temp project
00444         //otherwise the existing control points will be loaded again
00445         Panorama tempPano=pano.duplicate();
00446         HuginBase::CPVector emptyCPV;
00447         tempPano.setCtrlPoints(emptyCPV);
00448         tempPano.printPanoramaScript(ptoinstream, tempPano.getOptimizeVector(), tempPano.getOptions(), imgs, false);
00449     }
00450 
00451 #ifdef __WXMSW__
00452     if (autopanoArgs.size() > 32000) {
00453         CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
00454                      _("Too many images selected"), parent );
00455         return cps;
00456     }
00457 #endif
00458 
00459     wxString cmd = autopanoExe + wxT(" ") + autopanoArgs;
00460     DEBUG_DEBUG("Executing: " << autopanoExe.mb_str(wxConvLocal) << " " << autopanoArgs.mb_str(wxConvLocal));
00461 
00462     wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(autopanoArgs);
00463     if (arguments.GetCount() > 127) {
00464         DEBUG_ERROR("Too many arguments for call to wxExecute()");
00465         DEBUG_ERROR("Try using the %%s parameter in preferences");
00466         CPMessage(wxString::Format(_("Too many arguments (images). Try using the %%s parameter in preferences.\n\n Could not execute command: %s"), autopanoExe.c_str()), _("wxExecute Error"), parent);
00467         return cps;
00468     }
00469 
00470     ret_value = 0;
00471     // use MyExternalCmdExecDialog
00472     ret_value = CPExecute(autopanoExe, autopanoArgs, _("finding control points"), parent);
00473 
00474     if (ret_value == HUGIN_EXIT_CODE_CANCELLED) {
00475         return cps;
00476     } else if (ret_value == -1) {
00477         CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
00478         return cps;
00479     } else if (ret_value > 0) {
00480         CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
00481                      _("wxExecute Error"), parent);
00482         return cps;
00483     }
00484 
00485     if (! wxFileExists(ptofile.c_str())) {
00486         CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
00487                      _("Control point detector failure"), parent );
00488         return cps;
00489     }
00490 
00491     // read and update control points
00492     cps = readUpdatedControlPoints((const char*)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, !use_inputscript);
00493 
00494     if (namefile_name != wxString(wxT(""))) {
00495         namefile.Close();
00496         wxRemoveFile(namefile_name);
00497     }
00498 
00499     if (ptoinfile_name != wxString(wxT(""))) {
00500         wxRemoveFile(ptoinfile_name);
00501     }
00502 
00503     if (!wxRemoveFile(ptofile)) {
00504         DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
00505     }
00506 
00507     return cps;
00508 }
00509 
00510 HuginBase::CPVector AutoPanoSift::automatch(CPDetectorSetting &setting, HuginBase::Panorama & pano, const HuginBase::UIntSet & imgs,
00511                            int nFeatures, vector<wxString> &keyFiles, int & ret_value, wxWindow *parent)
00512 {
00513     HuginBase::CPVector cps;
00514     if (imgs.size() == 0) 
00515     {
00516         return cps;
00517     }
00518     DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages());
00519     // create suitable command line..
00520     wxString generateKeysExe=GetProgPath(setting.GetProg());
00521     wxString matcherExe = GetProgPath(setting.GetProgMatcher());
00522     wxString generateKeysArgs=setting.GetArgs();
00523     wxString matcherArgs = setting.GetArgsMatcher();
00524     
00525     wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
00526     if(!tempDir.IsEmpty())
00527         if(tempDir.Last()!=wxFileName::GetPathSeparator())
00528             tempDir.Append(wxFileName::GetPathSeparator());
00529     //check arguments
00530     if(generateKeysArgs.Find(wxT("%i"))==wxNOT_FOUND || generateKeysArgs.Find(wxT("%k"))==wxNOT_FOUND)
00531     {
00532         CPMessage(_("Please use %i to specify the input files and %k to specify the keypoint file for the generate keys step"),
00533                      _("Error in control point detector command"), parent);
00534         return cps;
00535     };
00536     if(matcherArgs.Find(wxT("%k"))==wxNOT_FOUND || matcherArgs.Find(wxT("%o"))==wxNOT_FOUND)
00537     {
00538         CPMessage(_("Please use %k to specify the keypoint files and %o to specify the output project file for the matching step"),
00539                      _("Error in control point detector command"), parent);
00540         return cps;
00541     };
00542 
00543     ret_value=0;
00544     for(UIntSet::const_iterator img=imgs.begin();img!=imgs.end();++img)
00545     {
00546         if(keyFiles[*img].IsEmpty())
00547         {
00548             //no key files exists, so generate it
00549             wxString keyfile=wxFileName::CreateTempFileName(tempDir+wxT("apk_"));
00550             keyFiles[*img]=keyfile;
00551             wxString cmd=generateKeysArgs;
00552             wxString tmp;
00553             tmp.Printf(wxT("%d"), nFeatures);
00554             cmd.Replace(wxT("%p"), tmp);
00555 
00556             SrcPanoImage srcImg = pano.getSrcImage(*img);
00557             tmp.Printf(wxT("%f"), srcImg.getHFOV());
00558             cmd.Replace(wxT("%v"), tmp);
00559 
00560             tmp.Printf(wxT("%d"), (int) srcImg.getProjection());
00561             cmd.Replace(wxT("%f"), tmp);
00562             
00563             cmd.Replace(wxT("%i"),wxQuoteFilename(wxString(srcImg.getFilename().c_str(), HUGIN_CONV_FILENAME)));
00564             cmd.Replace(wxT("%k"),wxQuoteFilename(keyfile));
00565             // use MyExternalCmdExecDialog
00566             ret_value = CPExecute(generateKeysExe, cmd, _("generating key file"), parent);
00567             cmd=generateKeysExe+wxT(" ")+cmd;
00568             if (ret_value == HUGIN_EXIT_CODE_CANCELLED) 
00569                 return cps;
00570             else
00571                 if (ret_value == -1) 
00572                 {
00573                     CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
00574                     return cps;
00575                 } 
00576                 else
00577                     if (ret_value > 0) 
00578                     {
00579                         CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
00580                             _("wxExecute Error"), parent);
00581                         return cps;
00582                     };
00583         };
00584     };
00585 
00586     // TODO: create a secure temporary filename here
00587     wxString ptofile = wxFileName::CreateTempFileName(wxT("ap_res"));
00588     matcherArgs.Replace(wxT("%o"), ptofile);
00589     wxString tmp;
00590     tmp.Printf(wxT("%d"), nFeatures);
00591     matcherArgs.Replace(wxT("%p"), tmp);
00592 
00593     SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
00594     tmp.Printf(wxT("%f"), firstImg.getHFOV());
00595     matcherArgs.Replace(wxT("%v"), tmp);
00596 
00597     tmp.Printf(wxT("%d"), (int) firstImg.getProjection());
00598     matcherArgs.Replace(wxT("%f"), tmp);
00599 
00600     wxString imgFiles;
00601     for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
00602     {
00603         imgFiles.append(wxT(" ")).append(wxQuoteFilename(keyFiles[*it]));
00604      };
00605      matcherArgs.Replace(wxT("%k"), wxString (imgFiles.wc_str(), HUGIN_CONV_FILENAME));
00606 
00607 #ifdef __WXMSW__
00608     if (matcherArgs.size() > 32000) {
00609         CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
00610                      _("Too many images selected"), parent );
00611         return cps;
00612     }
00613 #endif
00614 
00615     wxString cmd = matcherExe + wxT(" ") + matcherArgs;
00616     DEBUG_DEBUG("Executing: " << matcherExe.mb_str(wxConvLocal) << " " << matcherArgs.mb_str(wxConvLocal));
00617 
00618     wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(matcherArgs);
00619     if (arguments.GetCount() > 127) {
00620         DEBUG_ERROR("Too many arguments for call to wxExecute()");
00621         CPMessage(wxString::Format(_("Too many arguments (images). Try using a cp generator setting which supports the %%s parameter in preferences.\n\n Could not execute command: %s"), matcherExe.c_str()), _("wxExecute Error"), parent);
00622         return cps;
00623     }
00624 
00625     // use MyExternalCmdExecDialog
00626     ret_value = CPExecute(matcherExe, matcherArgs, _("finding control points"), parent);
00627 
00628     if (ret_value == HUGIN_EXIT_CODE_CANCELLED) 
00629         return cps;
00630     else 
00631         if (ret_value == -1) 
00632         {
00633             CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"), parent);
00634             return cps;
00635         } 
00636         else
00637             if (ret_value > 0) 
00638             {
00639                 CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
00640                      _("wxExecute Error"), parent);
00641                 return cps;
00642             };
00643 
00644     if (! wxFileExists(ptofile.c_str()))
00645     {
00646         CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
00647                      _("Control point detector failure"), parent );
00648         return cps;
00649     }
00650 
00651     // read and update control points
00652     cps = readUpdatedControlPoints((const char *)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, true);
00653 
00654     if (!wxRemoveFile(ptofile)) {
00655         DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
00656     }
00657 
00658     return cps;
00659 };
00660 
00661 HuginBase::CPVector AutoPanoKolor::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
00662                               int nFeatures, int & ret_value, wxWindow *parent)
00663 {
00664     HuginBase::CPVector cps;
00665     wxString autopanoExe = setting.GetProg();
00666 
00667     // write default autopano.kolor.com flags
00668     wxString autopanoArgs = setting.GetArgs();
00669 
00670     string imgFiles;
00671     for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
00672     {
00673         imgFiles.append(" ").append(quoteFilename(pano.getImage(*it).getFilename()));
00674     }
00675 
00676     wxString ptofilepath = wxFileName::CreateTempFileName(wxT("ap_res"));
00677     wxFileName ptofn(ptofilepath);
00678     wxString ptofile = ptofn.GetFullName();
00679     autopanoArgs.Replace(wxT("%o"), ptofile);
00680     wxString tmp;
00681     tmp.Printf(wxT("%d"), nFeatures);
00682     autopanoArgs.Replace(wxT("%p"), tmp);
00683     SrcPanoImage firstImg = pano.getSrcImage(*imgs.begin());
00684     tmp.Printf(wxT("%f"), firstImg.getHFOV());
00685     autopanoArgs.Replace(wxT("%v"), tmp);
00686 
00687     tmp.Printf(wxT("%d"), (int) firstImg.getProjection());
00688     autopanoArgs.Replace(wxT("%f"), tmp);
00689 
00690     autopanoArgs.Replace(wxT("%i"), wxString (imgFiles.c_str(), HUGIN_CONV_FILENAME));
00691 
00692     wxString tempdir = ptofn.GetPath();
00693         autopanoArgs.Replace(wxT("%d"), ptofn.GetPath());
00694     wxString cmd;
00695     cmd.Printf(wxT("%s %s"), wxQuoteFilename(autopanoExe).c_str(), autopanoArgs.c_str());
00696 #ifdef __WXMSW__
00697     if (cmd.size() > 32766) {
00698         CPMessage(_("Command line for control point detector too long.\nThis is a Windows limitation\nPlease select less images, or place the images in a folder with\na shorter pathname"),
00699                      _("Too many images selected"), parent);
00700         return cps;
00701     }
00702 #endif
00703     DEBUG_DEBUG("Executing: " << cmd.c_str());
00704 
00705     wxArrayString arguments = wxCmdLineParser::ConvertStringToArgs(cmd);
00706     if (arguments.GetCount() > 127) {
00707         DEBUG_ERROR("Too many arguments for call to wxExecute()");
00708         DEBUG_ERROR("Try using the %s parameter in preferences");
00709         CPMessage(wxString::Format(_("Too many arguments (images). Try using the %%s parameter in preferences.\n\n Could not execute command: %s"), autopanoExe.c_str()), _("wxExecute Error"), parent);
00710         return cps;
00711     }
00712 
00713     ret_value = 0;
00714     // use MyExternalCmdExecDialog
00715     ret_value = CPExecute(autopanoExe, autopanoArgs, _("finding control points"), parent);
00716 
00717     if (ret_value == HUGIN_EXIT_CODE_CANCELLED) {
00718         return cps;
00719     } else if (ret_value == -1) {
00720         CPMessage( wxString::Format(_("Could not execute command: %s"),cmd.c_str()), _("wxExecute Error"),  parent);
00721         return cps;
00722     } else if (ret_value > 0) {
00723         CPMessage(wxString::Format(_("Command: %s\nfailed with error code: %d"),cmd.c_str(),ret_value),
00724                      _("wxExecute Error"), parent);
00725         return cps;
00726     }
00727 
00728     ptofile = ptofn.GetFullPath();
00729     ptofile.append(wxT("0.oto"));
00730     if (! wxFileExists(ptofile.c_str()) ) {
00731         CPMessage(wxString::Format(_("Could not open %s for reading\nThis is an indicator that the control point detector call failed,\nor incorrect command line parameters have been used.\n\nExecuted command: %s"),ptofile.c_str(),cmd.c_str()),
00732                      _("Control point detector failure"), parent );
00733         return cps;
00734     }
00735     // read and update control points
00736     cps = readUpdatedControlPoints((const char *)ptofile.mb_str(HUGIN_CONV_FILENAME), pano, imgs, true);
00737 
00738     if (!wxRemoveFile(ptofile)) {
00739         DEBUG_DEBUG("could not remove temporary file: " << ptofile.c_str());
00740     }
00741     return cps;
00742 }
00743 
00744 struct img_ev
00745 {
00746     unsigned int img_nr;
00747     double ev;
00748 };
00749 struct stack_img
00750 {
00751     unsigned int layer_nr;
00752     std::vector<img_ev> images;
00753 };
00754 bool sort_img_ev (img_ev i1, img_ev i2) { return (i1.ev<i2.ev); };
00755 
00756 void AddControlPointsWithCheck(HuginBase::CPVector &cpv, HuginBase::CPVector &new_cp, Panorama *pano = NULL)
00757 {
00758     for(unsigned int i=0;i<new_cp.size();i++)
00759     {
00760         HuginBase::ControlPoint cp=new_cp[i];
00761         bool duplicate=false;
00762         for(unsigned int j=0;j<cpv.size();j++)
00763         {
00764             if(cp==cpv[j])
00765             {
00766                 duplicate=true;
00767                 break;
00768             }
00769         };
00770         if(!duplicate)
00771         {
00772             cpv.push_back(cp);
00773             if(pano!=NULL)
00774                 pano->addCtrlPoint(cp);
00775         };
00776     };
00777 };
00778 
00779 HuginBase::CPVector AutoPanoSiftStack::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
00780                                      int nFeatures, int & ret_value, wxWindow *parent)
00781 {
00782     HuginBase::CPVector cps;
00783     if (imgs.size() == 0) {
00784         return cps;
00785     };
00786     std::vector<stack_img> stack_images;
00787     HuginBase::StandardImageVariableGroups* variable_groups = new HuginBase::StandardImageVariableGroups(pano);
00788     for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
00789     {
00790         unsigned int stack_nr=variable_groups->getStacks().getPartNumber(*it);
00791         //check, if this stack is already in list
00792         bool found=false;
00793         unsigned int index=0;
00794         for(index=0;index<stack_images.size();index++)
00795         {
00796             found=(stack_images[index].layer_nr==stack_nr);
00797             if(found)
00798                 break;
00799         };
00800         if(!found)
00801         {
00802             //new stack
00803             stack_images.resize(stack_images.size()+1);
00804             index=stack_images.size()-1;
00805             //add new stack
00806             stack_images[index].layer_nr=stack_nr;
00807         };
00808         //add new image
00809         unsigned int new_image_index=stack_images[index].images.size();
00810         stack_images[index].images.resize(new_image_index+1);
00811         stack_images[index].images[new_image_index].img_nr=*it;
00812         stack_images[index].images[new_image_index].ev=pano.getImage(*it).getExposure();
00813     };
00814     delete variable_groups;
00815     //get image with median exposure for search with cp generator
00816     UIntSet images_layer;
00817     for(unsigned int i=0;i<stack_images.size();i++)
00818     {
00819         std::sort(stack_images[i].images.begin(),stack_images[i].images.end(),sort_img_ev);
00820         unsigned int index=0;
00821         if(stack_images[i].images[0].ev!=stack_images[i].images[stack_images[i].images.size()-1].ev)
00822         {
00823             index=stack_images[i].images.size() / 2;
00824         };
00825         images_layer.insert(stack_images[i].images[index].img_nr);
00826     };
00827     //generate cp for median exposure
00828     ret_value=0;
00829     if(images_layer.size()>1)
00830     {
00831         AutoPanoSift matcher;
00832         cps=matcher.automatch(setting, pano, images_layer, nFeatures, ret_value, parent);
00833         if(ret_value!=0)
00834             return cps;
00835     };
00836     //now work on all stacks
00837     if(!setting.GetProgStack().IsEmpty())
00838     {
00839         CPDetectorSetting stack_setting;
00840         stack_setting.SetType(CPDetector_AutoPanoSift);
00841         stack_setting.SetProg(setting.GetProgStack());
00842         stack_setting.SetArgs(setting.GetArgsStack());
00843 
00844         for(unsigned int i=0;i<stack_images.size();i++)
00845         {
00846             UIntSet images_stack;
00847             images_stack.clear();
00848             for(unsigned int j=0;j<stack_images[i].images.size();j++)
00849                 images_stack.insert(stack_images[i].images[j].img_nr);
00850             if(images_stack.size()>1)
00851             {
00852                 AutoPanoSift matcher;
00853                 HuginBase::CPVector new_cps = matcher.automatch(stack_setting, pano, images_stack, nFeatures, ret_value, parent);
00854                 if(new_cps.size()>0)
00855                     AddControlPointsWithCheck(cps,new_cps);
00856                 if(ret_value!=0)
00857                     return cps;
00858             };
00859         };
00860     }
00861     return cps;
00862 };
00863 
00864 HuginBase::CPVector AutoPanoSiftMultiRow::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
00865                                      int nFeatures, int & ret_value, wxWindow *parent)
00866 {
00867     HuginBase::CPVector cps;
00868     if (imgs.size() < 2) 
00869     {
00870         return cps;
00871     };
00872     std::vector<wxString> keyFiles(pano.getNrOfImages());
00873     //generate cp for every consecutive image pair
00874     unsigned int counter=0;
00875     for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); )
00876     {
00877         if(counter==imgs.size()-1)
00878             break;
00879         counter++;
00880         UIntSet ImagePair;
00881         ImagePair.clear();
00882         ImagePair.insert(*it);
00883         ++it;
00884         ImagePair.insert(*it);
00885         AutoPanoSift matcher;
00886         HuginBase::CPVector new_cps;
00887         new_cps.clear();
00888         if(setting.IsTwoStepDetector())
00889             new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, keyFiles, ret_value, parent);
00890         else
00891             new_cps=matcher.automatch(setting, pano, ImagePair, nFeatures, ret_value, parent);
00892         if(new_cps.size()>0)
00893             AddControlPointsWithCheck(cps,new_cps);
00894         if(ret_value!=0)
00895         {
00896             Cleanup(setting, pano, imgs, keyFiles, parent);
00897             return cps;
00898         };
00899     };
00900     // now connect all image groups
00901     // generate temporary panorama to add all found cps
00902     UIntSet allImgs;
00903     fill_set(allImgs, 0, pano.getNrOfImages()-1);
00904     Panorama optPano=pano.getSubset(allImgs);
00905     for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
00906         optPano.addCtrlPoint(*it);
00907 
00908     HuginBase::CPGraph graph;
00909     HuginBase::createCPGraph(optPano, graph);
00910     HuginBase::CPComponents comps;
00911     size_t n = HuginBase::findCPComponents(graph, comps);
00912     if(n>1)
00913     {
00914         UIntSet ImagesGroups;
00915         for(size_t i=0;i<n;i++)
00916         {
00917             ImagesGroups.insert(*(comps[i].begin()));
00918             if(comps[i].size()>1)
00919                 ImagesGroups.insert(*(comps[i].rbegin()));
00920         };
00921         AutoPanoSift matcher;
00922         HuginBase::CPVector new_cps;
00923         if(setting.IsTwoStepDetector())
00924             new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, keyFiles, ret_value, parent);
00925         else
00926             new_cps=matcher.automatch(setting, optPano, ImagesGroups, nFeatures, ret_value, parent);
00927         if(new_cps.size()>0)
00928             AddControlPointsWithCheck(cps,new_cps,&optPano);
00929         if(ret_value!=0)
00930         {
00931             Cleanup(setting, pano, imgs, keyFiles, parent);
00932             return cps;
00933         };
00934         HuginBase::createCPGraph(optPano,graph);
00935         n=HuginBase::findCPComponents(graph, comps);
00936     };
00937     if(n==1 && setting.GetOption())
00938     {
00939         //next steps happens only when all images are connected;
00940         //now optimize panorama
00941         HuginBase::PanoramaOptions opts = pano.getOptions();
00942         opts.setProjection(HuginBase::PanoramaOptions::EQUIRECTANGULAR);
00943         // calculate proper scaling, 1:1 resolution.
00944         // Otherwise optimizer distances are meaningless.
00945         opts.setWidth(30000, false);
00946         opts.setHeight(15000);
00947 
00948         optPano.setOptions(opts);
00949         int w = hugin_utils::roundi(HuginBase::CalculateOptimalScale::calcOptimalScale(optPano) * optPano.getOptions().getWidth());
00950 
00951         opts.setWidth(w);
00952         opts.setHeight(w/2);
00953         optPano.setOptions(opts);
00954 
00955         //generate optimize vector, optimize only yaw and pitch
00956         HuginBase::OptimizeVector optvars;
00957         const SrcPanoImage & anchorImage = optPano.getImage(opts.optimizeReferenceImage);
00958         for (unsigned i=0; i < optPano.getNrOfImages(); i++) 
00959         {
00960             std::set<std::string> imgopt;
00961             if(i==opts.optimizeReferenceImage)
00962             {
00963                 //optimize only anchors pitch, not yaw
00964                 imgopt.insert("p");
00965             }
00966             else
00967             {
00968                 // do not optimize anchor image's stack for position.
00969                 if(!optPano.getImage(i).YawisLinkedWith(anchorImage))
00970                 {
00971                     imgopt.insert("p");
00972                     imgopt.insert("y");
00973                 };
00974             };
00975             optvars.push_back(imgopt);
00976         }
00977         optPano.setOptimizeVector(optvars);
00978 
00979         // remove vertical and horizontal control points
00980         HuginBase::CPVector backupOldCPS = optPano.getCtrlPoints();
00981         HuginBase::CPVector backupNewCPS;
00982         for (HuginBase::CPVector::const_iterator it = backupOldCPS.begin(); it != backupOldCPS.end(); ++it) {
00983             if (it->mode == HuginBase::ControlPoint::X_Y)
00984             {
00985                 backupNewCPS.push_back(*it);
00986             }
00987         }
00988         optPano.setCtrlPoints(backupNewCPS);
00989         // do a first pairwise optimisation step
00990         HuginBase::AutoOptimise::autoOptimise(optPano,false);
00991         HuginBase::PTools::optimize(optPano);
00992         optPano.setCtrlPoints(backupOldCPS);
00993         //and find cp on overlapping images
00994         //work only on image pairs, which are not yet connected
00995         AutoPanoSiftPreAlign matcher;
00996         CPDetectorSetting newSetting;
00997         newSetting.SetProg(setting.GetProg());
00998         newSetting.SetArgs(setting.GetArgs());
00999         if(setting.IsTwoStepDetector())
01000         {
01001             newSetting.SetProgMatcher(setting.GetProgMatcher());
01002             newSetting.SetArgsMatcher(setting.GetArgsMatcher());
01003         };
01004         newSetting.SetOption(true);
01005         HuginBase::CPVector new_cps;
01006         if(setting.IsTwoStepDetector())
01007             new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, keyFiles, ret_value, parent);
01008         else
01009             new_cps=matcher.automatch(newSetting, optPano, imgs, nFeatures, ret_value, parent);
01010         if(new_cps.size()>0)
01011             AddControlPointsWithCheck(cps,new_cps);
01012     };
01013     Cleanup(setting, pano, imgs, keyFiles, parent);
01014     return cps;
01015 };
01016 
01017 HuginBase::CPVector AutoPanoSiftMultiRowStack::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
01018                                      int nFeatures, int & ret_value, wxWindow *parent)
01019 {
01020     HuginBase::CPVector cps;
01021     if (imgs.size() == 0) {
01022         return cps;
01023     };
01024     std::vector<stack_img> stack_images;
01025     HuginBase::StandardImageVariableGroups* variable_groups = new HuginBase::StandardImageVariableGroups(pano);
01026     for(UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
01027     {
01028         unsigned int stack_nr=variable_groups->getStacks().getPartNumber(*it);
01029         //check, if this stack is already in list
01030         bool found=false;
01031         unsigned int index=0;
01032         for(index=0;index<stack_images.size();index++)
01033         {
01034             found=(stack_images[index].layer_nr==stack_nr);
01035             if(found)
01036                 break;
01037         };
01038         if(!found)
01039         {
01040             //new stack
01041             stack_images.resize(stack_images.size()+1);
01042             index=stack_images.size()-1;
01043             //add new stack
01044             stack_images[index].layer_nr=stack_nr;
01045         };
01046         //add new image
01047         unsigned int new_image_index=stack_images[index].images.size();
01048         stack_images[index].images.resize(new_image_index+1);
01049         stack_images[index].images[new_image_index].img_nr=*it;
01050         stack_images[index].images[new_image_index].ev=pano.getImage(*it).getExposure();
01051     };
01052     delete variable_groups;
01053     //get image with median exposure for search with cp generator
01054     UIntSet images_layer;
01055     for(unsigned int i=0;i<stack_images.size();i++)
01056     {
01057         std::sort(stack_images[i].images.begin(),stack_images[i].images.end(),sort_img_ev);
01058         unsigned int index=0;
01059         if(stack_images[i].images[0].ev!=stack_images[i].images[stack_images[i].images.size()-1].ev)
01060         {
01061             index=stack_images[i].images.size() / 2;
01062         };
01063         images_layer.insert(stack_images[i].images[index].img_nr);
01064     };
01065     ret_value=0;
01066     //work on all stacks
01067     if(!setting.GetProgStack().IsEmpty())
01068     {
01069         CPDetectorSetting stack_setting;
01070         stack_setting.SetType(CPDetector_AutoPanoSift);
01071         stack_setting.SetProg(setting.GetProgStack());
01072         stack_setting.SetArgs(setting.GetArgsStack());
01073 
01074         for(unsigned int i=0;i<stack_images.size();i++)
01075         {
01076             UIntSet images_stack;
01077             images_stack.clear();
01078             for(unsigned int j=0;j<stack_images[i].images.size();j++)
01079                 images_stack.insert(stack_images[i].images[j].img_nr);
01080             if(images_stack.size()>1)
01081             {
01082                 AutoPanoSift matcher;
01083                 HuginBase::CPVector new_cps = matcher.automatch(stack_setting, pano, images_stack, nFeatures, ret_value, parent);
01084                 if(new_cps.size()>0)
01085                     AddControlPointsWithCheck(cps,new_cps);
01086                 if(ret_value!=0)
01087                 {
01088                     std::vector<wxString> emptyKeyfiles;
01089                     Cleanup(setting, pano, imgs, emptyKeyfiles, parent);
01090                     return cps;
01091                 };
01092             };
01093         };
01094     }
01095     //generate cp for median exposure with multi-row algorithm
01096     if(images_layer.size()>1)
01097     {
01098         UIntSet allImgs;
01099         fill_set(allImgs, 0, pano.getNrOfImages()-1);
01100         Panorama newPano=pano.getSubset(allImgs);
01101         if(cps.size()>0)
01102             for (HuginBase::CPVector::const_iterator it = cps.begin(); it != cps.end(); ++it)
01103                 newPano.addCtrlPoint(*it);
01104 
01105         AutoPanoSiftMultiRow matcher;
01106         HuginBase::CPVector new_cps = matcher.automatch(setting, newPano, images_layer, nFeatures, ret_value, parent);
01107         if(new_cps.size()>0)
01108             AddControlPointsWithCheck(cps,new_cps);
01109     };
01110     return cps;
01111 };
01112 
01113 HuginBase::CPVector AutoPanoSiftPreAlign::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
01114                                      int nFeatures, int & ret_value, wxWindow *parent)
01115 {
01116     std::vector<wxString> keyFiles(pano.getNrOfImages());
01117     return automatch(setting, pano, imgs, nFeatures, keyFiles, ret_value, parent);
01118 };
01119 
01120 HuginBase::CPVector AutoPanoSiftPreAlign::automatch(CPDetectorSetting &setting, Panorama & pano, const UIntSet & imgs,
01121                                          int nFeatures, std::vector<wxString> &keyFiles, int & ret_value, wxWindow *parent)
01122 {
01123     HuginBase::CPVector cps;
01124     if (imgs.size()<2) 
01125         return cps;
01126     DEBUG_ASSERT(keyFiles.size()==pano.getNrOfImages());
01127 
01128     vector<UIntSet> usedImages;
01129     usedImages.resize(pano.getNrOfImages());
01130     if(setting.GetOption())
01131     {
01132         //only work on not connected image pairs
01133         HuginBase::CPVector oldCps = pano.getCtrlPoints();
01134         for(unsigned i=0;i<oldCps.size();i++)
01135         {
01136             if (oldCps[i].mode == HuginBase::ControlPoint::X_Y)
01137             {
01138                 usedImages[oldCps[i].image1Nr].insert(oldCps[i].image2Nr);
01139                 usedImages[oldCps[i].image2Nr].insert(oldCps[i].image1Nr);
01140             };
01141         };
01142     };
01143     HuginBase::CalculateImageOverlap overlap(&pano);
01144     overlap.calculate(10);
01145     for(UIntSet::const_iterator it=imgs.begin();it!=imgs.end();++it)
01146     {
01147         UIntSet images;
01148         images.clear();
01149         images.insert(*it);
01150         UIntSet::const_iterator it2=it;
01151         for(++it2;it2!=imgs.end();++it2)
01152         {
01153             //check if this image pair was yet used
01154             if(set_contains(usedImages[*it2],*it))
01155                 continue;
01156             //now check position
01157             if(overlap.getOverlap(*it,*it2)>0)
01158             {
01159                 images.insert(*it2);
01160             };
01161         };
01162         if(images.size()<2)
01163             continue;
01164         //remember image pairs for later
01165         for(UIntSet::const_iterator img_it=images.begin();img_it!=images.end();++img_it)
01166             for(UIntSet::const_iterator img_it2=images.begin();img_it2!=images.end();++img_it2)
01167                 usedImages[*img_it].insert(*img_it2);
01168         AutoPanoSift matcher;
01169         HuginBase::CPVector new_cps;
01170         if(setting.IsTwoStepDetector())
01171             new_cps=matcher.automatch(setting, pano, images, nFeatures, keyFiles, ret_value, parent);
01172         else
01173             new_cps=matcher.automatch(setting, pano, images, nFeatures, ret_value, parent);
01174         if(new_cps.size()>0)
01175             AddControlPointsWithCheck(cps,new_cps);
01176         if(ret_value!=0)
01177         {
01178             Cleanup(setting, pano, imgs, keyFiles, parent);
01179             return cps;
01180         };
01181     };
01182     Cleanup(setting, pano, imgs, keyFiles, parent);
01183     return cps;
01184 };

Generated on 28 Jul 2015 for Hugintrunk by  doxygen 1.4.7