Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
deghosting_mask.cpp
Go to the documentation of this file.
1 
21 #include <iostream>
22 #include <string>
23 #include <cstring>
24 #include <cstdio>
25 
26 #include <hugin_config.h>
27 // for stripExtension
28 #include <hugin_utils/utils.h>
29 // for exportImage
30 #include <vigra/impex.hxx>
31 
32 #include "deghosting.h"
33 #include "support.h"
34 #include "threshold.h"
35 #include "denoise.h"
36 
37 // deghosting algorithms
38 #include "khan.h"
39 
40 #include <getopt.h>
41 #ifdef _WIN32
42  #define snprintf _snprintf
43 #endif
44 
45 // options for otherFlags
46 static const uint16_t SAVE_GENWEIGHTS = 1;
47 static const uint16_t OTHER_GRAY = 2;
48 
49 // globals containing settings
50 static int iterations = 4;
51 static double sigma = 30;
53 static uint16_t otherFlags = 0;
54 static uint16_t otherThresholdFlags = 0;
55 static uint16_t debugFlags = 0;
56 static deghosting::EMoR response(0.0f);
57 static int verbosity = 0;
58 static double thresholdLim = 150;
59 static double contrast = 1.3;
60 
63 void parseOptions_advanced(char* optarg) {
64  for(char *c = optarg; *c; c++) {
65  switch(*c) {
66  case 'f':
68  break;
69  case 'g':
71  break;
72  case 'm':
74  break;
75  case 't':
77  break;
78  case 'w':
80  break;
81  default:
82  std::cerr<< "Error: unknown option" << std::endl;
83  exit(1);
84  }
85  }
86 }
87 
90 void parseOptions_save(char* optarg) {
91  for(char *c = optarg; *c; c++) {
92  switch(*c) {
93  case 'i':
95  break;
96  case 'w':
98  break;
99  default:
100  std::cerr<< "Error: unknown option" << std::endl;
101  exit(1);
102  }
103  }
104 }
105 
106 static void usage()
107 {
108  std::cout << "deghosting_mask: creates mask for removing ghosting in images" << std::endl
109  << "deghosting_mask version " << hugin_utils::GetHuginVersion() << std::endl
110  << std::endl
111  << "Usage: deghosting_mask [options] inputfile(s) " << std::endl
112  << " option are: " << std::endl
113  << " -o, --output=PREFIX prefix for output masks" << std::endl
114  << " -i, --iterations=ITER number of iterations, default is (ITER > 0)" << std::endl
115  << " default: " << iterations << std::endl
116  << " -s, --sigma=SIGMA standard deviation of Gaussian weighting" << std::endl
117  << " function (SIGMA > 0); default: " << sigma << std::endl
118  //<< " -r, --response=E:M:o:R use camera response specified in EMoR format" << std::endl
119  << " -t, --threshold=THRESH threshold; default: " << thresholdLim << std::endl
120  << " -c, --contrast=CONTR change contrast before applying threshold;" << std::endl
121  << " default: " << contrast << std::endl
122  << " -a, --advanced=SET advanced settings. Possible options are:" << std::endl
123  << " f use gray images for computation. It's about two times faster" << std::endl
124  << " but it usually returns worse results." << std::endl
125  << " You also have to change threshold to smaller value (around 100)" << std::endl
126  << " g use gamma 2.2 correction instead of logarithm if input images are HDR" << std::endl
127  << " m do not scale image, NOTE: slows down process" << std::endl
128  << " t use simple threshold, may result in holes in images" << std::endl
129  << " w compute \"complete\" weights, not only probabilities" << std::endl
130  << " -w, --save=SET advanced save settings" << std::endl
131  << " i save initial weights" << std::endl
132  << " w save generated weights" << std::endl
133  << " -h, --help display this help" << std::endl
134  << " -v, --verbose verbose, repeat for more verbose output" << std::endl;
135 }
136 
137 int main(int argc, char *argv[]) {
138  try
139  {
140  const char * optstring = "o:i:s:r:t:c:a:w:hv";
141  int c;
142 
143  std::string outputPrefix = "weight";
144 
145  enum optionArgumentKind {
146  NoArgument,
147  StringArgument,
148  DoubleArgument,
149  IntegerArgument,
150  ArrayArgument
151  };
152 
153  enum optionId {
154  outputID,
155  iterationsID,
156  sigmaID,
157  responseID,
158  thresholdID,
159  contrastID,
160  advancedID,
161  saveID,
162  helpID,
163  verboseID
164  };
165 
166  static struct option longOptions[] = {
167  { "output", 1, 0, StringArgument },
168  { "iterations", 1, 0, IntegerArgument },
169  { "sigma", 1, 0, DoubleArgument },
170  { "response", 1, 0, ArrayArgument },
171  { "threshold", 1, 0, DoubleArgument },
172  { "contrast", 1, 0, DoubleArgument },
173  { "advanced", 1, 0, StringArgument },
174  { "save", 1, 0, StringArgument },
175  { "help", 0, 0, NoArgument },
176  { "verbose", 0, 0, NoArgument },
177  { 0, 0, 0, 0 }
178  };
179 
180  // TEST
181  // response for testing
182  response.resize(5);
183  response[0] = -3.59f;
184  response[1] = -0.93f;
185  response[2] = 0.11f;
186  response[3] = -0.22f;
187  response[4] = 0.34f;
188 
189  int optionIndex = 0;
190 
191  while ((c = getopt_long(argc, argv, optstring, longOptions, &optionIndex)) != -1) {
192  switch (c) {
193  case NoArgument: {
194  if (longOptions[optionIndex].flag != 0) break;
195  switch (optionIndex) {
196  case helpID:
197  usage();
198  return 0;
199  case verboseID:
200  verbosity++;
201  break;
202  default:
203  std::cerr << "There's a problem with parsing options" << std::endl;
204  return 1;
205  }
206  break;
207  }
208 
209  case StringArgument: {
210  if (longOptions[optionIndex].flag != 0) break;
211  switch (optionIndex) {
212  case outputID:
213  outputPrefix = optarg;
214  break;
215  case advancedID:
216  parseOptions_advanced(optarg);
217  break;
218  case saveID:
219  parseOptions_save(optarg);
220  break;
221  default:
222  std::cerr << "There's a problem with parsing options" << std::endl;
223  return 1;
224  }
225  break;
226  }
227 
228  case IntegerArgument: {
229  if (longOptions[optionIndex].flag != 0) break;
230  switch (optionIndex) {
231  case iterationsID:
232  iterations = atoi(optarg);
233  break;
234  default:
235  std::cerr << "There's a problem with parsing options" << std::endl;
236  return 1;
237  }
238  break;
239  }
240 
241  case DoubleArgument: {
242  if (longOptions[optionIndex].flag != 0) break;
243  switch (optionIndex) {
244  case sigmaID:
245  sigma = atof(optarg);
246  break;
247  case thresholdID:
248  thresholdLim = atof(optarg);
249  break;
250  case contrastID:
251  contrast = atof(optarg);
252  break;
253  }
254  break;
255  }
256 
257  case ArrayArgument: {
258  if (longOptions[optionIndex].flag != 0) break;
259  switch (optionIndex) {
260  case responseID:
261  // TODO
262  break;
263  }
264  break;
265  }
266 
267  case 'o':
268  outputPrefix = optarg;
269  break;
270  case 'i':
271  iterations = atoi(optarg);
272  break;
273  case 's':
274  sigma = atof(optarg);
275  break;
276  case 'r':
277  // TODO
278  break;
279  case 't':
280  thresholdLim = atof(optarg);
281  break;
282  case 'c':
283  contrast = atof(optarg);
284  break;
285  case 'a':
286  parseOptions_advanced(optarg);
287  break;
288  case 'w':
289  parseOptions_save(optarg);
290  break;
291  case 'h':
292  usage();
293  return 0;
294  case 'v':
295  verbosity++;
296  break;
297  case ':':
298  case '?':
299  // missing argument or invalid switch
300  return 1;
301  break;
302  default:
303  // this should not happen
304  abort();
305  }
306  }
307 
308  std::cout << std::endl;
309 
310  unsigned nFiles = argc - optind;
311  if (nFiles < 3)
312  {
313  std::cerr << hugin_utils::stripPath(argv[0]) << ": at least three input images needed" << std::endl;
314  return 1;
315  };
316 
317  // load all images
318  std::vector<std::string> inputFiles;
319  for (size_t i = optind; i < (size_t)argc; i++)
320  {
321  inputFiles.push_back(argv[i]);
322  }
323 
324  std::vector<deghosting::FImagePtr> weights;
325  std::vector<vigra::Rect2D> inputROI;
326  vigra::Rect2D outputROI;
327  if (otherFlags & OTHER_GRAY)
328  {
330  weights = deghoster.createWeightMasks();
331  inputROI = deghoster.getInputROIs();
332  outputROI = deghoster.getOutputROI();
333  }
334  else
335  {
337  weights = deghoster.createWeightMasks();
338  inputROI = deghoster.getInputROIs();
339  outputROI = deghoster.getOutputROI();
340  }
341 
342  //deghoster->setCameraResponse(response);
343 
344  // save weights
346  {
347  for (unsigned int i = 0; i<weights.size(); ++i)
348  {
349  char tmpfn[100];
350  snprintf(tmpfn, 99, "%s_%u.tif", outputPrefix.c_str(), i);
351  vigra::ImageExportInfo exWeights(tmpfn);
352  exWeights.setPixelType("UINT8");
353  exWeights.setPosition(inputROI[i].upperLeft());
354  exWeights.setCanvasSize(vigra::Size2D(inputROI[i].lowerRight().x, inputROI[i].lowerRight().y));
355  vigra::Rect2D roi(inputROI[i]);
356  roi.moveBy(-outputROI.upperLeft());
357  vigra::exportImage(srcImageRange(*weights[i], roi), exWeights);
358  }
359  }
360 
361  // apply contrast functor
362  for (unsigned int i = 0; i < weights.size(); ++i)
363  {
364  vigra::transformImage(vigra::srcImageRange(*(weights[i])), vigra::destImage(*(weights[i])), vigra::BrightnessContrastFunctor<vigra::FImage::PixelType>(1, contrast, 0, 255));
365  }
366 
367  std::vector<deghosting::BImagePtr> thresholded = threshold(weights, thresholdLim, otherThresholdFlags);
368 
369  // save masks with treshold applied
370  for (unsigned int i = 0; i<weights.size(); ++i)
371  {
372  char tmpfn[100];
373  std::string fileName = hugin_utils::stripExtension(inputFiles[i]);
374  fileName = hugin_utils::stripPath(fileName);
375  snprintf(tmpfn, 99, "%s_mask.tif", fileName.c_str());
376  vigra::ImageExportInfo exWeights(tmpfn);
377  exWeights.setPixelType("UINT8");
378  exWeights.setPosition(inputROI[i].upperLeft());
379  exWeights.setCanvasSize(vigra::Size2D(inputROI[i].lowerRight().x, inputROI[i].lowerRight().y));
380  vigra::Rect2D roi(inputROI[i]);
381  roi.moveBy(-outputROI.upperLeft());
382  vigra::BImage outImg = vigra::BImage((*thresholded[i]).size());
383  simpleDenoise(vigra::srcImageRange(*thresholded[i]), destImage(outImg));
384  vigra::exportImage(vigra::srcImageRange(outImg, roi), exWeights);
385  }
386  }
387  catch (const std::exception & e)
388  {
389  std::cerr << "caught exception: " << e.what() << std::endl;
390  return 1;
391  } catch (...)
392  {
393  std::cerr << "caught unknown exception" << std::endl;
394  return 1;
395  }
396  return 0;
397 }
const uint16_t ADV_MULTIRES
Definition: deghosting.h:53
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
std::vector< vigra::Rect2D > getInputROIs() const
Definition: deghosting.cpp:68
static const uint16_t OTHER_GRAY
const uint16_t ADV_ONLYP
Definition: deghosting.h:52
static double sigma
virtual std::vector< FImagePtr > createWeightMasks() override
create weight masks create weight masks for masking out ghosting regions
Definition: khan.h:301
static uint16_t otherThresholdFlags
static int iterations
void simpleDenoise(SrcIterator sy, SrcIterator send, SrcAccessor sa, DestIterator dy, DestAccessor da)
Simple denoising algorithm Copyright (C) 2009 Lukáš Jirkovský l.jirkovsky@gmail.com
Definition: denoise.h:26
static deghosting::EMoR response(0.0f)
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition: utils.cpp:130
static int verbosity
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
Definition: ROIImage.h:324
static const uint16_t SAVE_GENWEIGHTS
Tool for creating b/w alpha masks to eliminate ghosting artifacts Copyright (C) 2009 Lukáš Jirkovsk...
static double contrast
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
const uint16_t SAVE_INITWEIGHTS
Definition: deghosting.h:56
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition: threshold.h:41
std::vector< float > EMoR
Definition: deghosting.h:48
const uint16_t THRESHOLD_DONTCARE
Definition: threshold.h:29
const uint16_t ADV_GAMMA
Definition: deghosting.h:51
static uint16_t debugFlags
static uint16_t otherFlags
static void usage()
Definition: Main.cpp:32
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:920
void parseOptions_save(char *optarg)
function handling save options
void parseOptions_advanced(char *optarg)
function handling advanced options
static uint16_t flags
static double thresholdLim
vigra::Rect2D getOutputROI() const
Definition: deghosting.cpp:63
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