Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VignettingCorrection.h
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
24 #ifndef VIGRA_EXT_VIGNETTING_CORRECTION_H
25 #define VIGRA_EXT_VIGNETTING_CORRECTION_H
26 
27 #include <vector>
28 #include <functional>
29 #include "hugin_config.h"
30 
31 #include <vigra/stdimage.hxx>
32 #include <vigra/transformimage.hxx>
33 #include <vigra/inspectimage.hxx>
34 #include <vigra/combineimages.hxx>
35 #include <vigra/functorexpression.hxx>
36 
37 #include <vigra_ext/utils.h>
38 
39 #include <random>
40 
41 //#define DEBUG_WRITE_FILES
42 
43 namespace vigra_ext{
44 
45 template <class VT1, class VT2, class InvResp, class Adjust>
47 {
48 public:
51  typedef VT1 first_argument_type;
52 
55  typedef VT2 second_argument_type;
56 
59  typedef typename vigra::NumericTraits<VT1>::RealPromote result_type;
60 
61  typedef result_type RVT1;
62  typedef typename vigra::NumericTraits<VT2>::RealPromote RVT2;
63 
64  VigCorrFlatDivFunctor(RVT2 mean, const InvResp & fr, const Adjust & adj)
65  : m_InvResp(fr), m_Adjust(adj), m_mean(mean)
66  { }
67 
68  InvResp m_InvResp;
69  Adjust m_Adjust;
71 
75  {
76  // apply inverse response/gamma correction, vignetting correction by
77  // division and possible brightness adjust
78  RVT1 i(m_InvResp(v1));
79  RVT2 corr((v2)/m_mean);
80  i /= corr;
81  return m_Adjust( i );
82  }
83 };
84 
85 template <class VT1, class InvResp, class VigFunc, class Adjust>
87 {
88 public:
91  typedef VT1 first_argument_type;
92 
95  typedef typename vigra::NumericTraits<VT1>::RealPromote result_type;
97 
98  VigCorrDivFunctor(const InvResp & fr, const VigFunc & vf, const Adjust & adj)
99  : m_InvResp(fr), m_VigFunc(vf), m_Adjust(adj)
100  { }
101 
102  InvResp m_InvResp;
103  VigFunc m_VigFunc;
104  Adjust m_Adjust;
105 
108  result_type operator()(first_argument_type const & v1, float x, float y) const
109  {
110  // apply inverse response/gamma correction, vignetting correction by
111  // division and possible brightness adjust
112  return m_Adjust(m_InvResp(v1) / m_VigFunc(x,y));
113  }
114 };
115 
116 
117 
118 template <class VT1, class VT2, class InvResp, class Adjust>
120 {
121 public:
124  typedef VT1 first_argument_type;
125 
128  typedef VT2 second_argument_type;
129 
132  typedef typename vigra::NumericTraits<VT1>::RealPromote result_type;
133 
135  typedef typename vigra::NumericTraits<VT2>::RealPromote RVT2;
136 
137  VigCorrFlatAddFunctor(const InvResp & fr, const Adjust & adj)
138  : m_InvResp(fr), m_Adjust(adj)
139  { }
140 
141  InvResp m_InvResp;
142  Adjust m_Adjust;
143 
147  {
148  // apply inverse response/gamma correction, vignetting correction by
149  // division and possible brightness adjust
150  return m_Adjust(m_InvResp(v1) + v2);
151  }
152 };
153 
154 template <class VT1, class InvResp, class VigFunc, class Adjust>
156 {
157 public:
160  typedef VT1 first_argument_type;
161 
164  typedef typename vigra::NumericTraits<VT1>::RealPromote result_type;
165 
167 
168  VigCorrAddFunctor(const InvResp & fr, const VigFunc & vf, const Adjust & adj)
169  : m_InvResp(fr), m_VigFunc(vf), m_Adjust(adj)
170  { }
171 
172  InvResp m_InvResp;
173  VigFunc m_VigFunc;
174  Adjust m_Adjust;
175 
178  result_type operator()(first_argument_type const & v1, float x, float y) const
179  {
180  // apply inverse response/gamma correction, vignetting correction by
181  // division and possible brightness adjust
182  return m_Adjust(m_InvResp(v1) + m_VigFunc(x,y));
183  }
184 };
185 
186 
187 template <int NTERMS=4>
189 {
190  double m_coeff[NTERMS];
191 
192  PolySqDistFunctor(const std::vector<double> & coeff)
193  {
194  for (unsigned int i=0; i<NTERMS; i++) m_coeff[i] = coeff[i];
195  };
196 
197  double operator()(double x, double y) const
198  {
199  double ret = m_coeff[0];
200  double r2 = x*x + y*y;
201  double r = r2;
202  for (unsigned int i = 1; i < NTERMS; i++) {
203  ret += m_coeff[i] * r;
204  r *= r2;
205  }
206  return ret;
207  }
208 };
209 
210 inline bool isTrueType(vigra::VigraFalseType) {
211  return false;
212 }
213 
214 inline bool isTrueType(vigra::VigraTrueType) {
215  return true;
216 }
217 
218 template<class T>
219 bool ditheringNeeded(T const &)
220 {
221  typedef typename vigra::NumericTraits<T>::isIntegral is_integral;
222  return isTrueType(is_integral());
223 }
224 
226  // Dithering is used to fool the eye into seeing gradients that are finer
227  // than the precision of the pixel type.
228  // This prevents the occurence of cleanly-bordered regions in the output where
229  // the pixel values suddenly change from N to N+1.
230  // Such regions are especially objectionable in the green channel of 8-bit images.
231 template <class T>
233 {
234  std::mt19937 Twister;
235 
236  typedef T result_type;
237 
238  // Dithering is used to fool the eye into seeing gradients that are finer
239  // than the precision of the pixel type.
240  // This prevents the occurence of cleanly-bordered regions in the output where
241  // the pixel values suddenly change from N to N+1.
242  // Such regions are especially objectionable in the green channel of 8-bit images.
243  double dither(const double &v) const
244  {
245  std::mt19937 &mt = const_cast<std::mt19937 &>(Twister);
246  double vFraction = v - floor(v);
247  // Only dither values within a certain range of the rounding cutoff point.
248  if (vFraction > 0.25 && vFraction <= 0.75) {
249  // Generate a random number between 0 and 0.5.
250  double random = 0.5 * (double)mt() / UINT_MAX;
251  if ((vFraction - 0.25) >= random) {
252  return ceil(v);
253  } else {
254  return floor(v);
255  }
256  } else {
257  return v;
258  }
259  }
260 
261  // dither vector
262  T dither(const T &v, vigra::VigraFalseType) const
263  {
264  T ret;
265  for (size_t i=0; i < v.size(); i++) {
266  ret[i] = dither(v[i]);
267  }
268  return ret;
269  }
270 
271  // dither scalar type
272  T dither(const T & v, vigra::VigraTrueType) const
273  {
274  return dither(v);
275  }
276 
277  T operator()(const T &v) const
278  {
279  typedef typename vigra::NumericTraits<T>::isScalar is_scalar;
280 
281  return dither(v, is_scalar());
282  }
283 };
284 
285 
286 
288 {
289  double gamma;
290  double maxval;
291  GammaFunctor(double g, double m)
292  : gamma(g), maxval(m)
293  {}
294 
295  template <class T>
296  typename vigra::NumericTraits<T>::RealPromote operator()(T p) const
297  {
298  typedef typename vigra::NumericTraits<T>::RealPromote RT;
299  RT pix(p);
300  pix /= maxval;
301  return vigra_ext::pow(pix, gamma)*maxval;
302 // return vigra::NumericTraits<T>::fromRealPromote(vigra_ext::pow(pix, gamma)*maxval);
303 // return pow(pix, gamma)*maxval;
304  }
305 };
306 
309 template <class PT>
311 {
312  typedef PT result_type;
313 
314  PT m_a;
315  PT m_b;
317  : m_a(a), m_b(b)
318  { };
319 
320  PT operator()(PT p) const
321  {
322  return p * m_a + m_b;
323  }
324 };
325 
326 
327 template <class SrcImageIterator, class SrcAccessor,
328  class DestImageIterator, class DestAccessor, class Functor>
329 void
330 applyRadialVigCorrection(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
331  vigra::pair<DestImageIterator, DestAccessor> dest,
332  double cx, double cy,
333  Functor const & f)
334 {
335  applyRadialVigCorrection(src.first, src.second, src.third, dest.first, dest.second,
336  cx, cy, f);
337 }
338 
339 template <class SrcImageIterator, class SrcAccessor,
340  class DestImageIterator, class DestAccessor, class Functor>
341 void
342 applyRadialVigCorrection(SrcImageIterator src_upperleft,
343  SrcImageIterator src_lowerright, SrcAccessor sa,
344  DestImageIterator dest_upperleft, DestAccessor da,
345  double cx, double cy,
346  Functor const & f)
347 {
348  vigra::Diff2D destSize = src_lowerright - src_upperleft;
349 
350  double sf = 1.0/sqrt(destSize.x/2.0*destSize.x/2.0 + destSize.y/2.0*destSize.y/2.0);
351  double ynorm = -cy * sf;
352 
353  for(; src_upperleft.y < src_lowerright.y; ++src_upperleft.y, ++dest_upperleft.y)
354  {
355  typename SrcImageIterator::row_iterator s(src_upperleft.rowIterator());
356  typename SrcImageIterator::row_iterator send(s+ destSize.x);
357  typename DestImageIterator::row_iterator d(dest_upperleft.rowIterator());
358  double xnorm = -cx*sf;
359  for(; s != send; ++s, ++d) {
360  da.set(f(sa(s), xnorm, ynorm), d);
361  xnorm +=sf;
362  }
363  ynorm += sf;
364  }
365 }
366 
371 template <class SrcImageIterator, class SrcAccessor,
372  class DestImageIterator, class DestAccessor, class Functor>
373 void
374 applyRadialVigCorrectionDither(vigra::triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
375  vigra::pair<DestImageIterator, DestAccessor> dest,
376  double cx, double cy,
377  Functor const & f, bool dither)
378 {
380  if (dither) {
381  DF df;
382  NestFunctor<DF, Functor> nf(df, f);
383  applyRadialVigCorrection(src, dest, cx, cy, nf );
384  } else {
385  applyRadialVigCorrection(src, dest, cx, cy, f);
386  }
387 }
388 
389 
394 template <class ImgIter, class ImgAccessor,
395  class FFIter, class FFAccessor,
396  class DestIter, class DestAccessor,
397  class Functor>
398 void
399 combineTwoImagesDither(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
400  vigra::pair<FFIter, FFAccessor> ffImg,
401  vigra::pair<DestIter, DestAccessor> destImg,
402  Functor const & f, bool dither)
403 {
405  if (dither) {
406  DF df;
407  vigra::combineTwoImages(srcImg, ffImg, destImg,
408  NestFunctor<DF, Functor>(df, f) );
409  } else {
410  vigra::combineTwoImages(srcImg, ffImg, destImg, f);
411  }
412 }
413 
414 
415 template <class ImgIter, class ImgAccessor, class FFIter, class FFAccessor, class DestIter, class DestAccessor>
416 void flatfieldVigCorrection(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
417  vigra::pair<FFIter, FFAccessor> ffImg,
418  vigra::pair<DestIter, DestAccessor> destImg,
419  double gamma, double gammaMaxVal, bool division,
420  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote a,
421  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote b,
422  bool dither)
423 {
424  typedef typename ImgAccessor::value_type PT;
425  typedef typename vigra::NumericTraits<PT>::RealPromote RPT;
426  typedef typename FFAccessor::value_type FFT;
427  typedef typename vigra::NumericTraits<FFT>::RealPromote RFFT;
428 
429  typedef PassThroughFunctor<RPT> RnF;
430  typedef LinearTransformFunctor<RPT> LTF;
431  LTF adjust(a,b);
432 
433  RFFT mean;
434  if (division) {
435  // calculate mean of flatfield image
436  vigra::FindAverage<FFT> average; // init functor
437  vigra::inspectImage(ffImg.first, ffImg.first + (srcImg.second - srcImg.first), ffImg.second, average);
438  mean = average();
439  }
440 
441  if (gamma == 1.0) {
442  RnF Rf;
443  if (division) {
444  combineTwoImagesDither(srcImg, ffImg, destImg,
446  dither);
447  } else {
448  combineTwoImagesDither(srcImg, ffImg, destImg,
450  dither);
451  }
452  } else {
453  GammaFunctor Rf(gamma, gammaMaxVal);
454  if (division) {
455  combineTwoImagesDither(srcImg, ffImg, destImg,
457  dither);
458  } else {
459  combineTwoImagesDither(srcImg, ffImg, destImg,
461  dither);
462  }
463  }
464 }
465 
466 
467 template <class ImgIter, class ImgAccessor, class DestIter, class DestAccessor>
468 void radialVigCorrection(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
469  vigra::pair<DestIter, DestAccessor> destImg, double gamma, double gammaMaxVal,
470  const std::vector<double> & radCoeff, hugin_utils::FDiff2D center, bool division,
471  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote a,
472  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote b,
473  bool dither)
474 {
475  typedef typename ImgAccessor::value_type PT;
476  typedef typename vigra::NumericTraits<PT>::RealPromote RPT;
477 
478  typedef PolySqDistFunctor<4> PolyF;
479  typedef PassThroughFunctor<RPT> RnF;
480  typedef LinearTransformFunctor<RPT> LTF;
481 
482  PolyF poly(radCoeff);
483  LTF adjust(a,b);
484 
485  // adjust functor
486 
487  if (gamma == 1.0) {
488  RnF Rf;
489  if (division) {
490  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
491  VigCorrDivFunctor<PT, RnF, PolyF, LTF>(Rf, poly, adjust),
492  dither);
493  } else {
494  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
495  VigCorrAddFunctor<PT, RnF, PolyF, LTF>(Rf, poly, adjust),
496  dither);
497  }
498  } else {
499  GammaFunctor Rf(gamma, gammaMaxVal);
500  if (division) {
501  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
503  dither);
504  } else {
505  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
507  dither);
508  }
509  }
510 }
511 
512 template <class ImgIter, class ImgAccessor, class DestIter, class DestAccessor>
513 void applyBrightnessCorrection(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
514  vigra::pair<DestIter, DestAccessor> destImg,
515  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote a,
516  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote b)
517 {
518  typedef typename ImgAccessor::value_type PT;
519  typedef typename vigra::NumericTraits<PT>::RealPromote RPT;
520 
521  vigra::transformImage(srcImg, destImg, LinearTransformFunctor<RPT>(a,b));
522 }
523 
524 
525 template <class ImgIter, class ImgAccessor, class DestIter, class DestAccessor>
526 void applyGammaAndBrightCorrection(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
527  vigra::pair<DestIter, DestAccessor> destImg,
528  double gamma, double maxGVal,
529  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote a,
530  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote b)
531 {
532  typedef typename ImgAccessor::value_type PT;
533  typedef typename vigra::NumericTraits<PT>::RealPromote RPT;
534  typedef LinearTransformFunctor<RPT> LTF;
535 
536  LTF ltf(a,b);
537  GammaFunctor gf(gamma, maxGVal);
538  vigra::transformImage(srcImg, destImg, NestFunctor<LTF, GammaFunctor>(ltf, gf));
539 }
540 
541 template <class ImgIter, class ImgAccessor, class DestIter, class DestAccessor>
542 void applyGammaCorrection(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
543  vigra::pair<DestIter, DestAccessor> destImg,
544  double gamma, double maxGVal)
545 {
546  GammaFunctor gf(gamma, maxGVal);
547  vigra::transformImage(srcImg, destImg, gf );
548 }
549 
550 
551 /*
552 template <class ImgIter, class ImgAccessor, class DestIter, class DestAccessor>
553 void correctRespVigExpInv(vigra::triple<ImgIter, ImgIter, ImgAccessor> srcImg,
554  vigra::pair<DestIter, DestAccessor> destImg,
555  const std::vector<double> & EMoRCoeff, double maxGreyVal,
556  const std::vector<double> & radCoeff, hugin_utils::FDiff2D center, bool division,
557  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote a,
558  typename vigra::NumericTraits<typename ImgAccessor::value_type>::RealPromote b,
559  bool dither)
560 {
561  typedef typename ImgAccessor::value_type PT;
562  typedef typename vigra::NumericTraits<PT>::RealPromote RPT;
563  typedef typename ImgAccessor::value_type OutPixelType;
564 
565  typedef PolySqDistFunctor<4> PolyF;
566  typedef PassThroughFunctor<RPT> RnF;
567  typedef LinearTransformFunctor<RPT> LTF;
568 
569  PolyF poly(radCoeff);
570  LTF adjust(a,b);
571 
572  // adjust functor
573 
574  if (EMoRCoeff.empty()) {
575  RnF Rf;
576  if (division) {
577  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
578  VigCorrDivFunctor<PT, RnF, PolyF, LTF>(Rf, poly, adjust),
579  dither);
580  } else {
581  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
582  VigCorrAddFunctor<PT, RnF, PolyF, LTF>(Rf, poly, adjust),
583  dither);
584  }
585  } else {
586  // prepare lookup table
587  // create a camera response lut
588  std::vector<float> lut10;
589  vigra_ext::createEMoRLUT(params, lut10);
590  // create inverse lut
591  std::vector<float> invlut10(1<<10);
592  vigra_ext::invertLUT(lut10, invlut10);
593 
594  GammaFunctor Rf(gamma, gammaMaxVal);
595  if (division) {
596  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
597  VigCorrDivFunctor<PT, GammaFunctor, PolyF, LTF>(Rf, poly, adjust),
598  dither);
599  } else {
600  applyRadialVigCorrectionDither(srcImg, destImg, center.x, center.y,
601  VigCorrAddFunctor<PT, GammaFunctor, PolyF, LTF>(Rf, poly, adjust),
602  dither);
603  }
604  }
605 }
606 
607 */
608 
609 } // namespace
610 
611 #endif // VIGRA_EXT_VIGNETTING_CORRECTION_H
double operator()(double x, double y) const
VigCorrFlatDivFunctor(RVT2 mean, const InvResp &fr, const Adjust &adj)
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.
vigra::NumericTraits< T >::RealPromote operator()(T p) const
VigCorrDivFunctor(const InvResp &fr, const VigFunc &vf, const Adjust &adj)
vigra::NumericTraits< VT1 >::RealPromote result_type
the functor&#39;s result type
VT2 second_argument_type
the functor&#39;s second argument type
PolySqDistFunctor(const std::vector< double > &coeff)
void flatfieldVigCorrection(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< FFIter, FFAccessor > ffImg, vigra::pair< DestIter, DestAccessor > destImg, double gamma, double gammaMaxVal, bool division, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote a, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote b, bool dither)
void radialVigCorrection(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< DestIter, DestAccessor > destImg, double gamma, double gammaMaxVal, const std::vector< double > &radCoeff, hugin_utils::FDiff2D center, bool division, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote a, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote b, bool dither)
result_type operator()(first_argument_type const &v1, float x, float y) const
calculate transform.
vigra::NumericTraits< VT2 >::RealPromote RVT2
VT1 first_argument_type
the functor&#39;s first argument type
T dither(const T &v, vigra::VigraTrueType) const
functions to manage ROI&#39;s
result_type operator()(first_argument_type const &v1, float x, float y) const
calculate transform.
void combineTwoImages(SrcImageIterator1 src1_upperleft, SrcImageIterator1 src1_lowerright, SrcAccessor1 src1_acc, SrcImageIterator2 src2_upperleft, SrcAccessor2 src2_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc, const Functor &func)
Definition: openmp_vigra.h:249
VT1 first_argument_type
the functor&#39;s first argument type
float pow(float a, double b)
Definition: utils.h:181
double dither(const double &v) const
VT1 first_argument_type
the functor&#39;s first argument type
VT2 second_argument_type
the functor&#39;s second argument type
T dither(const T &v, vigra::VigraFalseType) const
functor to combine two functors: result = f1( f2(v) )
Definition: utils.h:431
void applyGammaCorrection(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< DestIter, DestAccessor > destImg, double gamma, double maxGVal)
void applyBrightnessCorrection(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< DestIter, DestAccessor > destImg, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote a, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote b)
result_type operator()(first_argument_type const &v1, second_argument_type const &v2) const
calculate transform.
VigCorrFlatAddFunctor(const InvResp &fr, const Adjust &adj)
void combineTwoImagesDither(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< FFIter, FFAccessor > ffImg, vigra::pair< DestIter, DestAccessor > destImg, Functor const &f, bool dither)
Apply combine two images.
VT1 first_argument_type
the functor&#39;s first argument type
vigra::NumericTraits< VT1 >::RealPromote result_type
the functor&#39;s result type
GammaFunctor(double g, double m)
result_type operator()(first_argument_type const &v1, second_argument_type const &v2) const
calculate transform.
bool isTrueType(vigra::VigraFalseType)
VigCorrAddFunctor(const InvResp &fr, const VigFunc &vf, const Adjust &adj)
T operator()(const T &v) const
Dither code taken from enblend and adapted to a standalone functor.
vigra::NumericTraits< VT1 >::RealPromote result_type
the functor&#39;s result type
vigra::NumericTraits< VT2 >::RealPromote RVT2
bool ditheringNeeded(T const &)
void applyGammaAndBrightCorrection(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra::pair< DestIter, DestAccessor > destImg, double gamma, double maxGVal, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote a, typename vigra::NumericTraits< typename ImgAccessor::value_type >::RealPromote b)
void applyRadialVigCorrectionDither(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::pair< DestImageIterator, DestAccessor > dest, double cx, double cy, Functor const &f, bool dither)
Apply flatfield correction with dithering.
void applyRadialVigCorrection(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::pair< DestImageIterator, DestAccessor > dest, double cx, double cy, Functor const &f)
vigra::NumericTraits< VT1 >::RealPromote result_type
the functor&#39;s result type