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, see
00027  *  <http://www.gnu.org/licenses/>.
00028  *
00029  */
00030 
00031 #include <fstream>
00032 #include <sstream>
00033 #ifdef WIN32
00034 #include <getopt.h>
00035 #else
00036 #include <unistd.h>
00037 #endif
00038 
00039 #include <algorithms/optimizer/PTOptimizer.h>
00040 #include <algorithms/control_points/CleanCP.h>
00041 #include "panotools/PanoToolsInterface.h"
00042 
00043 using namespace std;
00044 using namespace HuginBase;
00045 using namespace AppBase;
00046 
00047 static void usage(const char* name)
00048 {
00049     cout << name << ": remove wrong control points by statistic method" << endl
00050          << "cpclean version " << hugin_utils::GetHuginVersion() << endl
00051          << endl
00052          << "Usage:  " << name << " [options] input.pto" << endl
00053          << endl
00054          << "CPClean uses statistical methods to remove wrong control points" << endl << endl
00055          << "Step 1 optimises all images pairs, calculates for each pair mean " << endl
00056          << "       and standard deviation and removes all control points " << endl
00057          << "       with error bigger than mean+n*sigma" << endl
00058          << "Step 2 optimises the whole panorama, calculates mean and standard deviation" << endl
00059          << "       for all control points and removes all control points with error" << endl
00060          << "       bigger than mean+n*sigma" << endl << endl
00061          << "  Options:" << endl
00062          << "     -o file.pto  Output Hugin PTO file. Default: '<filename>_clean.pto'." << endl
00063          << "     -n num   distance factor for checking (default: 2)" << endl
00064          << "     -p       do only pairwise optimisation (skip step 2)" << endl
00065          << "     -w       do optimise whole panorama (skip step 1)" << endl
00066          << "     -s       skip optimisation step when optimisation the whole panorama" << endl
00067          << "     -l       also include line control points for calculation and" << endl
00068          << "              filtering in step 2" << endl
00069          << "     -h       shows help" << endl
00070          << endl;
00071 }
00072 
00073 // dummy panotools progress functions
00074 static int ptProgress(int command, char* argument)
00075 {
00076     return 1;
00077 }
00078 
00079 static int ptinfoDlg(int command, char* argument)
00080 {
00081     return 1;
00082 }
00083 
00084 int main(int argc, char* argv[])
00085 {
00086     // parse arguments
00087     const char* optstring = "o:hn:pwslv";
00088 
00089     int c;
00090     string output;
00091     bool onlyPair = false;
00092     bool wholePano = false;
00093     bool skipOptimisation = false;
00094     bool includeLineCp = false;
00095     bool verbose = false;
00096     double n = 2.0;
00097     while ((c = getopt (argc, argv, optstring)) != -1)
00098     {
00099         switch (c)
00100         {
00101             case 'o':
00102                 output = optarg;
00103                 break;
00104             case 'h':
00105                 usage(hugin_utils::stripPath(argv[0]).c_str());
00106                 return 0;
00107             case 'n':
00108                 n = atof(optarg);
00109                 if(n==0)
00110                 {
00111                     cerr <<"Invalid parameter: " << optarg << " is not valid real number" << endl;
00112                     return 1;
00113                 };
00114                 if (n<1.0)
00115                 {
00116                     cerr << "Invalid parameter: n must be at least 1" << endl;
00117                     return 1;
00118                 };
00119                 break;
00120             case 'p':
00121                 onlyPair= true;
00122                 break;
00123             case 'w':
00124                 wholePano = true;
00125                 break;
00126             case 's':
00127                 skipOptimisation = true;
00128                 break;
00129             case 'l':
00130                 includeLineCp = true;
00131                 break;
00132             case 'v':
00133                 verbose = true;
00134                 break;
00135             case ':':
00136                 cerr <<"Option -n requires a number" << endl;
00137                 return 1;
00138                 break;
00139             case '?':
00140                 break;
00141             default:
00142                 abort ();
00143         }
00144     }
00145 
00146     if (argc - optind != 1)
00147     {
00148         usage(hugin_utils::stripPath(argv[0]).c_str());
00149         return 1;
00150     };
00151 
00152     if (onlyPair && wholePano)
00153     {
00154         cerr << "Options -p and -w can't used together" << endl;
00155         return 1;
00156     };
00157 
00158     string input=argv[optind];
00159 
00160     Panorama pano;
00161     ifstream prjfile(input.c_str());
00162     if (!prjfile.good())
00163     {
00164         cerr << "could not open script : " << input << endl;
00165         return 1;
00166     }
00167     pano.setFilePrefix(hugin_utils::getPathPrefix(input));
00168     DocumentData::ReadWriteError err = pano.readData(prjfile);
00169     if (err != DocumentData::SUCCESSFUL)
00170     {
00171         cerr << "error while parsing panos tool script: " << input << endl;
00172         cerr << "DocumentData::ReadWriteError code: " << err << endl;
00173         return 1;
00174     }
00175 
00176     size_t nrImg=pano.getNrOfImages();
00177     if (nrImg < 2)
00178     {
00179         cerr << "Panorama should consist of at least two images" << endl;
00180         return 1;
00181     }
00182 
00183     if (pano.getNrOfCtrlPoints() < 3)
00184     {
00185         cerr << "Panorama should contain at least 3 control point" << endl;
00186     };
00187 
00188     if (!verbose)
00189     {
00190         PT_setProgressFcn(ptProgress);
00191         PT_setInfoDlgFcn(ptinfoDlg);
00192     };
00193 
00194     size_t cpremoved1=0;
00195     UIntSet CPtoRemove;
00196     // step 1 with pairwise optimisation
00197     if(!wholePano)
00198     {
00199         AppBase::DummyProgressDisplay dummy;
00200         CPtoRemove=getCPoutsideLimit_pair(pano, dummy, n);
00201         if (CPtoRemove.size()>0)
00202             for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
00203             {
00204                 pano.removeCtrlPoint(*it);
00205             }
00206         cpremoved1=CPtoRemove.size();
00207     };
00208 
00209     // step 2 with optimisation of whole panorama
00210     bool unconnected=false;
00211     if(!onlyPair)
00212     {
00213         //check for unconnected images
00214         CPGraph graph;
00215         createCPGraph(pano, graph);
00216         CPComponents comps;
00217         const size_t parts=findCPComponents(graph, comps);
00218         if (parts > 1)
00219         {
00220             unconnected=true;
00221         }
00222         else
00223         {
00224             CPtoRemove.clear();
00225             if(skipOptimisation)
00226             {
00227                 std::cout << endl << "Skipping optimisation, current image positions will be used." << endl;
00228             };
00229             CPtoRemove=getCPoutsideLimit(pano, n, skipOptimisation, includeLineCp);
00230             if (CPtoRemove.size()>0)
00231                 for(UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
00232                 {
00233                     pano.removeCtrlPoint(*it);
00234                 }
00235         };
00236     };
00237 
00238     cout << endl;
00239     if(!wholePano)
00240     {
00241         cout << "Removed " << cpremoved1 << " control points in step 1" << endl;
00242     }
00243     if(!onlyPair)
00244         if(unconnected)
00245         {
00246             cout <<"Skipped step 2 because of unconnected image pairs" << endl;
00247         }
00248         else
00249         {
00250             cout << "Removed " << CPtoRemove.size() << " control points in step 2" << endl;
00251         }
00252 
00253     //write output
00254     OptimizeVector optvec = pano.getOptimizeVector();
00255     UIntSet imgs;
00256     fill_set(imgs,0, pano.getNrOfImages()-1);
00257     // Set output .pto filename if not given
00258     if (output=="")
00259     {
00260         output=input.substr(0,input.length()-4).append("_clean.pto");
00261     }
00262     ofstream of(output.c_str());
00263     pano.printPanoramaScript(of, optvec, pano.getOptions(), imgs, false, hugin_utils::getPathPrefix(input));
00264 
00265     cout << endl << "Written output to " << output << endl;
00266     return 0;
00267 }

Generated on 2 Sep 2015 for Hugintrunk by  doxygen 1.4.7