27 #ifndef MLN_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH
28 # define MLN_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH
36 #include <mln/core/image/image2d.hh>
37 #include <mln/extension/adjust_fill.hh>
38 #include <mln/extension/adjust_duplicate.hh>
54 unsigned dir,
double sigma,
55 const mln_value(I)& bdr);
59 # ifndef MLN_INCLUDE_ONLY
64 struct recursivefilter_coef_
66 enum FilterType { DericheGaussian,
67 DericheGaussianFirstDerivative,
68 DericheGaussianSecondDerivative };
70 std::vector<double> n, d, nm, dm;
73 recursivefilter_coef_(
double a0,
double a1,
77 double s, FilterType filter_type)
89 double sin0 =
sin(w0);
90 double sin1 =
sin(w1);
91 double cos0 =
cos(w0);
92 double cos1 =
cos(w1);
94 switch (filter_type) {
96 case DericheGaussian :
99 (2.0 * a1 *
exp( b0 ) * cos0 * cos0 - a0 * sin0 *
exp( 2.0 * b0 )
100 + a0 * sin0 - 2.0 * a1 *
exp( b0 )) /
101 (( 2.0 * cos0 *
exp( b0 ) -
exp( 2.0 * b0 ) - 1 ) * sin0);
104 (2.0 * c1 *
exp( b1 ) * cos1 * cos1 - c0 * sin1 *
exp( 2.0 * b1 )
105 + c0 * sin1 - 2.0 * c1 *
exp( b1 ))
106 / (( 2.0 * cos1 *
exp( b1 ) -
exp( 2.0 * b1 ) - 1 ) * sin1);
110 case DericheGaussianFirstDerivative :
113 (a0 * cos0 - a1 * sin0 + a1 * sin0 *
exp( 2.0 * b0 )
114 + a0 * cos0 *
exp( 2.0 * b0 ) - 2.0 * a0 *
exp( b0 ))
116 / (
exp( 4.0 * b0 ) - 4.0 * cos0 *
exp( 3.0 * b0 )
117 + 2.0 *
exp( 2.0 * b0 ) + 4.0 * cos0 * cos0 *
exp( 2.0 * b0 )
118 + 1.0 - 4.0 * cos0 *
exp( b0 ));
120 (c0 * cos1 - c1 * sin1 + c1 * sin1 *
exp( 2.0 * b1 )
121 + c0 * cos1 *
exp( 2.0 * b1 ) - 2.0 * c0 *
exp( b1 ))
123 (
exp( 4.0 * b1 ) - 4.0 * cos1 *
exp( 3.0 * b1 )
124 + 2.0 *
exp( 2.0 * b1 ) + 4.0 * cos1 * cos1 *
exp( 2.0 * b1 )
125 + 1.0 - 4.0 * cos1 *
exp( b1 ));
129 case DericheGaussianSecondDerivative :
133 12.0 * cos0 *
exp( 3.0 * b0 ) - 3.0 *
exp( 2.0 * b0 )
134 + 8.0 * cos0 * cos0 * cos0 *
exp( 3.0 * b0 ) - 12.0 * cos0 * cos0 *
136 - (3.0 *
exp( 4.0 * b0 ))
137 + 6.0 * cos0 *
exp( 5.0 * b0 ) -
exp( 6.0 * b0 ) + 6.0 * cos0 *
exp
139 - ( 1.0 + 12.0 * cos0 * cos0 *
exp( 2.0 * b0 ) );
141 4.0 * a0 * sin0 *
exp( 3.0 * b0 ) + a1 * cos0 * cos0 *
exp( 4.0 * b0 )
142 - ( 4.0 * a0 * sin0 *
exp( b0 ) + 6.0 * a1 * cos0 * cos0 *
exp( 2.0 * b0 ) )
143 + 2.0 * a1 * cos0 * cos0 * cos0 *
exp( b0 ) - 2.0 * a1 * cos0 *
exp(b0)
144 + 2.0 * a1 * cos0 * cos0 * cos0 *
exp( 3.0 * b0 ) - 2.0 * a1 * cos0
146 + a1 * cos0 * cos0 - a1 *
exp( 4.0 * b0 )
147 + 2.0 * a0 * sin0 * cos0 * cos0 *
exp( b0 ) - 2.0 * a0 * sin0 * cos0
148 * cos0 *
exp( 3.0 * b0 )
149 - ( a0 * sin0 * cos0 *
exp( 4.0 * b0 ) + a1 )
150 + 6.0 * a1 *
exp( 2.0 * b0 ) + a0 * cos0 * sin0
151 * 2.0 *
exp( b0 ) / ( aux * sin0 );
153 12.0 * cos1 *
exp( 3.0 * b1 ) - 3.0 *
exp( 2.0 * b1 )
154 + 8.0 * cos1 * cos1 * cos1 *
exp( 3.0 * b1 ) - 12.0 * cos1 * cos1 *
156 - 3.0 *
exp( 4.0 * b1 )
157 + 6.0 * cos1 *
exp( 5.0 * b1 ) -
exp( 6.0 * b1 ) + 6.0 * cos1 *
exp
159 - ( 1.0 + 12.0 * cos1 * cos1 *
exp( 2.0 * b1 ) );
160 sumC = 4.0 * c0 * sin1 *
exp( 3.0 * b1 ) + c1 * cos1 * cos1 *
exp( 4.0 * b1 )
161 - ( 4.0 * c0 * sin1 *
exp( b1 ) + 6.0 * c1 * cos1 * cos1 *
exp( 2.0 * b1 ) )
162 + 2.0 * c1 * cos1 * cos1 * cos1 *
exp( b1 ) - 2.0 * c1 * cos1 *
exp( b1 )
163 + 2.0 * c1 * cos1 * cos1 * cos1 *
exp( 3.0 * b1 ) - 2.0 * c1 * cos1
165 + c1 * cos1 * cos1 - c1 *
exp( 4.0 * b1 )
166 + 2.0 * c0 * sin1 * cos1 * cos1 *
exp( b1 ) - 2.0 * c0 * sin1 * cos1
167 * cos1 *
exp( 3.0 * b1 )
168 - ( c0 * sin1 * cos1 *
exp( 4.0 * b1 ) + c1 )
169 + 6.0 * c1 *
exp( 2.0 * b1 ) + c0 * cos1 * sin1
170 * 2.0 *
exp( b1 ) / ( aux * sin1 );
183 exp( -b1 - 2*b0 ) * (c1 * sin1 - cos1 * c0) +
184 exp( -b0 - 2*b1 ) * (a1 * sin0 - cos0 * a0);
186 2 *
exp(-b0 - b1) * ((a0 + c0) * cos1 * cos0 -
189 c0 *
exp(-2 * b0) + a0 *
exp(-2 * b1);
191 exp(-b1) * (c1 * sin1 - (c0 + 2*a0) * cos1) +
192 exp(-b0) * (a1 * sin0 - (2*c0 + a0) * cos0);
196 d[4] =
exp(-2 * b0 - 2 * b1);
198 -2 * cos0 *
exp(-b0 - 2*b1) -
199 2 * cos1 *
exp(-b1 - 2*b0);
201 4 * cos1 * cos0 *
exp(-b0 - b1) +
204 -2*
exp(-b1) * cos1 - 2 *
exp(-b0) * cos0;
206 switch (filter_type) {
207 case DericheGaussian :
208 case DericheGaussianSecondDerivative :
210 for (
unsigned i = 1; i <= 3; ++i)
213 nm[i] = n[i] - d[i] * n[0];
216 nm[4] = -d[4] * n[0];
219 case DericheGaussianFirstDerivative :
221 for (
unsigned i = 1; i <= 3; ++i)
224 nm[i] = - (n[i] - d[i] * n[0]);
244 template <
typename I,
typename C>
247 recursivefilter_directional_generic(I& ima,
249 const mln_psite(I)& start,
250 const mln_psite(I)& finish,
254 std::vector<double> tmp1(len);
255 std::vector<double> tmp2(len);
261 c.n[0]*ima(start + d)
266 c.n[0]*ima(start + d + d)
267 + c.n[1]*ima(start + d)
273 c.n[0]*ima(start + d + d + d)
274 + c.n[1]*ima(start + d + d)
275 + c.n[2]*ima(start + d)
277 - c.d[1]*tmp1[2] - c.d[2]*tmp1[1]
280 mln_site(I) current = start + d + d + d + d;
281 for (
int i = 4; i < len; ++i)
285 + c.n[1]*ima(current - d)
286 + c.n[2]*ima(current - d - d)
287 + c.n[3]*ima(current - d - d - d)
288 - c.d[1]*tmp1[i - 1] - c.d[2]*tmp1[i - 2]
289 - c.d[3]*tmp1[i - 3] - c.d[4]*tmp1[i - 4];
301 c.nm[1]*ima(finish - d)
302 + c.nm[2]*ima(finish)
303 - c.dm[1]*tmp2[len-2];
306 c.nm[1]*ima(finish - d - d)
307 + c.nm[2]*ima(finish - d)
308 + c.nm[3]*ima(finish)
309 - c.dm[1]*tmp2[len-3]
310 - c.dm[2]*tmp2[len-2];
312 current = finish - d - d - d ;
314 for (
int i = len - 5; i >= 0; --i)
318 + c.nm[2]*ima(current + d)
319 + c.nm[3]*ima(current + d + d)
320 + c.nm[4]*ima(current + d + d + d)
321 - c.dm[1]*tmp2[i+1] - c.dm[2]*tmp2[i+2]
322 - c.dm[3]*tmp2[i+3] - c.dm[4]*tmp2[i+4];
329 for (
int i = 0; i < len; ++i)
331 ima(current) = (tmp1[i] + tmp2[i]);
339 template <
typename I,
typename C>
342 recursivefilter_directional_fastest(I& ima,
344 const mln_psite(I)& start,
345 const mln_psite(I)& finish,
348 const mln_value(I)& bdr)
353 std::vector<double> tmp1(len);
354 std::vector<double> tmp2(len);
356 unsigned delta_offset = ima.delta_offset(d);
358 o_start = ima.offset_of_point(start),
359 o_start_d = o_start + delta_offset,
360 o_start_dd = o_start + 2 * delta_offset,
361 o_start_ddd = o_start + 3 * delta_offset;
364 c.n[0] * ima.element(o_start);
367 + c.n[0] * ima.element(o_start_d)
368 + c.n[1] * ima.element(o_start)
372 + c.n[0] * ima.element(o_start_dd)
373 + c.n[1] * ima.element(o_start_d)
374 + c.n[2] * ima.element(o_start)
379 + c.n[0] * ima.element(o_start_ddd)
380 + c.n[1] * ima.element(o_start_dd)
381 + c.n[2] * ima.element(o_start_d)
382 + c.n[3] * ima.element(o_start)
383 - c.d[1] * tmp1[2] - c.d[2] * tmp1[1]
387 o_current = o_start + 4 * delta_offset,
388 o_current_d = o_current - delta_offset,
389 o_current_dd = o_current - 2 * delta_offset,
390 o_current_ddd = o_current - 3 * delta_offset;
392 for (
int i = 4; i < len; ++i)
395 + c.n[0] * ima.element(o_current)
396 + c.n[1] * ima.element(o_current_d)
397 + c.n[2] * ima.element(o_current_dd)
398 + c.n[3] * ima.element(o_current_ddd)
399 - c.d[1] * tmp1[i - 1] - c.d[2] * tmp1[i - 2]
400 - c.d[3] * tmp1[i - 3] - c.d[4] * tmp1[i - 4];
401 o_current += delta_offset;
402 o_current_d += delta_offset;
403 o_current_dd += delta_offset;
404 o_current_ddd += delta_offset;
413 o_finish = ima.offset_of_point(finish),
414 o_finish_d = o_finish - delta_offset,
415 o_finish_dd = o_finish - 2 * delta_offset;
420 c.nm[1] * ima.element(o_finish);
423 + c.nm[1] * ima.element(o_finish_d)
424 + c.nm[2] * ima.element(o_finish)
425 - c.dm[1] * tmp2[len-2];
428 + c.nm[1] * ima.element(o_finish_dd)
429 + c.nm[2] * ima.element(o_finish_d)
430 + c.nm[3] * ima.element(o_finish)
431 - c.dm[1] * tmp2[len-3]
432 - c.dm[2] * tmp2[len-2];
434 o_current = o_finish - 3 * delta_offset;
435 o_current_d = o_current + delta_offset;
436 o_current_dd = o_current + 2 * delta_offset;
437 o_current_ddd = o_current + 3 * delta_offset;
439 for (
int i = len - 5; i >= 0; --i)
442 + c.nm[1] * ima.element(o_current)
443 + c.nm[2] * ima.element(o_current_d)
444 + c.nm[3] * ima.element(o_current_dd)
445 + c.nm[4] * ima.element(o_current_ddd)
446 - c.dm[1] * tmp2[i+1] - c.dm[2] * tmp2[i+2]
447 - c.dm[3] * tmp2[i+3] - c.dm[4] * tmp2[i+4];
448 o_current -= delta_offset;
449 o_current_d -= delta_offset;
450 o_current_dd -= delta_offset;
451 o_current_ddd -= delta_offset;
457 for (
int i = 0; i < len; ++i)
459 ima.element(o_current) =
static_cast<mln_value(I)
>(tmp1[i] + tmp2[i]);
460 o_current += delta_offset;
465 template <
typename I>
469 unsigned dir,
double sigma,
470 const mln_value(I)& bdr)
472 mln_trace(
"linear::gaussian_directional_2d");
474 typedef mln_site(I) P;
475 mlc_bool(P::dim == 2)::check();
477 const I& input =
exact(input_);
479 mln_precondition(dir == 0 || dir == 1);
480 mln_precondition(input.is_valid());
482 my::recursivefilter_coef_ coef(1.68f, 3.735f,
487 my::recursivefilter_coef_::DericheGaussian);
489 extension::
adjust_fill(input, 5 *
int(sigma + .50001) + 1, bdr);
490 mln_concrete(I) output =
duplicate(input);
502 for (
int j = 0; j <
ncols; ++j)
503 recursivefilter_directional_fastest(output, coef,
513 for (
int i = 0; i <
nrows; ++i)
514 recursivefilter_directional_fastest(output, coef,
525 # endif // ! MLN_INCLUDE_ONLY
532 #endif // ! MLN_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH