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

Generated on Thu Oct 2 01:25:38 2014 for Hugintrunk by  doxygen 1.3.9.1