[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

specklefilters.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2007-2014 by Benjamin Seppke */
4 /* Cognitive Systems Group, University of Hamburg, Germany */
5 /* */
6 /************************************************************************/
7 
8 #ifndef VIGRA_SPECKLEFILTER_HXX
9 #define VIGRA_SPECKLEFILTER_HXX
10 
11 #include "basicimage.hxx"
12 #include "inspectimage.hxx"
13 
14 #include "applywindowfunction.hxx"
15 
16 namespace vigra {
17 
18 namespace detail
19 {
20 
21 /**
22  * Helper to store distances in lookuptable (LUT)
23  */
24 vigra::FImage distanceLUT(vigra::Diff2D const & window_shape)
25 {
26  vigra::FImage res(window_shape);
27 
28  int y, x;
29  double w_half = window_shape.x/2.0,
30  h_half = window_shape.y/2.0,
31  x_diff, y_diff;
32 
33  for(y=0; y != window_shape.y; y++)
34  {
35  for(x=0; x != window_shape.x; x++)
36  {
37  x_diff = x-w_half;
38  y_diff = y-h_half;
39  res(x,y) = sqrt(x_diff*x_diff + y_diff*y_diff);
40  }
41  }
42 
43  return res;
44 }
45 
46 } //end namespace detail
47 
48 /*********************************************************************
49  * *
50  * The (Basic) Frost Filter *
51  * *
52  * Parameters: window_shape The size of the filter *
53  * k The damping factor (0,...,1) *
54  *********************************************************************/
55 
56 /**
57  This function tries to reduce the speckle noise of an image by means of applying the
58  basic Frost filter using a window of given size and a damping factor k. The implementation
59  is according to the article by
60  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
61 */
62 //@{
63 
64 /** \brief This function tries to reduce the speckle noise of an image by applying the basic Frost filter.
65 
66  The user has to provide a window size and a damping factor k. The implementation is
67  according to the article by
68  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
69 
70  All restrictions of the called functions \ref applyWindowFunction apply.
71 
72  <b> Preconditions:</b>
73  \code
74  0.0 < k <= 1.0
75  \endcode
76 
77  <b> Declarations:</b>
78 
79  pass 2D array views:
80  \code
81  namespace vigra {
82  template <class T1, class S1,
83  class T2, class S2>
84  void
85  frostFilter(MultiArrayView<2, T1, S1> const & src,
86  MultiArrayView<2, T2, S2> dest,
87  Diff2D window_shape, float k,
88  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
89 
90  }
91  \endcode
92 
93  \deprecatedAPI{frostFilter}
94  pass \ref ImageIterators and \ref DataAccessors :
95  \code
96  namespace vigra {
97  template <class SrcIterator, class SrcAccessor,
98  class DestIterator, class DestAccessor>
99  void frostFilter(SrcIterator supperleft,
100  SrcIterator slowerright, SrcAccessor sa,
101  DestIterator dupperleft, DestAccessor da,
102  Diff2D window_shape, float k,
103  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
104  }
105  \endcode
106  use argument objects in conjunction with \ref ArgumentObjectFactories :
107  \code
108  namespace vigra {
109  template <class SrcIterator, class SrcAccessor,
110  class DestIterator, class DestAccessor>
111  void
112  frostFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
113  pair<DestIterator, DestAccessor> dest,
114  Diff2D window_shape, float k,
115  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
116  }
117  \endcode
118  \deprecatedEnd
119 
120  <b> Usage:</b>
121 
122  <b>\#include</b> <vigra/specklefilters.hxx><br/>
123  Namespace: vigra
124 
125  \code
126  unsigned int w=1000, h=1000;
127  MultiArray<2, float> src(w,h), dest(w,h);
128  ...
129 
130  // apply a (basic) frost filter with a window size of 5x5 and a damping factor of 0.5
131  frostFilter(src, dest, Diff2D(5,5), 0.5);
132  \endcode
133 */
134 
135 doxygen_overloaded_function(template <...> void frostFilter)
136 
137 template<typename VALUETYPE>
138 class FrostFunctor
139 {
140 public:
141  FrostFunctor(Diff2D window_shape, float k)
142  : m_window_shape(window_shape),
143  m_k(k),
144  m_dist(detail::distanceLUT(window_shape))
145  {
146  using namespace vigra;
147  vigra_precondition( k>0 && k<=1 , "vigra::FrostFunctor(): Damping factor k has to be: 0 < k <= 1!");
148  }
149 
150  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
151  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
152  {
153  using namespace vigra;
154 
155  SrcIterator s_ul = s - m_window_shape/2,
156  s_lr = s_ul + m_window_shape;
157 
158  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
159 
160  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
161 
162  /*As defined in: Lopez & Touzi & Nezry: Adaptive speckle filters and scene heterogenity*/
163  VALUETYPE C_I2 = averageAndVariance.variance() / (averageAndVariance.average() * averageAndVariance.average()),
164  sum_m = 0.0,
165  sum_pm = 0.0,
166  m = 0.0,
167 // dist = 0.0,
168  p = 0.0;
169 
170  SrcIterator ys = s_ul;
171  SrcIterator xs = ys;
172 
173  FImage::const_traverser ydist = m_dist.upperLeft();
174  FImage::const_traverser xdist = ydist;
175  FImage::Accessor dist_acc = m_dist.accessor();
176 
177  //convolve mask with each impulse response to compute the result of the frost filter
178  int y, x;
179  for(y=0 ; ys.y!=s_lr.y; ys.y++, ydist.y++, y++)
180  {
181  for(xs=ys, xdist=ydist, x=0; xs.x!=s_lr.x; xs.x++, xdist.x++, x++)
182  {
183  p = s_acc(xs);
184 
185  //impuls response of the frost filter
186  m = exp(-1 * m_k * C_I2 * dist_acc(xdist));
187 
188  //convolve
189  sum_pm += m * p;
190  sum_m += m;
191  }
192  }
193  //normalize
194  d_acc.set(sum_pm/sum_m, d);
195  }
196 
197  Diff2D windowShape() const
198  {
199  return m_window_shape;
200  }
201 
202 private:
203  Diff2D m_window_shape;
204  float m_k;
205  FImage m_dist;
206 };
207 
208 template <class SrcIterator, class SrcAccessor,
209  class DestIterator, class DestAccessor>
210 inline void frostFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
211  DestIterator d_ul, DestAccessor d_acc,
212  Diff2D window_shape, float k,
213  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
214 {
215  FrostFunctor<typename SrcIterator::value_type> func(window_shape, k);
216  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
217 }
218 
219 template <class SrcIterator, class SrcAccessor,
220 class DestIterator, class DestAccessor>
221 inline void frostFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
222  pair<DestIterator, DestAccessor> d,
223  Diff2D window_shape, float k,
224  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
225 {
226  frostFilter(s.first, s.second, s.third,
227  d.first, d.second,
228  window_shape, k,
229  border);
230 }
231 
232 
233 template <class T1, class S1,
234  class T2, class S2>
235 inline void frostFilter(MultiArrayView<2, T1, S1> const & src,
237  Diff2D window_shape, float k,
238  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
239 {
240  vigra_precondition(src.shape() == dest.shape(),
241  "vigra::frostFilter(): Shape mismatch between input and output.");
242  frostFilter(srcImageRange(src),
243  destImage(dest),
244  window_shape, k,
245  border);
246 }
247 
248 
249 /*********************************************************************
250  * *
251  * The Enhanced Frost Filter *
252  * *
253  * Parameters: window_shape The size of the filter *
254  * k The damping factor (0,...,1) *
255  * enl Eq. Num. Looks for comp. of *
256  * the thresholds C_u and C_max *
257  *********************************************************************/
258 
259 /**
260  This function tries to reduce the speckle noise of an image by means of applying the
261  enhanced Frost filter using a window of given size, a damping factor k, and the equivalent
262  numbers of look (enl). The implementation is according to the article by
263  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
264 */
265 
266 /** \brief This function tries to reduce the speckle noise of an image by applying the Enhanced Frost filter.
267 
268  The user has to provide a window size, a damping factor k, and the equivalent
269  numbers of look (enl). The implementation is according to the article by
270  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
271 
272  All restrictions of the called functions \ref applyWindowFunction apply.
273 
274  <b> Preconditions:</b>
275  \code
276  1. 0.0 < k <= 1.0
277  2. enl > 0
278  \endcode
279 
280  <b> Declarations:</b>
281 
282  pass 2D array views:
283  \code
284  namespace vigra {
285  template <class T1, class S1,
286  class T2, class S2>
287  void
288  enhancedFrostFilter(MultiArrayView<2, T1, S1> const & src,
289  MultiArrayView<2, T2, S2> dest,
290  Diff2D window_shape, float k, int enl,
291  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
292 
293  }
294  \endcode
295 
296  \deprecatedAPI{enhancedFrostFilter}
297  pass \ref ImageIterators and \ref DataAccessors :
298  \code
299  namespace vigra {
300  template <class SrcIterator, class SrcAccessor,
301  class DestIterator, class DestAccessor>
302  void enhancedFrostFilter(SrcIterator supperleft,
303  SrcIterator slowerright, SrcAccessor sa,
304  DestIterator dupperleft, DestAccessor da,
305  Diff2D window_shape, float k, int enl,
306  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
307  }
308  \endcode
309  use argument objects in conjunction with \ref ArgumentObjectFactories :
310  \code
311  namespace vigra {
312  template <class SrcIterator, class SrcAccessor,
313  class DestIterator, class DestAccessor>
314  void
315  enhancedFrostFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
316  pair<DestIterator, DestAccessor> dest,
317  Diff2D window_shape, float k, int enl,
318  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
319  }
320  \endcode
321  \deprecatedEnd
322 
323  <b> Usage:</b>
324 
325  <b>\#include</b> <vigra/specklefilters.hxx><br/>
326  Namespace: vigra
327 
328  \code
329  unsigned int w=1000, h=1000;
330  MultiArray<2, float> src(w,h), dest(w,h);
331  ...
332 
333  // apply an enhanced frost filter with a window size of 5x5 and a damping factor of 0.5, where
334  // the image was composed by 3 equivalent looks:
335  enhancedFrostFilter(src, dest, Diff2D(5,5), 0.5, 3);
336  \endcode
337 */
338 
339 template<typename VALUETYPE>
341 {
342 public:
343  EnhancedFrostFunctor(Diff2D window_shape, float k, int enl)
344  : m_window_shape(window_shape),
345  m_k(k),
346  m_enl(enl),
347  m_dist(detail::distanceLUT(window_shape))
348 
349  {
350  using namespace vigra;
351  vigra_precondition( k>0 && k<=1 , "vigra::EnhancedFrostFunctor(): Damping factor k has to be: 0 < k <= 1!");
352  vigra_precondition( enl>0, "vigra::EnhancedFrostFunctor(): Equivalent number of looks (enl) must be larger than zero!");
353  }
354 
355  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
356  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
357  {
358  using namespace vigra;
359 
360  SrcIterator s_ul = s - m_window_shape/2,
361  s_lr = s_ul + m_window_shape;
362 
363  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
364 
365  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
366 
367  /*As defined in: Lopez & Touzi & Nezry: Adaptive speckle filters and scene heterogenity*/
368  /* With ENL -> C_u and ENL -> C_max from ENVI: online_help/Using_Adaptive_Filters.html */
369  VALUETYPE C_u = 0.523/sqrt((double)m_enl),
370  C_max = sqrt(1+2.0/m_enl),
371  C_I = sqrt(averageAndVariance.variance()) / averageAndVariance.average(),
372  sum_m = 0.0,
373  sum_pm = 0.0,
374  m = 0.0,
375 // dist = 0.0,
376  p = 0.0;
377 
378  SrcIterator ys = s_ul;
379  SrcIterator xs = ys;
380 
381  FImage::const_traverser ydist = m_dist.upperLeft();
382  FImage::const_traverser xdist = ydist;
383  FImage::Accessor dist_acc = m_dist.accessor();
384 
385  //convolve mask with each impulse response to compute the result of the frost filter
386  int y, x;
387  for(y=0 ; ys.y!=s_lr.y; ys.y++, ydist.y++, y++)
388  {
389  for(xs=ys, xdist=ydist, x=0; xs.x!=s_lr.x; xs.x++, xdist.x++, x++)
390  {
391  p = s_acc(xs);
392 
393  //impuls response of the frost filter
394  m = exp(-m_k * func(C_I, C_max, C_u) * dist_acc(xdist));
395 
396  //convolve
397  sum_pm += m * p;
398  sum_m += m;
399  }
400  }
401  //normalize
402  d_acc.set(sum_pm/sum_m, d);
403  }
404 
405  Diff2D windowShape() const
406  {
407  return m_window_shape;
408  }
409 
410 private:
411  //The penalisier function:
412  //As defined in: Shi & Fung: A comparison of Digital Speckle Filters
413  inline double func(double C_I, double C_max, double C_u) const
414  {
415  if(C_I < C_u)
416  {
417  return 0;
418  }
419  else if (C_I <= C_max)
420  {
421  return (C_I - C_u)/(C_max - C_I);
422  }
423  else
424  {
425  return 1.0e100;
426  }
427  }
428 
429  Diff2D m_window_shape;
430  float m_k;
431  int m_enl;
432  FImage m_dist;
433 };
434 
435 template <class SrcIterator, class SrcAccessor,
436  class DestIterator, class DestAccessor>
437 inline void enhancedFrostFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
438  DestIterator d_ul, DestAccessor d_acc,
439  Diff2D window_shape, float k, int enl,
440  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
441 {
443  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
444 }
445 
446 template <class SrcIterator, class SrcAccessor,
447  class DestIterator, class DestAccessor>
448 inline void enhancedFrostFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
449  pair<DestIterator, DestAccessor> d,
450  Diff2D window_shape, float k, int enl,
451  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
452 {
453  enhancedFrostFilter(s.first, s.second, s.third,
454  d.first, d.second,
455  window_shape, k, enl,
456  border);
457 }
458 
459 
460 template <class T1, class S1,
461  class T2, class S2>
462 inline void enhancedFrostFilter(MultiArrayView<2, T1, S1> const & src,
464  Diff2D window_shape, float k, int enl,
465  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
466 {
467  vigra_precondition(src.shape() == dest.shape(),
468  "vigra::enhancedFrostFilter(): Shape mismatch between input and output.");
469  enhancedFrostFilter(srcImageRange(src),
470  destImage(dest),
471  window_shape, k, enl,
472  border);
473 }
474 
475 
476 
477 /*********************************************************************
478  * *
479  * The Gamma Maximum A Posteriori (MAP) Filter *
480  * *
481  * Parameters: window_shape The size of the filter *
482  * enl Eq. Num. Looks for comp. of *
483  * the thresholds C_u and C_max *
484  *********************************************************************/
485 
486 /**
487  This function tries to reduce the speckle noise of an image by means of applying the
488  Gamma Maximum A Posteriori (MAP) filter using a window of given size, and the equivalent
489  numbers of look (enl). The implementation is according to the article by
490  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
491 */
492 
493 /** \brief This function tries to reduce the speckle noise of an image by applying the Gamma Maximum A Posteriori (MAP) filter.
494 
495  The user has to provide a window size and the equivalent numbers of look (enl).
496  The implementation is according to the article by
497  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
498 
499  All restrictions of the called functions \ref applyWindowFunction apply.
500 
501  <b> Preconditions:</b>
502  \code
503  enl > 0
504  \endcode
505 
506  <b> Declarations:</b>
507 
508  pass 2D array views:
509  \code
510  namespace vigra {
511  template <class T1, class S1,
512  class T2, class S2>
513  void
514  gammaMAPFilter(MultiArrayView<2, T1, S1> const & src,
515  MultiArrayView<2, T2, S2> dest,
516  Diff2D window_shape, int enl,
517  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
518 
519  }
520  \endcode
521 
522  \deprecatedAPI{gammaMAPFilter}
523  pass \ref ImageIterators and \ref DataAccessors :
524  \code
525  namespace vigra {
526  template <class SrcIterator, class SrcAccessor,
527  class DestIterator, class DestAccessor>
528  void gammaMAPFilter(SrcIterator supperleft,
529  SrcIterator slowerright, SrcAccessor sa,
530  DestIterator dupperleft, DestAccessor da,
531  Diff2D window_shape, int enl,
532  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
533  }
534  \endcode
535  use argument objects in conjunction with \ref ArgumentObjectFactories :
536  \code
537  namespace vigra {
538  template <class SrcIterator, class SrcAccessor,
539  class DestIterator, class DestAccessor>
540  void
541  gammaMAPFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
542  pair<DestIterator, DestAccessor> dest,
543  Diff2D window_shape, int enl,
544  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
545  }
546  \endcode
547  \deprecatedEnd
548 
549  <b> Usage:</b>
550 
551  <b>\#include</b> <vigra/specklefilters.hxx><br/>
552  Namespace: vigra
553 
554  \code
555  unsigned int w=1000, h=1000;
556  MultiArray<2, float> src(w,h), dest(w,h);
557  ...
558 
559  // apply a Gamma MAP filter with a window size of 5x5, where
560  // the image was composed by 3 equivalent looks:
561  gammaMAPFilter(src, dest, Diff2D(5,5), 3);
562  \endcode
563 */
564 
565 template<typename VALUETYPE>
567 {
568 public:
569  GammaMAPFunctor(Diff2D window_shape, int enl)
570  : m_window_shape(window_shape),
571  m_enl(enl)
572  {
573  using namespace vigra;
574  vigra_precondition( enl>0, "vigra::GamaMAPFunctor(): Equivalent number of looks (enl) must be larger than zero!");
575  }
576 
577  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
578  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
579  {
580  using namespace vigra;
581 
582  SrcIterator s_ul = s - m_window_shape/2,
583  s_lr = s_ul + m_window_shape;
584 
585  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
586  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
587 
588  //As defined in: Shi & Fung: A comparison of Digital Speckle Filters
589  /* With ENL -> C_u and ENL -> C_max from ENVI: online_help/Using_Adaptive_Filters.html */
590  VALUETYPE C_u = 0.523/sqrt((double)m_enl),
591  C_max = sqrt(1+2.0/m_enl),
592  I_mean = averageAndVariance.average(),
593  C_I = sqrt(averageAndVariance.variance()) / I_mean;
594 
595  if(C_I <= C_u)
596  {
597  d_acc.set(averageAndVariance.average(), d);
598  }
599  else if(C_I < C_max)
600  {
601  double alpha = (1 + C_u*C_u) / (C_I*C_I - C_u*C_u),
602  aL1 = alpha - m_enl - 1,
603  result = (aL1 * I_mean + sqrt(I_mean*I_mean * aL1*aL1 + 4*alpha*m_enl*I_mean))
604  / (2 * alpha);
605  d_acc.set(result, d);
606  }
607  else {
608  d_acc.set(s_acc(s), d);
609  }
610 
611  }
612 
613  Diff2D windowShape() const
614  {
615  return m_window_shape;
616  }
617 
618 private:
619  Diff2D m_window_shape;
620  int m_enl;
621 };
622 
623 
624 template <class SrcIterator, class SrcAccessor,
625  class DestIterator, class DestAccessor>
626 inline void gammaMAPFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
627  DestIterator d_ul, DestAccessor d_acc,
628  Diff2D window_shape, int enl,
629  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
630 {
632  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
633 }
634 
635 template <class SrcIterator, class SrcAccessor,
636  class DestIterator, class DestAccessor>
637 inline void gammaMAPFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
638  pair<DestIterator, DestAccessor> d,
639  Diff2D window_shape, int enl,
640  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
641 {
642  gammaMAPFilter(s.first, s.second, s.third,
643  d.first, d.second,
644  window_shape, enl,
645  border);
646 }
647 
648 template <class T1, class S1,
649  class T2, class S2>
650 inline void gammaMAPFilter(MultiArrayView<2, T1, S1> const & src,
652  Diff2D window_shape, int enl,
653  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
654 {
655  vigra_precondition(src.shape() == dest.shape(),
656  "vigra::gammaMAPFilter(): Shape mismatch between input and output.");
657  gammaMAPFilter(srcImageRange(src),
658  destImage(dest),
659  window_shape, enl,
660  border);
661 }
662 
663 
664 
665 /*********************************************************************
666  * *
667  * The Kuan Filter (with parameter window_shape) *
668  * *
669  * Parameters: window_shape The size of the filter *
670  * enl Eq. Num. Looks *
671  *********************************************************************/
672 
673 /**
674  This function tries to reduce the speckle noise of an image by means of applying the
675  Kuan filter using a window of given size, and the equivalent
676  numbers of look (enl). The implementation is according to the article by
677  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
678 */
679 
680 /** \brief This function tries to reduce the speckle noise of an image by applying the Kuan filter.
681 
682  The user has to provide a window size and the equivalent numbers of look (enl).
683  The implementation is according to the article by
684  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
685 
686  All restrictions of the called functions \ref applyWindowFunction apply.
687 
688  <b> Preconditions:</b>
689  \code
690  enl > 0
691  \endcode
692 
693  <b> Declarations:</b>
694 
695  pass 2D array views:
696  \code
697  namespace vigra {
698  template <class T1, class S1,
699  class T2, class S2>
700  void
701  kuanFilter(MultiArrayView<2, T1, S1> const & src,
702  MultiArrayView<2, T2, S2> dest,
703  Diff2D window_shape, int enl,
704  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
705 
706  }
707  \endcode
708 
709  \deprecatedAPI{kuanFilter}
710  pass \ref ImageIterators and \ref DataAccessors :
711  \code
712  namespace vigra {
713  template <class SrcIterator, class SrcAccessor,
714  class DestIterator, class DestAccessor>
715  void kuanFilter(SrcIterator supperleft,
716  SrcIterator slowerright, SrcAccessor sa,
717  DestIterator dupperleft, DestAccessor da,
718  Diff2D window_shape, int enl,
719  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
720  }
721  \endcode
722  use argument objects in conjunction with \ref ArgumentObjectFactories :
723  \code
724  namespace vigra {
725  template <class SrcIterator, class SrcAccessor,
726  class DestIterator, class DestAccessor>
727  void
728  kuanFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
729  pair<DestIterator, DestAccessor> dest,
730  Diff2D window_shape, int enl,
731  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
732  }
733  \endcode
734  \deprecatedEnd
735 
736  <b> Usage:</b>
737 
738  <b>\#include</b> <vigra/specklefilters.hxx><br/>
739  Namespace: vigra
740 
741  \code
742  unsigned int w=1000, h=1000;
743  MultiArray<2, float> src(w,h), dest(w,h);
744  ...
745 
746  // apply a Kuan filter with a window size of 5x5, where
747  // the image was composed by 3 equivalent looks:
748  kuanFilter(src, dest, Diff2D(5,5), 3);
749  \endcode
750 */
751 template<typename VALUETYPE>
753 {
754 public:
755  KuanFunctor(Diff2D window_shape, int enl)
756  : m_window_shape(window_shape),
757  m_enl(enl)
758  {
759  using namespace vigra;
760  vigra_precondition( enl>0, "vigra::KuanFunctor(): Equivalent number of looks (enl) must be larger than zero!");
761  }
762 
763  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
764  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
765  {
766  using namespace vigra;
767 
768  SrcIterator s_ul = s - m_window_shape/2,
769  s_lr = s_ul + m_window_shape;
770 
771  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
772  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
773 
774  /*As defined in: Lopez & Touzi & Nezry: Adaptive speckle filters and scene heterogenity*/
775  VALUETYPE /*C_u2 = m_var_u/(m_mean_u*m_mean_u),*/
776  C_u2 = (0.523*0.523)/m_enl,
777  C_I2 = averageAndVariance.variance() / (averageAndVariance.average()*averageAndVariance.average()),
778  W = (1 - C_u2/C_I2)/(1 + C_u2),
779  I = s_acc(s),
780  R = I * W + averageAndVariance.average() * (1 - W);
781 
782  d_acc.set(R, d);
783  }
784 
785  Diff2D windowShape() const
786  {
787  return m_window_shape;
788  }
789 
790 private:
791  Diff2D m_window_shape;
792  int m_enl;
793 };
794 
795 template <class SrcIterator, class SrcAccessor,
796 class DestIterator, class DestAccessor>
797 inline void kuanFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
798  DestIterator d_ul, DestAccessor d_acc,
799  Diff2D window_shape, int enl,
800  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
801 {
802  KuanFunctor<typename SrcIterator::value_type> func(window_shape, enl);
803  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
804 }
805 
806 template <class SrcIterator, class SrcAccessor,
807 class DestIterator, class DestAccessor>
808 inline void kuanFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
809  pair<DestIterator, DestAccessor> d,
810  Diff2D window_shape, int enl,
811  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
812 {
813  kuanFilter(s.first, s.second, s.third,
814  d.first, d.second,
815  window_shape, enl,
816  border);
817 }
818 
819 template <class T1, class S1,
820  class T2, class S2>
821 inline void kuanFilter(MultiArrayView<2, T1, S1> const & src,
823  Diff2D window_shape, int enl,
824  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
825 {
826  vigra_precondition(src.shape() == dest.shape(),
827  "vigra::kuanFilter(): Shape mismatch between input and output.");
828  kuanFilter(srcImageRange(src),
829  destImage(dest),
830  window_shape, enl,
831  border);
832 }
833 
834 
835 /*********************************************************************
836  * *
837  * The (Basic) Lee Filter *
838  * *
839  * Parameters: window_shape The size of the filter *
840  * enl Eq. Num. Looks *
841  *********************************************************************/
842 
843 /**
844  This function tries to reduce the speckle noise of an image by means of applying the
845  (basic) Lee filter using a window of given size, and the equivalent
846  numbers of look (enl). The implementation is according to the article by
847  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
848 */
849 
850 /** \brief This function tries to reduce the speckle noise of an image by applying the basic Lee filter.
851 
852  The user has to provide a window size and the equivalent numbers of look (enl).
853  The implementation is according to the article by
854  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
855 
856  All restrictions of the called functions \ref applyWindowFunction apply.
857 
858  <b> Preconditions:</b>
859  \code
860  enl > 0
861  \endcode
862 
863  <b> Declarations:</b>
864 
865  pass 2D array views:
866  \code
867  namespace vigra {
868  template <class T1, class S1,
869  class T2, class S2>
870  void
871  leeFilter(MultiArrayView<2, T1, S1> const & src,
872  MultiArrayView<2, T2, S2> dest,
873  Diff2D window_shape, int enl,
874  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
875 
876  }
877  \endcode
878 
879  \deprecatedAPI{leeFilter}
880  pass \ref ImageIterators and \ref DataAccessors :
881  \code
882  namespace vigra {
883  template <class SrcIterator, class SrcAccessor,
884  class DestIterator, class DestAccessor>
885  void leeFilter(SrcIterator supperleft,
886  SrcIterator slowerright, SrcAccessor sa,
887  DestIterator dupperleft, DestAccessor da,
888  Diff2D window_shape, int enl,
889  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
890  }
891  \endcode
892  use argument objects in conjunction with \ref ArgumentObjectFactories :
893  \code
894  namespace vigra {
895  template <class SrcIterator, class SrcAccessor,
896  class DestIterator, class DestAccessor>
897  void
898  leeFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
899  pair<DestIterator, DestAccessor> dest,
900  Diff2D window_shape, int enl,
901  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
902  }
903  \endcode
904  \deprecatedEnd
905 
906  <b> Usage:</b>
907 
908  <b>\#include</b> <vigra/specklefilters.hxx><br/>
909  Namespace: vigra
910 
911  \code
912  unsigned int w=1000, h=1000;
913  MultiArray<2, float> src(w,h), dest(w,h);
914  ...
915 
916  // apply a basic Lee filter with a window size of 5x5, where
917  // the image was composed by 3 equivalent looks:
918  leeFilter(src, dest, Diff2D(5,5), 3);
919  \endcode
920 */
921 template<typename VALUETYPE = float>
923 {
924 public:
925  LeeFunctor(Diff2D window_shape, int enl)
926  : m_window_shape(window_shape),
927  m_enl(enl)
928  {
929  using namespace vigra;
930  vigra_precondition( enl>0, "vigra::LeeFunctor(): Equivalent number of looks (enl) must be larger than zero!");
931  }
932 
933 
934  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
935  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
936  {
937  using namespace vigra;
938 
939  SrcIterator s_ul = s - m_window_shape/2,
940  s_lr = s_ul + m_window_shape;
941 
942  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
943  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
944 
945  /*As defined in: Lopez & Touzi & Nezry: Adaptive speckle filters and scene heterogenity*/
946  VALUETYPE C_u2 = (0.523*0.523)/m_enl,
947  C_I2 = averageAndVariance.variance() / (averageAndVariance.average()*averageAndVariance.average()),
948  W = (1.0 - C_u2/C_I2),
949  I = s_acc(s),
950  R = I * W + averageAndVariance.average() * (1 - W);
951 
952  d_acc.set(R, d);
953  }
954 
955  Diff2D windowShape() const
956  {
957  return m_window_shape;
958  }
959 
960 private:
961  Diff2D m_window_shape;
962  int m_enl;
963 };
964 
965 template <class SrcIterator, class SrcAccessor,
966 class DestIterator, class DestAccessor>
967 void leeFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
968  DestIterator d_ul, DestAccessor d_acc,
969  Diff2D window_shape, int enl,
970  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
971 {
972  LeeFunctor<typename SrcIterator::value_type> func(window_shape, enl);
973  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
974 }
975 
976 template <class SrcIterator, class SrcAccessor,
977 class DestIterator, class DestAccessor>
978 void leeFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
979  pair<DestIterator, DestAccessor> d,
980  Diff2D window_shape, int enl,
981  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
982 {
983  leeFilter(s.first, s.second, s.third,
984  d.first, d.second,
985  window_shape, enl,
986  border);
987 }
988 
989 template <class T1, class S1,
990  class T2, class S2>
991 inline void leeFilter(MultiArrayView<2, T1, S1> const & src,
993  Diff2D window_shape, int enl,
994  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
995 {
996  vigra_precondition(src.shape() == dest.shape(),
997  "vigra::leeFilter(): Shape mismatch between input and output.");
998  leeFilter(srcImageRange(src),
999  destImage(dest),
1000  window_shape, enl,
1001  border);
1002 }
1003 
1004 
1005 /*********************************************************************
1006  * *
1007  * The Enhanced Lee Filter *
1008  * *
1009  * Parameters: window_shape The size of the filter *
1010  * k The damping factor (0,...,1) *
1011  * enl Eq. Num. Looks for comp. of *
1012  * the thresholds C_u and C_max *
1013  *********************************************************************/
1014 
1015 /**
1016  This function tries to reduce the speckle noise of an image by means of applying the
1017  enhanced Lee filter using a window of given size, a damping factor k, and the equivalent
1018  numbers of look (enl). The implementation is according to the article by
1019  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
1020 */
1021 
1022 /** \brief This function tries to reduce the speckle noise of an image by applying the Enhanced Lee filter.
1023 
1024  The user has to provide a window size, a damping factor k, and the equivalent
1025  numbers of look (enl). The implementation is according to the article by
1026  Lopez & Touzi & Nezry (1990): Adaptive speckle filters and scene heterogenity.
1027 
1028  All restrictions of the called functions \ref applyWindowFunction apply.
1029 
1030  <b> Preconditions:</b>
1031  \code
1032  1. 0.0 < k <= 1.0
1033  2. enl > 0
1034  \endcode
1035 
1036  <b> Declarations:</b>
1037 
1038  pass 2D array views:
1039  \code
1040  namespace vigra {
1041  template <class T1, class S1,
1042  class T2, class S2>
1043  void
1044  enhancedLeeFilter(MultiArrayView<2, T1, S1> const & src,
1045  MultiArrayView<2, T2, S2> dest,
1046  Diff2D window_shape, float k, int enl,
1047  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
1048 
1049  }
1050  \endcode
1051 
1052  \deprecatedAPI{enhancedLeeFilter}
1053  pass \ref ImageIterators and \ref DataAccessors :
1054  \code
1055  namespace vigra {
1056  template <class SrcIterator, class SrcAccessor,
1057  class DestIterator, class DestAccessor>
1058  void enhancedLeeFilter(SrcIterator supperleft,
1059  SrcIterator slowerright, SrcAccessor sa,
1060  DestIterator dupperleft, DestAccessor da,
1061  Diff2D window_shape, float k, int enl,
1062  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
1063  }
1064  \endcode
1065  use argument objects in conjunction with \ref ArgumentObjectFactories :
1066  \code
1067  namespace vigra {
1068  template <class SrcIterator, class SrcAccessor,
1069  class DestIterator, class DestAccessor>
1070  void
1071  enhancedLeeFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
1072  pair<DestIterator, DestAccessor> dest,
1073  Diff2D window_shape, float k, int enl,
1074  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
1075  }
1076  \endcode
1077  \deprecatedEnd
1078 
1079  <b> Usage:</b>
1080 
1081  <b>\#include</b> <vigra/specklefilters.hxx><br/>
1082  Namespace: vigra
1083 
1084  \code
1085  unsigned int w=1000, h=1000;
1086  MultiArray<2, float> src(w,h), dest(w,h);
1087  ...
1088 
1089  // apply an enhanced Lee filter with a window size of 5x5 and a damping factor of 0.5, where
1090  // the image was composed by 3 equivalent looks:
1091  enhancedLeeFilter(src, dest, Diff2D(5,5), 0.5, 3);
1092  \endcode
1093 */
1094 
1095 template<typename VALUETYPE>
1097 {
1098 public:
1099  EnhancedLeeFunctor(Diff2D window_shape, float k, int enl)
1100  : m_window_shape(window_shape),
1101  m_k(k),
1102  m_enl(enl)
1103  {
1104  using namespace vigra;
1105  vigra_precondition( k>0 && k<=1 , "vigra::EnhancedLeeFunctor(): Damping factor k has to be: 0 < k <= 1!");
1106  vigra_precondition( enl>0, "vigra::EnhancedLeeFunctor(): Equivalent number of looks (enl) must be larger than zero!");
1107  }
1108 
1109  template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
1110  void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
1111  {
1112  using namespace vigra;
1113 
1114  SrcIterator s_ul = s - m_window_shape/2,
1115  s_lr = s_ul + m_window_shape;
1116 
1117 
1118  FindAverageAndVariance<VALUETYPE> averageAndVariance; // init functor
1119  inspectImage(s_ul, s_lr, s_acc, averageAndVariance);
1120 
1121  /*As defined in: Lopez & Touzi & Nezry: Adaptive speckle filters and scene heterogenity*/
1122  /* With ENL -> C_u and ENL -> C_max from ENVI: online_help/Using_Adaptive_Filters.html */
1123  VALUETYPE C_u = 0.523/sqrt((double)m_enl),
1124  C_max = sqrt(1+2.0/m_enl),
1125  C_A = sqrt(averageAndVariance.variance()) / averageAndVariance.average(),
1126  W = exp(-m_k * (C_A - C_u)/(C_max - C_A)),
1127  I = s_acc(s);
1128 
1129  if( C_A <= C_u )
1130  {
1131  d_acc.set(averageAndVariance.average(), d);
1132  }
1133  else if(C_A < C_max)
1134  {
1135  d_acc.set(I * W + averageAndVariance.average() * (1 - W), d);
1136  }
1137  else {
1138  d_acc.set(I, d);
1139  }
1140  }
1141 
1142  Diff2D windowShape() const
1143  {
1144  return m_window_shape;
1145  }
1146 
1147 private:
1148 
1149  Diff2D m_window_shape;
1150  float m_k;
1151  int m_enl;
1152 };
1153 
1154 template <class SrcIterator, class SrcAccessor,
1155  class DestIterator, class DestAccessor>
1156 void enhancedLeeFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
1157  DestIterator d_ul, DestAccessor d_acc,
1158  Diff2D window_shape, float k, int enl,
1159  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
1160 {
1161  EnhancedLeeFunctor<typename SrcIterator::value_type> func(window_shape, k, enl);
1162  applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
1163 }
1164 
1165 template <class SrcIterator, class SrcAccessor,
1166  class DestIterator, class DestAccessor>
1167 void enhancedLeeFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
1168  pair<DestIterator, DestAccessor> d,
1169  Diff2D window_shape, float k, int enl,
1170  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
1171 {
1172  enhancedLeeFilter(s.first, s.second, s.third,
1173  d.first, d.second,
1174  window_shape, k, enl,
1175  border);
1176 }
1177 
1178 template <class T1, class S1,
1179  class T2, class S2>
1180 inline void enhancedLeeFilter(MultiArrayView<2, T1, S1> const & src,
1182  Diff2D window_shape, float k, int enl,
1183  BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
1184 {
1185  vigra_precondition(src.shape() == dest.shape(),
1186  "vigra::enhancedLeeFilter(): Shape mismatch between input and output.");
1187  enhancedLeeFilter(srcImageRange(src),
1188  destImage(dest),
1189  window_shape, k, enl,
1190  border);
1191 }
1192 
1193 //@}
1194 
1195 } //end of namespace vigra
1196 
1197 #endif //VIGRA_SPECKLEFILTERS_HXX
This function tries to reduce the speckle noise of an image by applying the basic Lee filter...
Definition: specklefilters.hxx:922
int y
Definition: diff2d.hxx:392
const difference_type & shape() const
Definition: multi_array.hxx:1648
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
int x
Definition: diff2d.hxx:385
Two dimensional difference vector.
Definition: diff2d.hxx:185
This function tries to reduce the speckle noise of an image by applying the Enhanced Lee filter...
Definition: specklefilters.hxx:1096
This function tries to reduce the speckle noise of an image by applying the Gamma Maximum A Posterior...
Definition: specklefilters.hxx:566
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
This function tries to reduce the speckle noise of an image by applying the Kuan filter.
Definition: specklefilters.hxx:752
Definition: basicimage.hxx:294
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
This function tries to reduce the speckle noise of an image by applying the Enhanced Frost filter...
Definition: specklefilters.hxx:340
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
void inspectImage(...)
Apply read-only functor to every pixel in the image.
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
void applyWindowFunction(...)
Apply a window function to each pixels of a given image.
Find the average pixel value and its variance in an image or ROI.
Definition: inspectimage.hxx:1401
void frostFilter(...)
This function tries to reduce the speckle noise of an image by applying the basic Frost filter...

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)