cpclean.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00015 /*  This program is free software; you can redistribute it and/or
00016  *  modify it under the terms of the GNU General Public
00017  *  License as published by the Free Software Foundation; either
00018  *  version 2 of the License, or (at your option) any later version.
00019  *
00020  *  This software is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00023  *  General Public License for more details.
00024  *
00025  *  You should have received a copy of the GNU General Public
00026  *  License along with this software; if not, write to the Free Software
00027  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 #include <hugin_version.h>
00032 
00033 #include <fstream>
00034 #include <sstream>
00035 #ifdef WIN32
00036  #include <getopt.h>
00037 #else
00038  #include <unistd.h>
00039 #endif
00040 
00041 #include <algorithms/optimizer/PTOptimizer.h>
00042 #include <algorithms/control_points/CleanCP.h>
00043 
00044 using namespace std;
00045 using namespace HuginBase;
00046 using namespace AppBase;
00047 
00048 static void usage(const char * name)
00049 {
00050     cout << name << ": remove wrong control points by statistic method" << endl
00051          << "cpclean version " << DISPLAY_VERSION << endl
00052          << endl
00053          << "Usage:  " << name << " [options] input.pto" << endl
00054          << endl
00055          << "CPClean uses statistical methods to remove wrong control points" << endl << endl
00056          << "Step 1 optimises all images pairs, calculates for each pair mean " << endl
00057          << "       and standard deviation and removes all control points " << endl
00058          << "       with error bigger than mean+n*sigma" << endl
00059          << "Step 2 optimises the whole panorama, calculates mean and standard deviation" << endl
00060          << "       for all control points and removes all control points with error" << endl
00061          << "       bigger than mean+n*sigma" << endl << endl
00062          << "  Options:" << endl
00063          << "     -o file.pto  Output Hugin PTO file. Default: '<filename>_clean.pto'." << endl
00064          << "     -n num   distance factor for checking (default: 2)" << endl
00065          << "     -p       do only pairwise optimisation (skip step 2)" << endl
00066          << "     -w       do optimise whole panorama (skip step 1)" << endl
00067          << "     -s       skip optimisation step when optimisation the whole panorama" << endl
00068          << "     -l       also include line control points for calculation and" << endl
00069          << "              filtering in step 2" << endl
00070          << "     -h       shows help" << endl
00071          << endl;
00072 }
00073 
00074 int main(int argc, char *argv[])
00075 {
00076     // parse arguments
00077     const char * optstring = "o:hn:pwsl";
00078 
00079     int c;
00080     string output;
00081     bool onlyPair = false;
00082     bool wholePano = false;
00083     bool skipOptimisation = false;
00084     bool includeLineCp = false;
00085     double n = 2.0;
00086     while ((c = getopt (argc, argv, optstring)) != -1)
00087     {
00088         switch (c) {
00089         case 'o':
00090             output = optarg;
00091             break;
00092         case 'h':
00093             usage(argv[0]);
00094             return 0;
00095         case 'n':
00096             n = atof(optarg);
00097             if(n==0)
00098             {
00099                 cerr <<"Invalid parameter: " << optarg << " is not valid real number" << endl;
00100                 return 1;
00101             };
00102                 if (n<1.0) 
00103             {
00104                         cerr << "Invalid parameter: n must be at least 1" << endl;
00105                         return 1;
00106             };
00107             break;
00108         case 'p':
00109             onlyPair= true;
00110             break;
00111         case 'w':
00112             wholePano = true;
00113             break;
00114         case 's':
00115             skipOptimisation = true;
00116             break;
00117         case 'l':
00118             includeLineCp = true;
00119             break;
00120         case ':':
00121             cerr <<"Option -n requires a number" << endl;
00122             return 1;
00123             break;
00124         case '?':
00125             break;
00126         default:
00127             abort ();
00128         }
00129     }
00130 
00131     if (argc - optind != 1) 
00132     {
00133         usage(argv[0]);
00134         return 1;
00135     };
00136     
00137     if (onlyPair && wholePano)
00138     {
00139         cerr << "Options -p and -w can't used together" << endl;
00140         return 1;
00141     };
00142 
00143     string input=argv[optind];
00144 
00145     Panorama pano;
00146     ifstream prjfile(input.c_str());
00147     if (!prjfile.good()) {
00148         cerr << "could not open script : " << input << endl;
00149         return 1;
00150     }
00151     pano.setFilePrefix(hugin_utils::getPathPrefix(input));
00152     DocumentData::ReadWriteError err = pano.readData(prjfile);
00153     if (err != DocumentData::SUCCESSFUL) {
00154         cerr << "error while parsing panos tool script: " << input << endl;
00155         cerr << "DocumentData::ReadWriteError code: " << err << endl;
00156         return 1;
00157     }
00158 
00159     size_t nrImg=pano.getNrOfImages();
00160     if (nrImg < 2) 
00161     {
00162         cerr << "Panorama should consist of at least two images" << endl;
00163         return 1;
00164     }
00165 
00166     if (pano.getNrOfCtrlPoints() < 3)
00167     {
00168         cerr << "Panorama should contain at least 3 control point" << endl;
00169     };
00170     
00171     size_t cpremoved1=0;
00172     UIntSet CPtoRemove;
00173     // step 1 with pairwise optimisation
00174     if(!wholePano)
00175     {
00176         CPtoRemove=getCPoutsideLimit_pair(pano,n);
00177         if (CPtoRemove.size()>0)
00178             for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
00179                 pano.removeCtrlPoint(*it);
00180         cpremoved1=CPtoRemove.size();
00181     };
00182 
00183     // step 2 with optimisation of whole panorama
00184     bool unconnected=false;
00185     if(!onlyPair)
00186     {
00187         //check for unconnected images
00188         CPGraph graph;
00189         createCPGraph(pano, graph);
00190         CPComponents comps;
00191         int parts=findCPComponents(graph, comps);
00192         if (parts > 1) 
00193         {
00194             unconnected=true;
00195         }
00196         else
00197         {
00198             CPtoRemove.clear();
00199             if(skipOptimisation)
00200             {
00201                 std::cout << endl << "Skipping optimisation, current image positions will be used." << endl;
00202             };
00203             CPtoRemove=getCPoutsideLimit(pano, n, skipOptimisation, includeLineCp);
00204             if (CPtoRemove.size()>0)
00205                 for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
00206                     pano.removeCtrlPoint(*it);
00207         };
00208     };
00209 
00210     cout << endl;
00211     if(!wholePano)
00212         cout << "Removed " << cpremoved1 << " control points in step 1" << endl;
00213     if(!onlyPair)
00214         if(unconnected)
00215             cout <<"Skipped step 2 because of unconnected image pairs" << endl;
00216         else
00217             cout << "Removed " << CPtoRemove.size() << " control points in step 2" << endl;
00218 
00219     //write output
00220     OptimizeVector optvec = pano.getOptimizeVector();
00221     UIntSet imgs;
00222     fill_set(imgs,0, pano.getNrOfImages()-1);
00223         // Set output .pto filename if not given
00224         if (output=="")
00225     {
00226         output=input.substr(0,input.length()-4).append("_clean.pto");
00227         }
00228     ofstream of(output.c_str());
00229     pano.printPanoramaScript(of, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input));
00230     
00231     cout << endl << "Written output to " << output << endl;
00232     return 0;
00233 }

Generated on Wed Apr 16 01:25:39 2014 for Hugintrunk by  doxygen 1.3.9.1