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 optionIndex = 0;
00158     int number;
00159     double floatNumber;
00160     std::string ransacMode;
00161     std::vector<int> keyfilesIndex;
00162     int doLinearMatch=0;
00163     int doMultirow=0;
00164     int doPrealign=0;
00165     while ((c = getopt_long (argc, argv, optstring, longOptions,&optionIndex)) != -1)
00166     {
00167         switch (c)
00168         {
00169             case 'q':
00170                 ioPanoDetector.setVerbose(0);
00171                 break;
00172             case 'v':
00173                 ioPanoDetector.setVerbose(2);
00174                 break;
00175             case 'f':
00176                 ioPanoDetector.setDownscale(false);
00177                 break;
00178             case SIEVE1WIDTH:
00179                 number=atoi(optarg);
00180                 if(number>0)
00181                 {
00182                     ioPanoDetector.setSieve1Width(number);
00183                 };
00184                 break;
00185             case SIEVE1HEIGHT:
00186                 number=atoi(optarg);
00187                 if(number>0)
00188                 {
00189                     ioPanoDetector.setSieve1Height(number);
00190                 };
00191                 break;
00192             case SIEVE1SIZE:
00193                 number=atoi(optarg);
00194                 if(number>0)
00195                 {
00196                     ioPanoDetector.setSieve1Size(number);
00197                 };
00198                 break;
00199             case LINEARMATCH:
00200                 doLinearMatch=1;
00201                 break;
00202             case LINEARMATCHLEN:
00203                 number=atoi(optarg);
00204                 if(number>0)
00205                 {
00206                     ioPanoDetector.setLinearMatchLen(number);
00207                 };
00208                 break;
00209             case MULTIROW:
00210                 doMultirow=1;
00211                 break;
00212             case PREALIGNED:
00213                 doPrealign=1;
00214                 break;
00215             case KDTREESTEPS:
00216                 number=atoi(optarg);
00217                 if(number>0)
00218                 {
00219                     ioPanoDetector.setKDTreeSearchSteps(number);
00220                 };
00221                 break;
00222             case KDTREESECONDDIST:
00223                 floatNumber=atof(optarg);
00224                 if(floatNumber>0)
00225                 {
00226                     ioPanoDetector.setKDTreeSecondDistance(floatNumber);
00227                 };
00228                 break;
00229             case MINMATCHES:
00230                 number=atoi(optarg);
00231                 if(number>0)
00232                 {
00233                     ioPanoDetector.setMinimumMatches(number);
00234                 };
00235                 break;
00236             case RANSACMODE:
00237                 ransacMode = optarg;
00238                 std::cout << "Ransac: " << ransacMode << std::endl;
00239                 ransacMode=hugin_utils::tolower(ransacMode);
00240                 std::cout << "Ransac: " << ransacMode << std::endl;
00241                 if(ransacMode=="auto")
00242                 {
00243                     ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::AUTO);
00244                 }
00245                 else
00246                 {
00247                     if(ransacMode=="hom")
00248                     {
00249                         ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::HOMOGRAPHY);
00250                     }
00251                     else
00252                     {
00253                         if(ransacMode=="rpy")
00254                         {
00255                             ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPY);
00256                         }
00257                         else
00258                         {
00259                             if(ransacMode=="rpyv")
00260                             {
00261                                 ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPYV);
00262                             }
00263                             else
00264                             {
00265                                 if(ransacMode=="rpyvb")
00266                                 {
00267                                     ioPanoDetector.setRansacMode(HuginBase::RANSACOptimizer::RPYVB);
00268                                 }
00269                                 else
00270                                 {
00271                                     std::cout << "Warning: Invalid parameter in --ransacmode." << std::endl;
00272                                 };
00273                             };
00274                         };
00275                     };
00276                 };
00277                 break;
00278             case RANSACITER:
00279                 number=atoi(optarg);
00280                 if(number>0)
00281                 {
00282                     ioPanoDetector.setRansacIterations(number);
00283                 };
00284                 break;
00285             case RANSACDIST:
00286                 number=atoi(optarg);
00287                 if(number>0)
00288                 {
00289                     ioPanoDetector.setRansacDistanceThreshold(number);
00290                 };
00291                 break;
00292             case SIEVE2WIDTH:
00293                 number=atoi(optarg);
00294                 if(number>0)
00295                 {
00296                     ioPanoDetector.setSieve2Width(number);
00297                 };
00298                 break;
00299             case SIEVE2HEIGHT:
00300                 number=atoi(optarg);
00301                 if(number>0)
00302                 {
00303                     ioPanoDetector.setSieve2Height(number);
00304                 };
00305                 break;
00306             case SIEVE2SIZE:
00307                 number=atoi(optarg);
00308                 if(number>0)
00309                 {
00310                     ioPanoDetector.setSieve2Size(number);
00311                 };
00312                 break;
00313             case 't':
00314                 ioPanoDetector.setTest(true);
00315                 break;
00316             case 'n':
00317                 number=atoi(optarg);
00318                 if(number>0)
00319                 {
00320                     ioPanoDetector.setCores(number);
00321                 };
00322                 break;
00323             case 'o':
00324                 ioPanoDetector.setOutputFile(optarg);
00325                 break;
00326             case 'k':
00327                 number=atoi(optarg);
00328                 if((number==0) && (strcmp(optarg,"0")!=0))
00329                 {
00330                     std::cout << "Warning: " << optarg << " is not a valid image number of writekeyfile." << std::endl;
00331                 }
00332                 else
00333                 {
00334                     keyfilesIndex.push_back(number);
00335                 };
00336                 break;
00337             case KALL:
00338                 ioPanoDetector.setWriteAllKeyPoints();
00339                 break;
00340             case 'c':
00341                 ioPanoDetector.setCached(true);
00342                 break;
00343             case CLEAN:
00344                 ioPanoDetector.setCleanup(true);
00345                 break;
00346             case 'p':
00347                 ioPanoDetector.setKeyfilesPath(optarg);
00348                 break;
00349             case CELESTE:
00350                 ioPanoDetector.setCeleste(true);
00351                 break;
00352             case CELESTETHRESHOLD:
00353                 floatNumber=atof(optarg);
00354                 if(floatNumber>0.0)
00355                 {
00356                     ioPanoDetector.setCelesteThreshold(floatNumber);
00357                 };
00358                 break;
00359             case CELESTERADIUS:
00360                 number=atoi(optarg);
00361                 if(number>0)
00362                 {
00363                     ioPanoDetector.setCelesteRadius(number);
00364                 };
00365                 break;
00366             case CPFINDVERSION:
00367                 printVersion();
00368                 return false;
00369                 break;
00370             case 'h':
00371                 printUsage();
00372                 return false;
00373                 break;
00374             case ':':
00375                 std::cerr <<"Option " << longOptions[optionIndex].name << " requires an argument" << std::endl;
00376                 return false;
00377                 break;
00378             case '?':
00379             default:
00380                 break;
00381         };
00382     };
00383     
00384     if (argc - optind != 1)
00385     {
00386         std::cout << "Error: cpfind requires at least an input project file." << std::endl;
00387         return false;
00388     };
00389     ioPanoDetector.setInputFile(argv[optind]);
00390     if(doLinearMatch + doMultirow + doPrealign>1)
00391     {
00392         std::cout << "Error: The arguments --linearmatch, --multirow and --prealigned are" << std::endl
00393              << "       mutually exclusive. Use only one of them." << std::endl;
00394         return false;
00395     };
00396     if(doLinearMatch)
00397     {
00398         ioPanoDetector.setMatchingStrategy(PanoDetector::LINEAR);
00399     };
00400     if(doMultirow)
00401     {
00402         ioPanoDetector.setMatchingStrategy(PanoDetector::MULTIROW);
00403     };
00404     if(doPrealign)
00405     {
00406         ioPanoDetector.setMatchingStrategy(PanoDetector::PREALIGNED);
00407     };
00408     if(keyfilesIndex.size()>0)
00409     {
00410         ioPanoDetector.setKeyPointsIdx(keyfilesIndex);
00411     };
00412     return true;
00413 };
00414 
00415 int main(int argc, char** argv)
00416 {
00417     // create a panodetector object
00418     PanoDetector aPanoDetector;
00419     if(!parseOptions(argc, argv, aPanoDetector))
00420     {
00421         return 0;
00422     }
00423 
00424     if (!aPanoDetector.checkData())
00425     {
00426         return 0;
00427     }
00428 
00429     printVersion();
00430     if (aPanoDetector.getVerbose() > 1)
00431     {
00432         aPanoDetector.printDetails();
00433     }
00434 
00435     TIMETRACE("Detection",aPanoDetector.run());
00436 
00437     return 0;
00438 
00439 }

Generated on 27 Sep 2016 for Hugintrunk by  doxygen 1.4.7