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

shockfilter.hxx
1/************************************************************************/
2/* */
3/* Copyright 2007-2014 by Benjamin Seppke */
4/* Cognitive Systems Group, University of Hamburg, Germany */
5/* */
6/************************************************************************/
7
8#ifndef VIGRA_SHOCKFILTER_HXX
9#define VIGRA_SHOCKFILTER_HXX
10
11#include "basicimage.hxx"
12#include "convolution.hxx"
13#include "tensorutilities.hxx"
14
15 namespace vigra {
16
17
18/********************************************************/
19/* */
20/* Coherence enhancing shock filter */
21/* */
22/********************************************************/
23
24/**
25 This function calculates of the coherence enhancing shock filter proposed by
26 J. Weickert (2002): Coherence-Enhancing Show Filters.
27 It uses the structure tensor information of an image and an iterative discrete upwinding scheme
28 instead of pure dilation and erosion to perform the necessary morphological operations
29 on the image.
30*/
31//@{
32
33/** \brief This function calculates discrete upwinding scheme proposed by J. Weickert (2002) in Coherence-Enhancing Show Filters.
34
35 An image is upwinded positively (dilation), if the given second src is positive.
36 Otherwise it is upwinds negatively (eroded). The effect can be steered by an upwinding
37 factor.
38
39
40 <b> Declarations:</b>
41
42 pass 2D array views:
43 \code
44 namespace vigra {
45 template <class T1, class S1,
46 class T2, class S2
47 class T3, class S3>
48 void
49 upwindImage(MultiArrayView<2, T1, S1> const & src,
50 MultiArrayView<2, T2, S2> const & src2,
51 MultiArrayView<2, T3, S3> dest,
52 float upwind_factor_h);
53
54 }
55 \endcode
56
57 \deprecatedAPI{upwindImage}
58 pass \ref ImageIterators and \ref DataAccessors :
59 \code
60 namespace vigra {
61 template <class SrcIterator, class SrcAccessor,
62 class Src2Iterator, class Src2Accessor,
63 class DestIterator, class DestAccessor>
64 void upwindImage(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
65 Src2Iterator s2_ul, Src2Accessor s2_acc,
66 DestIterator d_ul, DestAccessor d_acc,
67 float upwind_factor_h)
68 }
69 \endcode
70 use argument objects in conjunction with \ref ArgumentObjectFactories :
71 \code
72 namespace vigra {
73 template <class SrcIterator, class SrcAccessor,
74 class Src2Iterator, class Src2Accessor,
75 class DestIterator, class DestAccessor>
76 void
77 upwindImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
78 pair<Src2Iterator, Src2Accessor> src2,
79 pair<DestIterator, DestAccessor> dest,
80 float upwind_factor_h);
81 }
82 \endcode
83 \deprecatedEnd
84*/
85
86
87doxygen_overloaded_function(template <...> void upwindImage)
88
89 template <class SrcIterator, class SrcAccessor,
90 class Src2Iterator, class Src2Accessor,
91 class DestIterator, class DestAccessor>
92 void upwindImage(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
93 Src2Iterator s2_ul, Src2Accessor s2_acc,
94 DestIterator d_ul, DestAccessor d_acc,
95 float upwind_factor_h)
96{
97 using namespace std;
98
99 typedef typename SrcIterator::difference_type DiffType;
100
101 DiffType shape = s_lr - s_ul;
102
103 typedef typename SrcAccessor::value_type SrcType;
104 typedef typename DestAccessor::value_type ResultType;
105
106 SrcType upper, lower, left, right, center;
107 ResultType fx, fy;
108
109
110 for(int y=0; y<shape[1]; ++y)
111 {
112 for(int x=0; x<shape[0]; ++x)
113 {
114 upper = s_acc(s_ul + Diff2D(x, max(0, y-1)));
115 lower = s_acc(s_ul + Diff2D(x, min(shape[1]-1, y+1)));
116 left = s_acc(s_ul + Diff2D(max(0, x-1), y));
117 right = s_acc(s_ul + Diff2D(min(shape[0]-1, x+1), y));
118 center = s_acc(s_ul + Diff2D(x, y));
119
120 if(s2_acc(s2_ul+Diff2D(x,y))<0)
121 {
122 fx = max(max(right - center, left - center), 0.0f);
123 fy = max(max(lower - center, upper - center), 0.0f);
124 d_acc.set (center + upwind_factor_h*sqrt( fx*fx + fy*fy), d_ul+Diff2D(x,y));
125 }
126 else
127 {
128 fx = max(max(center - right, center - left), 0.0f);
129 fy = max(max(center - lower, center - upper), 0.0f);
130 d_acc.set (center - upwind_factor_h*sqrt( fx*fx + fy*fy), d_ul+Diff2D(x,y));
131 }
132 }
133 }
134}
135
136 template <class SrcIterator, class SrcAccessor,
137 class Src2Iterator, class Src2Accessor,
138 class DestIterator, class DestAccessor>
139 inline void upwindImage(triple<SrcIterator, SrcIterator, SrcAccessor> s,
140 pair<Src2Iterator, Src2Accessor> s2,
141 pair<DestIterator, DestAccessor> d,
142 float upwind_factor_h)
143{
144 upwindImage(s.first, s.second, s.third, s2.first, s2.second, d.first, d.second, upwind_factor_h);
145}
146
147 template <class T1, class S1,
148 class T2, class S2,
149 class T3, class S3>
150 inline void upwindImage(MultiArrayView<2, T1, S1> const & src,
151 MultiArrayView<2, T2, S2> const & src2,
152 MultiArrayView<2, T3, S3> dest,
153 float upwind_factor_h)
154{
155 vigra_precondition(src.shape() == src2.shape() && src.shape() == dest.shape(),
156 "vigra::upwindImage(): shape mismatch between input and output.");
157 upwindImage(srcImageRange(src),
158 srcImage(src2),
159 destImage(dest),
160 upwind_factor_h);
161}
162
163
164/** \brief This function calculates of the coherence enhancing shock filter proposed by J. Weickert (2002) in Coherence-Enhancing Show Filters.
165
166 <b> Declarations:</b>
167
168 pass 2D array views:
169 \code
170 namespace vigra {
171 template <class T1, class S1,
172 class T2, class S2>
173 void
174 shockFilter(MultiArrayView<2, T1, S1> const & src,
175 MultiArrayView<2, T2, S2> dest,
176 float sigma, float rho, float upwind_factor_h,
177 unsigned int iterations);
178
179 }
180 \endcode
181
182 \deprecatedAPI{shockFilter}
183 pass \ref ImageIterators and \ref DataAccessors :
184 \code
185 namespace vigra {
186 template <class SrcIterator, class SrcAccessor,
187 class DestIterator, class DestAccessor>
188 void shockFilter(SrcIterator supperleft,
189 SrcIterator slowerright, SrcAccessor sa,
190 DestIterator dupperleft, DestAccessor da,
191 float sigma, float rho, float upwind_factor_h,
192 unsigned int iterations);
193 }
194 \endcode
195 use argument objects in conjunction with \ref ArgumentObjectFactories :
196 \code
197 namespace vigra {
198 template <class SrcIterator, class SrcAccessor,
199 class DestIterator, class DestAccessor>
200 void
201 shockFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
202 pair<DestIterator, DestAccessor> dest,
203 float sigma, float rho, float upwind_factor_h,
204 unsigned int iterations);
205 }
206 \endcode
207 \deprecatedEnd
208
209 <b> Usage:</b>
210
211 <b>\#include</b> <vigra/shockilter.hxx><br/>
212 Namespace: vigra
213
214 \code
215 unsigned int w=1000, h=1000;
216 MultiArray<2, float> src(w,h), dest(w,h);
217 ...
218
219
220
221 // apply a shock-filter:
222 shockFilter(src, dest, 1.0, 5.0, 0.3, 5);
223 \endcode
224
225 <b> Preconditions:</b>
226
227 The image must be larger than the window size of the filter.
228*/
229
230doxygen_overloaded_function(template <...> void upwindImage)
231
232 template <class SrcIterator, class SrcAccessor,
233 class DestIterator, class DestAccessor>
234 void shockFilter(SrcIterator s_ul, SrcIterator s_lr, SrcAccessor s_acc,
235 DestIterator d_ul, DestAccessor d_acc,
236 float sigma, float rho, float upwind_factor_h,
237 unsigned int iterations)
238{
239
240 typedef typename SrcIterator::difference_type DiffType;
241 DiffType shape = s_lr - s_ul;
242
243 unsigned int w = shape[0],
244 h = shape[1];
245
246 FVector3Image tensor(w,h);
247 FVector3Image eigen(w,h);
248 FImage hxx(w,h), hxy(w,h), hyy(w,h), temp(w,h) ,result(w,h);
249
250 float c, s, v_xx, v_xy, v_yy;
251
252 copyImage(srcIterRange(s_ul, s_lr, s_acc), destImage(result));
253
254 for(unsigned int i = 0; i<iterations; ++i)
255 {
256
257 structureTensor(srcImageRange(result), destImage(tensor), sigma, rho);
258 tensorEigenRepresentation(srcImageRange(tensor), destImage(eigen));
259 hessianMatrixOfGaussian(srcImageRange(result),
260 destImage(hxx), destImage(hxy), destImage(hyy), sigma);
261
262 for(int y=0; y<shape[1]; ++y)
263 {
264 for(int x=0; x<shape[0]; ++x)
265 {
266 c = cos(eigen(x,y)[2]);
267 s = sin(eigen(x,y)[2]);
268 v_xx = hxx(x,y);
269 v_xy = hxy(x,y);
270 v_yy = hyy(x,y);
271 //store signum image in hxx (safe, because no other will ever access hxx(x,y)
272 hxx(x,y) = c*c*v_xx + 2*c*s*v_xy + s*s*v_yy;
273 }
274 }
275 upwindImage(srcImageRange(result),srcImage(hxx), destImage(temp), upwind_factor_h);
276 result = temp;
277
278 }
279 copyImage(srcImageRange(result), destIter(d_ul, d_acc));
280}
281
282 template <class SrcIterator, class SrcAccessor,
283 class DestIterator, class DestAccessor>
284 inline void shockFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
285 pair<DestIterator, DestAccessor> d,
286 float sigma, float rho, float upwind_factor_h,
287 unsigned int iterations)
288{
289 shockFilter(s.first, s.second, s.third,
290 d.first, d.second,
291 sigma, rho, upwind_factor_h,
292 iterations);
293}
294
295 template <class T1, class S1,
296 class T2, class S2>
297 inline void shockFilter(MultiArrayView<2, T1, S1> const & src,
298 MultiArrayView<2, T2, S2> dest,
299 float sigma, float rho, float upwind_factor_h,
300 unsigned int iterations)
301{
302 vigra_precondition(src.shape() == dest.shape(),
303 "vigra::shockFilter(): shape mismatch between input and output.");
304 shockFilter(srcImageRange(src),
305 destImage(dest),
306 sigma, rho, upwind_factor_h,
307 iterations);
308}
309
310} //end of namespace vigra
311
312#endif //VIGRA_SHOCKFILTER_HXX
vigra::Diff2D
Two dimensional difference vector.
Definition diff2d.hxx:186
vigra::RGBValue
Class for a single RGB value.
Definition rgbvalue.hxx:128
vigra
vigra::structureTensor
void structureTensor(...)
Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters.
vigra::FImage
BasicImage< float > FImage
Definition stdimage.hxx:143
vigra::tensorEigenRepresentation
void tensorEigenRepresentation(...)
Calculate eigen representation of a symmetric 2x2 tensor.
vigra::hessianMatrixOfGaussian
void hessianMatrixOfGaussian(...)
Filter image with the 2nd derivatives of the Gaussian at the given scale to get the Hessian matrix.
vigra::upwindImage
void upwindImage(...)
This function calculates discrete upwinding scheme proposed by J. Weickert (2002) in Coherence-Enhanc...
vigra::FVector3Image
BasicImage< TinyVector< float, 3 > > FVector3Image
Definition stdimage.hxx:286
vigra::copyImage
void copyImage(...)
Copy source image into destination image.

© 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