Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cpclean.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
15 /* This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public
17  * License as published by the Free Software Foundation; either
18  * version 2 of the License, or (at your option) any later version.
19  *
20  * This software is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public
26  * License along with this software. If not, see
27  * <http://www.gnu.org/licenses/>.
28  *
29  */
30 
31 #include <fstream>
32 #include <sstream>
33 #include <getopt.h>
34 
39 
40 static void usage(const char* name)
41 {
42  std::cout << name << ": remove wrong control points by statistic method" << std::endl
43  << "cpclean version " << hugin_utils::GetHuginVersion() << std::endl
44  << std::endl
45  << "Usage: " << name << " [options] input.pto" << std::endl
46  << std::endl
47  << "CPClean uses statistical methods to remove wrong control points" << std::endl << std::endl
48  << "Step 1 optimises all images pairs, calculates for each pair mean " << std::endl
49  << " and standard deviation and removes all control points " << std::endl
50  << " with error bigger than mean+n*sigma" << std::endl
51  << "Step 2 optimises the whole panorama, calculates mean and standard deviation" << std::endl
52  << " for all control points and removes all control points with error" << std::endl
53  << " bigger than mean+n*sigma" << std::endl << std::endl
54  << " Options:" << std::endl
55  << " --output|-o file.pto Output Hugin PTO file." << std::endl
56  << " Default: '<filename>_clean.pto'." << std::endl
57  << " --max-distance|-n num distance factor for checking (default: 2)" << std::endl
58  << " (cps with an error > mean + this factor*sigma" << std::endl
59  << " will be removed)" << std::endl
60  << " --pairwise-checking|-p do only images pairs cp checking (skip step 2)" << std::endl
61  << " --whole-pano-checking|-w do only whole panorama cp checking (skip step 1)" << std::endl
62  << " --dont-optimize|-s skip optimisation step when checking the" << std::endl
63  << " whole panorama (only step 2)" << std::endl
64  << " --check-line-cp|-l also include line control points for calculation" << std::endl
65  << " and filtering in step 2" << std::endl
66  << " --verbose|-v verbose output during optimisation"<<std::endl
67  << " --help|-h shows help" << std::endl
68  << std::endl;
69 }
70 
71 // dummy panotools progress functions
72 static int ptProgress(int command, char* argument)
73 {
74  return 1;
75 }
76 
77 static int ptinfoDlg(int command, char* argument)
78 {
79  return 1;
80 }
81 
82 int main(int argc, char* argv[])
83 {
84  // parse arguments
85  const char* optstring = "o:hn:pwslv";
86  static struct option longOptions[] =
87  {
88  { "output", required_argument, NULL, 'o'},
89  { "max-distance", required_argument, NULL, 'n'},
90  { "pairwise-checking", no_argument, NULL, 'p'},
91  { "whole-pano-checking", no_argument, NULL, 'w'},
92  { "dont-optimize", no_argument, NULL, 's'},
93  { "check-line-cp", no_argument, NULL, 'l' },
94  { "verbose", no_argument, NULL, 'v'},
95  { "help", no_argument, NULL, 'h' },
96  0
97  };
98  int c;
99  std::string output;
100  bool onlyPair = false;
101  bool wholePano = false;
102  bool skipOptimisation = false;
103  bool includeLineCp = false;
104  bool verbose = false;
105  double n = 2.0;
106  while ((c = getopt_long(argc, argv, optstring, longOptions, nullptr)) != -1)
107  {
108  switch (c)
109  {
110  case 'o':
111  output = optarg;
112  break;
113  case 'h':
114  usage(hugin_utils::stripPath(argv[0]).c_str());
115  return 0;
116  case 'n':
117  n = atof(optarg);
118  if(n==0)
119  {
120  std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid parameter: " << optarg << " is not valid real number" << std::endl;
121  return 1;
122  };
123  if (n<1.0)
124  {
125  std::cerr << hugin_utils::stripPath(argv[0]) << ": Invalid parameter: n must be at least 1" << std::endl;
126  return 1;
127  };
128  break;
129  case 'p':
130  onlyPair= true;
131  break;
132  case 'w':
133  wholePano = true;
134  break;
135  case 's':
136  skipOptimisation = true;
137  break;
138  case 'l':
139  includeLineCp = true;
140  break;
141  case 'v':
142  verbose = true;
143  break;
144  case ':':
145  case '?':
146  // missing argument or invalid switch
147  return 1;
148  break;
149  default:
150  // this should not happen
151  abort ();
152  }
153  }
154 
155  if (argc - optind != 1)
156  {
157  if (argc - optind < 1)
158  {
159  std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
160  }
161  else
162  {
163  std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
164  };
165  return 1;
166  };
167 
168  if (onlyPair && wholePano)
169  {
170  std::cerr << hugin_utils::stripPath(argv[0]) << ": Options -p and -w can't used together" << std::endl;
171  return 1;
172  };
173 
174  std::string input=argv[optind];
175 
176  HuginBase::Panorama pano;
177  if (!pano.ReadPTOFile(input, hugin_utils::getPathPrefix(input)))
178  {
179  return 1;
180  };
181 
182  const size_t nrImg=pano.getNrOfImages();
183  if (nrImg < 2)
184  {
185  std::cerr << "Panorama should consist of at least two images" << std::endl;
186  return 1;
187  }
188 
189  if (pano.getNrOfCtrlPoints() < 3)
190  {
191  std::cerr << "Panorama should contain at least 3 control point" << std::endl;
192  };
193 
194  if (!verbose)
195  {
196  PT_setProgressFcn(ptProgress);
197  PT_setInfoDlgFcn(ptinfoDlg);
198  };
199 
200  size_t cpremoved1 = 0;
201  HuginBase::UIntSet CPtoRemove;
202  // step 1 with pairwise optimisation
203  if(!wholePano)
204  {
206  std::cout << "Step 1: Do image pair control point checking..." << std::endl;
207  CPtoRemove=getCPoutsideLimit_pair(pano, dummy, n);
208  if (!CPtoRemove.empty())
209  for (HuginBase::UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
210  {
211  pano.removeCtrlPoint(*it);
212  }
213  cpremoved1=CPtoRemove.size();
214  };
215 
216  // step 2 with optimisation of whole panorama
217  bool unconnected=false;
218  if(!onlyPair)
219  {
220  //check for unconnected images
221  HuginGraph::ImageGraph graph(pano);
222  unconnected = !graph.IsConnected();
223  if (!unconnected)
224  {
225  CPtoRemove.clear();
226  std::cout << "Step 2: Do whole panorama control point checking..." << std::endl;
227  if(skipOptimisation)
228  {
229  std::cout << " Skipping optimisation, current image positions will be used." << std::endl;
230  };
231  CPtoRemove=getCPoutsideLimit(pano, n, skipOptimisation, includeLineCp);
232  if (!CPtoRemove.empty())
233  for (HuginBase::UIntSet::reverse_iterator it = CPtoRemove.rbegin(); it != CPtoRemove.rend(); ++it)
234  {
235  pano.removeCtrlPoint(*it);
236  }
237  }
238  else
239  {
240  std::cout << "Skipping whole panorama checking because of unconnected image groups" << std::endl;
241  };
242  };
243 
244  std::cout << std::endl;
245  if(!wholePano)
246  {
247  std::cout << "Removed " << cpremoved1 << " control points in step 1" << std::endl;
248  }
249  if (!onlyPair)
250  {
251  if (unconnected)
252  {
253  std::cout << "Skipped step 2 because of unconnected image pairs" << std::endl;
254  }
255  else
256  {
257  std::cout << "Removed " << CPtoRemove.size() << " control points in step 2" << std::endl;
258  };
259  };
260 
261  //write output
262  // Set output .pto filename if not given
263  output = hugin_utils::GetOutputFilename(output, input, "clean");
264  if (pano.WritePTOFile(output, hugin_utils::getPathPrefix(output)))
265  {
266  std::cout << std::endl << "Written output to " << output << std::endl;
267  };
268  return 0;
269 }
static int ptProgress(int command, char *argument)
Definition: cpclean.cpp:72
Dummy progress display, without output.
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition: utils.cpp:420
bool IsConnected()
check if all images are connected
Definition: ImageGraph.cpp:128
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
algorithms for remove control points by statistic method
Model for a panorama.
Definition: Panorama.h:152
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
UIntSet getCPoutsideLimit_pair(Panorama pano, AppBase::ProgressDisplay &progress, double n)
optimises images pairwise and removes for every image pair control points with error &gt; mean+n*sigma ...
Definition: CleanCP.cpp:37
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Definition: Panorama.cpp:2023
!! from PTOptimise.h 1951
UIntSet getCPoutsideLimit(Panorama pano, double n, bool skipOptimisation, bool includeLineCp)
optimises the whole panorama and removes all control points with error &gt; mean+n*sigma ...
Definition: CleanCP.cpp:123
static void usage()
Definition: Main.cpp:32
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:907
void removeCtrlPoint(unsigned int pNr)
remove a control point.
Definition: Panorama.cpp:391
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
static int ptinfoDlg(int command, char *argument)
Definition: cpclean.cpp:77
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition: utils.cpp:160
int main(int argc, char *argv[])
Definition: Main.cpp:167
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition: ImageGraph.h:44