vigra - vigra/specklefilters.hxx Source File

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

specklefilters.hxx |

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,
236 MultiArrayView<2, T2, S2> dest,
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>
340 class EnhancedFrostFunctor
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 {
442 EnhancedFrostFunctor<typename SrcIterator::value_type> func(window_shape, k, enl);
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,
463 MultiArrayView<2, T2, S2> dest,
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>
566 class GammaMAPFunctor
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 {
631 GammaMAPFunctor<typename SrcIterator::value_type> func(window_shape, enl);
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,
651 MultiArrayView<2, T2, S2> dest,
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>
752 class KuanFunctor
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,
822 MultiArrayView<2, T2, S2> dest,
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>
922 class LeeFunctor
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,
992 MultiArrayView<2, T2, S2> dest,
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>
1096 class EnhancedLeeFunctor
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,
1181 MultiArrayView<2, T2, S2> dest,
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
vigra::LeeFunctor
This function tries to reduce the speckle noise of an image by applying the basic Lee filter...
Definition: specklefilters.hxx:922
vigra::Diff2D::y
int y
Definition: diff2d.hxx:392
vigra::MultiArrayView::shape
const difference_type & shape() const
Definition: multi_array.hxx:1648
vigra::linalg::exp
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
vigra::Diff2D::x
int x
Definition: diff2d.hxx:385
vigra::Diff2D
Two dimensional difference vector.
Definition: diff2d.hxx:185
vigra::EnhancedLeeFunctor
This function tries to reduce the speckle noise of an image by applying the Enhanced Lee filter...
Definition: specklefilters.hxx:1096
vigra::GammaMAPFunctor
This function tries to reduce the speckle noise of an image by applying the Gamma Maximum A Posterior...
Definition: specklefilters.hxx:566
vigra::doxygen_overloaded_function
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
vigra::KuanFunctor
This function tries to reduce the speckle noise of an image by applying the Kuan filter.
Definition: specklefilters.hxx:752
vigra::BasicImage< float >
vigra::ConstBasicImageIterator
Definition: basicimage.hxx:294
vigra::MultiArrayView
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
vigra::EnhancedFrostFunctor
This function tries to reduce the speckle noise of an image by applying the Enhanced Frost filter...
Definition: specklefilters.hxx:340
vigra::StandardAccessor
Encapsulate access to the values an iterator points to.
Definition: accessor.hxx:133
vigra::inspectImage
void inspectImage(...)
Apply read-only functor to every pixel in the image.
vigra::sqrt
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
vigra::applyWindowFunction
void applyWindowFunction(...)
Apply a window function to each pixels of a given image.
vigra::FindAverageAndVariance
Find the average pixel value and its variance in an image or ROI.
Definition: inspectimage.hxx:1401
vigra::frostFilter
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)