main.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 ; tab-width: 4 -*-
00002 /*
00003 * Copyright (C) 2007-2008 Anael Orlinski
00004 *
00005 * This file is part of Panomatic.
00006 *
00007 * Panomatic is free software; you can redistribute it and/or modify
00008 * it under the terms of the GNU General Public License as published by
00009 * the Free Software Foundation; either version 2 of the License, or
00010 * (at your option) any later version.
00011 *
00012 * Panomatic is distributed in the hope that it will be useful,
00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 * GNU General Public License for more details.
00016 *
00017 * You should have received a copy of the GNU General Public License
00018 * along with Panomatic; if not, write to the Free Software
00019 * <http://www.gnu.org/licenses/>.
00020 */
00021 
00022 #include <iostream>
00023 #include <vector>
00024 #include <string>
00025 #include "Utils.h"
00026 #include <getopt.h>
00027 #include "hugin_utils/stl_utils.h"
00028 
00029 #include "PanoDetector.h"
00030 
00031 void printVersion()
00032 {
00033     std::cout << "Hugin's cpfind " << hugin_utils::GetHuginVersion() << std::endl;
00034     std::cout << "based on Pan-o-matic by Anael Orlinski" << std::endl;
00035 };
00036 
00037 void printUsage()
00038 {
00039     printVersion();
00040     std::cout << std::endl
00041         << "Basic usage: " << std::endl
00042         << "  cpfind -o output_project project.pto" << std::endl
00043         << "  cpfind -k i0 -k i1 ... -k in project.pto" << std::endl
00044         << "  cpfind --kall project.pto" << std::endl
00045         << std::endl << "The input project file is required." << std::endl
00046         << std::endl << "General options" << std::endl
00047         << "  -q|--quiet   Do not output progress" << std::endl
00048         << "  -v|--verbose  Verbose output" << std::endl
00049         << "  -h|--help     Shows this help screen" << std::endl
00050         << "  --version     Prints the version number and exits then" << std::endl
00051         << "  -o|--output=<string>  Sets the filename of the output file" << std::endl
00052         << "                        (default: default.pto)" << std::endl
00053         << std::endl << "Matching strategy (these options are mutually exclusive)" << std::endl
00054         << "  --linearmatch   Enable linear images matching" << std::endl
00055         << "                  Can be fine tuned with" << std::endl
00056         << "      --linearmatchlen=<int>  Number of images to match (default: 1)" << std::endl
00057         << "  --multirow      Enable heuristic multi row matching" << std::endl
00058         << "  --prealigned    Match only overlapping images," << std::endl
00059         << "                  requires a rough aligned panorama" << std::endl
00060         << std::endl << "Feature description options" << std::endl
00061         << "  --sieve1width=<int>    Sieve 1: Number of buckets on width (default: 10)" << std::endl
00062         << "  --sieve1height=<int>   Sieve 1: Number of buckets on height (default: 10)" << std::endl
00063         << "  --sieve1size=<int>     Sieve 1: Max points per bucket (default: 100)" << std::endl
00064         << "  --kdtreesteps=<int>          KDTree: search steps (default: 200)" << std::endl
00065         << "  --kdtreeseconddist=<double>  KDTree: distance of 2nd match (default: 0.25)" << std::endl
00066         << std::endl << "Feature matching options" << std::endl
00067         << "  --ransaciter=<int>     Ransac: iterations (default: 1000)" << std::endl
00068         << "  --ransacdist=<int>     Ransac: homography estimation distance threshold" << std::endl
00069         << "                                 (in pixels) (default: 25)" << std::endl
00070         << "  --ransacmode=<string>  Ransac: Select the mode used in the ransac step." << std::endl
00071         << "                                 Possible values: auto, hom, rpy, rpyv, rpyb" << std::endl
00072         << "                                 (default: auto)" << std::endl
00073         << "  --minmatches=<int>     Minimum matches (default: 6)" << std::endl
00074         << "  --sieve2width=<int>    Sieve 2: Number of buckets on width (default: 5)" << std::endl
00075         << "  --sieve2height=<int>   Sieve 2: Number of buckets on height (default: 5)" << std::endl
00076         << "  --sieve2size=<int>     Sieve 2: Max points per bucket (default: 1)" << std::endl
00077         << std::endl << "Caching options" << std::endl
00078         << "  -c|--cache    Caches keypoints to external file" << std::endl
00079         << "  --clean       Clean up cached keyfiles" << std::endl
00080         << "  -p|--keypath=<string>    Store keyfiles in given path" << std::endl
00081         << "  -k|--writekeyfile=<int>  Write a keyfile for this image number" << std::endl
00082         << "  --kall                   Write keyfiles for all images in the project" << std::endl
00083         << std::endl << "Advanced options" << std::endl
00084         << "  --celeste       Masks area with clouds before running feature descriptor" << std::endl
00085         << "                  Celeste can be fine tuned with the following parameters" << std::endl
00086         << "      --celestethreshold=<int>  Threshold for celeste (default 0.5)" << std::endl
00087         << "      --celesteradius=<int>     Radius for celeste (in pixels, default 20)" << std::endl
00088         << "  --ncores=<int>  Number of threads to use (default: autodetect number of cores)" << std::endl;
00089 };
00090 
00091 bool parseOptions(int argc, char** argv, PanoDetector& ioPanoDetector)
00092 {
00093     enum
00094     {
00095         SIEVE1WIDTH=256,
00096         SIEVE1HEIGHT,
00097         SIEVE1SIZE,
00098         LINEARMATCH,
00099         LINEARMATCHLEN,
00100         MULTIROW,
00101         PREALIGNED,
00102         KDTREESTEPS,
00103         KDTREESECONDDIST,
00104         MINMATCHES,
00105         RANSACMODE,
00106         RANSACITER,
00107         RANSACDIST,
00108         SIEVE2WIDTH,
00109         SIEVE2HEIGHT,
00110         SIEVE2SIZE,
00111         KALL,
00112         CLEAN,
00113         CELESTE,
00114         CELESTETHRESHOLD,
00115         CELESTERADIUS,
00116         CPFINDVERSION
00117     };
00118     const char* optstring = "qvftn:o:k:cp:h";
00119     static struct option longOptions[] =
00120     {
00121         {"quiet", no_argument, NULL, 'q' },
00122         {"verbose", no_argument, NULL, 'v'},
00123         {"fullscale", no_argument, NULL, 'f'},
00124         {"sieve1width", required_argument, NULL, SIEVE1WIDTH},
00125         {"sieve1height", required_argument, NULL, SIEVE1HEIGHT},
00126         {"sieve1size", required_argument, NULL, SIEVE1SIZE},
00127         {"linearmatch", no_argument, NULL, LINEARMATCH},
00128         {"linearmatchlen", required_argument, NULL, LINEARMATCHLEN},
00129         {"multirow", no_argument, NULL, MULTIROW},
00130         {"prealigned", no_argument, NULL, PREALIGNED},
00131         {"kdtreesteps", required_argument, NULL, KDTREESTEPS},
00132         {"kdtreeseconddist", required_argument, NULL, KDTREESECONDDIST},
00133         {"minmatches", required_argument, NULL, MINMATCHES},
00134         {"ransacmode", required_argument, NULL, RANSACMODE},
00135         {"ransaciter", required_argument, NULL, RANSACITER},
00136         {"ransacdist", required_argument, NULL, RANSACDIST},
00137         {"sieve2width", required_argument, NULL, SIEVE2WIDTH},
00138         {"sieve2height", required_argument, NULL, SIEVE2HEIGHT},
00139         {"sieve2size", required_argument, NULL, SIEVE2SIZE},
00140         {"test", no_argument, NULL, 't'},
00141         {"ncores", required_argument, NULL, 'n'},
00142         {"output", required_argument, NULL, 'o'},
00143         {"writekeyfile", required_argument, NULL, 'k'},
00144         {"kall", no_argument, NULL, KALL},
00145         {"cache", no_argument, NULL, 'c'},
00146         {"clean", no_argument, NULL, CLEAN},
00147         {"keypath", required_argument, NULL, 'p'},
00148         {"celeste", no_argument, NULL, CELESTE},
00149         {"celestethreshold", required_argument, NULL, CELESTETHRESHOLD},
00150         {"celesteradius", required_argument, NULL, CELESTERADIUS},
00151         {"version", no_argument, NULL, CPFINDVERSION},
00152         {"help", no_argument, NULL, 'h'},
00153         0
00154     };
00155 
00156     int c;
00157     int number;
00158     double floatNumber;
00159     std::string ransacMode;
00160     std::vector<int> keyfilesIndex;
00161     int doLinearMatch=0;
00162     int doMultirow=0;
00163     int doPrealign=0;
00164     while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
00165     {
00166         switch (c)
00167         {
00168             case 'q':
00169                 ioPanoDetector.setVerbose(0);
00170                 break;
00171             case 'v':
00172                 ioPanoDetector.setVerbose(2);
00173                 break;
00174             case 'f':
00175                 ioPanoDetector.setDownscale(false);
00176                 break;
00177             case SIEVE1WIDTH:
00178                 number=atoi(optarg);
00179                 if(number>0)
00180                 {
00181                     ioPanoDetector.setSieve1Width(number);
00182                 };
00183                 break;
00184             case SIEVE1HEIGHT:
00185                 number=atoi(optarg);
00186                 if(number>0)
00187                 {
00188                     ioPanoDetector.setSieve1Height(number);
00189                 };
00190                 break;
00191             case SIEVE1SIZE:
00192                 number=atoi(optarg);
00193                 if(number>0)
00194                 {
00195                     ioPanoDetector.setSieve1Size(number);
00196                 };
00197                 break;
00198             case LINEARMATCH:
00199                 doLinearMatch=1;
00200                 break;
00201             case LINEARMATCHLEN:
00202                 number=atoi(optarg);
00203                 if(number>0)
00204                 {
00205                     ioPanoDetector.setLinearMatchLen(number);
00206                 };
00207                 break;
00208             case MULTIROW:
00209                 doMultirow=1;
00210                 break;
00211             case PREALIGNED:
00212                 doPrealign=1;
00213                 break;
00214             case KDTREESTEPS:
00215                 number=atoi(optarg);
00216                 if(number>0)
00217                 {
00218                     ioPanoDetector.setKDTreeSearchSteps(number);
00219                 };
00220                 break;
00221             case KDTREESECONDDIST:
00222                 floatNumber=atof(optarg);
00223                 if(floatNumber>0)
00224                 {
00225                     ioPanoDetector.setKDTreeSecondDistance(floatNumber);
00226                 };
00227                 break;
00228             case MINMATCHES:
00229                 number=atoi(optarg);
00230                 if(number>0)
00231                 {
00232                     ioPanoDetector.setMinimumMatches(number);
00233                 };
00234                 break;
00235             case RANSACMODE:
00236                 ransacMode = optarg;
00237                 std::cout << "Ransac: " << ransacMode << std::endl;
00238                 ransacMode=hugin_utils::tolower(ransacMode);
00239                 std::cout << "Ransac: " << ransacMode << std::endl;
00240                 if(ransacMode=="auto")
00241                 {
00242                     ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::AUTO);
00243                 }
00244                 else
00245                 {
00246                     if(ransacMode=="hom")
00247                     {
00248                         ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::HOMOGRAPHY);
00249                     }
00250                     else
00251                     {
00252                         if(ransacMode=="rpy")
00253                         {
00254                             ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPY);
00255                         }
00256                         else
00257                         {
00258                             if(ransacMode=="rpyv")
00259                             {
00260                                 ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPYV);
00261                             }
00262                             else
00263                             {
00264                                 if(ransacMode=="rpyvb")
00265                                 {
00266                                     ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPYVB);
00267                                 }
00268                                 else
00269                                 {
00270                                     std::cout << "Warning: Invalid parameter in --ransacmode." << std::endl;
00271                                 };
00272                             };
00273                         };
00274                     };
00275                 };
00276                 break;
00277             case RANSACITER:
00278                 number=atoi(optarg);
00279                 if(number>0)
00280                 {
00281                     ioPanoDetector.setRansacIterations(number);
00282                 };
00283                 break;
00284             case RANSACDIST:
00285                 number=atoi(optarg);
00286                 if(number>0)
00287                 {
00288                     ioPanoDetector.setRansacDistanceThreshold(number);
00289                 };
00290                 break;
00291             case SIEVE2WIDTH:
00292                 number=atoi(optarg);
00293                 if(number>0)
00294                 {
00295                     ioPanoDetector.setSieve2Width(number);
00296                 };
00297                 break;
00298             case SIEVE2HEIGHT:
00299                 number=atoi(optarg);
00300                 if(number>0)
00301                 {
00302                     ioPanoDetector.setSieve2Height(number);
00303                 };
00304                 break;
00305             case SIEVE2SIZE:
00306                 number=atoi(optarg);
00307                 if(number>0)
00308                 {
00309                     ioPanoDetector.setSieve2Size(number);
00310                 };
00311                 break;
00312             case 't':
00313                 ioPanoDetector.setTest(true);
00314                 break;
00315             case 'n':
00316                 number=atoi(optarg);
00317                 if(number>0)
00318                 {
00319                     ioPanoDetector.setCores(number);
00320                 };
00321                 break;
00322             case 'o':
00323                 ioPanoDetector.setOutputFile(optarg);
00324                 break;
00325             case 'k':
00326                 number=atoi(optarg);
00327                 if((number==0) && (strcmp(optarg,"0")!=0))
00328                 {
00329                     std::cout << "Warning: " << optarg << " is not a valid image number of writekeyfile." << std::endl;
00330                 }
00331                 else
00332                 {
00333                     keyfilesIndex.push_back(number);
00334                 };
00335                 break;
00336             case KALL:
00337                 ioPanoDetector.setWriteAllKeyPoints();
00338                 break;
00339             case 'c':
00340                 ioPanoDetector.setCached(true);
00341                 break;
00342             case CLEAN:
00343                 ioPanoDetector.setCleanup(true);
00344                 break;
00345             case 'p':
00346                 ioPanoDetector.setKeyfilesPath(optarg);
00347                 break;
00348             case CELESTE:
00349                 ioPanoDetector.setCeleste(true);
00350                 break;
00351             case CELESTETHRESHOLD:
00352                 floatNumber=atof(optarg);
00353                 if(floatNumber>0.0)
00354                 {
00355                     ioPanoDetector.setCelesteThreshold(floatNumber);
00356                 };
00357                 break;
00358             case CELESTERADIUS:
00359                 number=atoi(optarg);
00360                 if(number>0)
00361                 {
00362                     ioPanoDetector.setCelesteRadius(number);
00363                 };
00364                 break;
00365             case CPFINDVERSION:
00366                 printVersion();
00367                 return false;
00368                 break;
00369             case 'h':
00370                 printUsage();
00371                 return false;
00372                 break;
00373             case ':':
00374             case '?':
00375                 // missing argument or invalid switch
00376                 return false;
00377                 break;
00378             default:
00379                 // this should not happen
00380                 abort();
00381         };
00382     };
00383     
00384     if (argc - optind != 1)
00385     {
00386         if (argc - optind < 1)
00387         {
00388             std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
00389         }
00390         else
00391         {
00392             std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
00393         };
00394         return false;
00395     };
00396     ioPanoDetector.setInputFile(argv[optind]);
00397     if(doLinearMatch + doMultirow + doPrealign>1)
00398     {
00399         std::cerr << hugin_utils::stripPath(argv[0]) << ": The arguments --linearmatch, --multirow and --prealigned are" << std::endl
00400              << "  mutually exclusive. Use only one of them." << std::endl;
00401         return false;
00402     };
00403     if(doLinearMatch)
00404     {
00405         ioPanoDetector.setMatchingStrategy(PanoDetector::LINEAR);
00406     };
00407     if(doMultirow)
00408     {
00409         ioPanoDetector.setMatchingStrategy(PanoDetector::MULTIROW);
00410     };
00411     if(doPrealign)
00412     {
00413         ioPanoDetector.setMatchingStrategy(PanoDetector::PREALIGNED);
00414     };
00415     if(keyfilesIndex.size()>0)
00416     {
00417         ioPanoDetector.setKeyPointsIdx(keyfilesIndex);
00418     };
00419     return true;
00420 };
00421 
00422 int main(int argc, char** argv)
00423 {
00424     // create a panodetector object
00425     PanoDetector aPanoDetector;
00426     if(!parseOptions(argc, argv, aPanoDetector))
00427     {
00428         return 0;
00429     }
00430 
00431     if (!aPanoDetector.checkData())
00432     {
00433         return 0;
00434     }
00435 
00436     printVersion();
00437     if (aPanoDetector.getVerbose() > 1)
00438     {
00439         aPanoDetector.printDetails();
00440     }
00441 
00442     TIMETRACE("Detection",aPanoDetector.run());
00443 
00444     return 0;
00445 
00446 }

Generated on 2 Dec 2016 for Hugintrunk by  doxygen 1.4.7