1 /************************************************************************/
2 /* */
3 /* Copyright 2007-2014 by Benjamin Seppke */
4 /* Cognitive Systems Group, University of Hamburg, Germany */
5 /* */
6 /************************************************************************/
7
8 #ifndef VIGRA_MEDIANFILTER_HXX
9 #define VIGRA_MEDIANFILTER_HXX
10
11 #include <vector>
12 #include <algorithm>
13
14 #include "applywindowfunction.hxx"
15
16 namespace vigra
17 {
18
19 /********************************************************/
20 /* */
21 /* Generic median filter */
22 /* */
23 /********************************************************/
24 /**
25 This function calculates the median of a window of given size for the complete image.
26 It also allows a correct border handling, since it uses the \ref applyWindowFunction
27 environment for computation!
28 */
29 //@{
30
31 /** \brief This function calculates the median of a window of given size for the complete image.
32
33 All \ref BorderTreatmentMode "border treatment modes" (except BORDER_TREATMENT_CLIP) are supported.
34
35 The input pixel type <tt>T1</tt> must be a \ref LinearSpace "linear space" over
36 the window functions' value_type <tt>T</tt>. Especially, the values must be sortable by
37 std::sort, to derive the mean values aka the median.
38
39 <b> Declarations:</b>
40
41 pass 2D array views:
42 \code
43 namespace vigra {
44 template <class T1, class S1,
45 class T2, class S2>
46 void
47 medianFilter(MultiArrayView<2, T1, S1> const & src,
48 MultiArrayView<2, T2, S2> dest,
49 Diff2D window_shape,
50 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
51
52 }
53 \endcode
54
55 \deprecatedAPI{medianFilter}
56 pass \ref ImageIterators and \ref DataAccessors :
57 \code
58 namespace vigra {
59 template <class SrcIterator, class SrcAccessor,
60 class DestIterator, class DestAccessor>
61 void medianFilter(SrcIterator supperleft,
62 SrcIterator slowerright, SrcAccessor sa,
63 DestIterator dupperleft, DestAccessor da,
64 Diff2D window_shape,
65 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
66 }
67 \endcode
68 use argument objects in conjunction with \ref ArgumentObjectFactories :
69 \code
70 namespace vigra {
71 template <class SrcIterator, class SrcAccessor,
72 class DestIterator, class DestAccessor>
73 void
74 medianFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
75 pair<DestIterator, DestAccessor> dest,
76 Diff2D window_shape,
77 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT);
78 }
79 \endcode
80 \deprecatedEnd
81
82 <b> Usage:</b>
83
84 <b>\#include</b> \<vigra/medianfilter.hxx\><br/>
85 Namespace: vigra
86
87 \code
88 unsigned int w=1000, h=1000;
89 MultiArray<2, float> src(w,h), dest(w,h);
90 ...
91
92 // apply a median filter with a window size of 5x5
93 medianFilter(src, dest, Diff2D(5,5));
94 \endcode
95
96 <b> Preconditions:</b>
97
98 The image must be larger than the window size of the filter.
99 */
100
101 doxygen_overloaded_function(template <...> void medianFilter)
102
103 template<class VALUETYPE>
104 class MedianFunctor
105 {
106 public:
MedianFunctor(Diff2D window_shape)107 MedianFunctor(Diff2D window_shape)
108 : m_window_shape(window_shape),
109 m_buffer(window_shape.x*window_shape.y)
110 {
111 }
112
113 template <class SrcIterator, class SrcAccessor, class DestIterator, class DestAccessor>
operator ()(SrcIterator s,SrcAccessor s_acc,DestIterator d,DestAccessor d_acc)114 void operator()(SrcIterator s, SrcAccessor s_acc, DestIterator d, DestAccessor d_acc)
115 {
116 SrcIterator s_ul = s - m_window_shape/2,
117 s_lr = s_ul + m_window_shape;
118
119 std::fill(m_buffer.begin(), m_buffer.end(), VALUETYPE());
120
121 SrcIterator ys = s_ul;
122 SrcIterator xs = ys;
123
124 typename std::vector<VALUETYPE>::iterator iter = m_buffer.begin(),
125 median_iter = m_buffer.begin()+m_buffer.size()/2;
126
127 for( ; ys.y != s_lr.y; ys.y++)
128 {
129 for(xs = ys; xs.x != s_lr.x; xs.x++, iter++)
130 {
131 *iter = s_acc(xs);
132 }
133 }
134
135 std::nth_element(m_buffer.begin(), median_iter, m_buffer.end());
136 d_acc.set(*median_iter,d);
137 }
138
windowShape() const139 Diff2D windowShape() const
140 {
141 return m_window_shape;
142 }
143
144 private:
145 Diff2D m_window_shape;
146 std::vector<VALUETYPE> m_buffer;
147 };
148
149
150 template <class SrcIterator, class SrcAccessor,
151 class DestIterator, class DestAccessor>
medianFilter(SrcIterator s_ul,SrcIterator s_lr,SrcAccessor s_acc,DestIterator d_ul,DestAccessor d_acc,Diff2D window_shape,BorderTreatmentMode border=BORDER_TREATMENT_REPEAT)152 inline void medianFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
153 DestIterator d_ul, DestAccessor d_acc,
154 Diff2D window_shape,
155 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
156 {
157 MedianFunctor<typename SrcIterator::value_type> func(window_shape);
158 applyWindowFunction(s_ul, s_lr, s_acc, d_ul, d_acc, func, border);
159 }
160
161 template <class SrcIterator, class SrcAccessor,
162 class DestIterator, class DestAccessor>
medianFilter(triple<SrcIterator,SrcIterator,SrcAccessor> s,pair<DestIterator,DestAccessor> d,Diff2D window_shape,BorderTreatmentMode border=BORDER_TREATMENT_REPEAT)163 inline void medianFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
164 pair<DestIterator, DestAccessor> d,
165 Diff2D window_shape,
166 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
167 {
168 medianFilter(s.first, s.second, s.third,
169 d.first, d.second,
170 window_shape,
171 border);
172 }
173
174 template <class T1, class S1,
175 class T2, class S2>
medianFilter(MultiArrayView<2,T1,S1> const & src,MultiArrayView<2,T2,S2> dest,Diff2D window_shape,BorderTreatmentMode border=BORDER_TREATMENT_REPEAT)176 inline void medianFilter(MultiArrayView<2, T1, S1> const & src,
177 MultiArrayView<2, T2, S2> dest,
178 Diff2D window_shape,
179 BorderTreatmentMode border = BORDER_TREATMENT_REPEAT)
180 {
181 vigra_precondition(src.shape() == dest.shape(),
182 "vigra::medianFilter(): shape mismatch between input and output.");
183 medianFilter(srcImageRange(src),
184 destImage(dest),
185 window_shape,
186 border);
187 }
188
189 //@}
190
191 } //end of namespace vigra
192
193 #endif //VIGRA_MEDIANFILTER_HXX
194