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

Generated on 10 Dec 2016 for Hugintrunk by  doxygen 1.4.7