27 #ifndef MLN_LINEAR_GAUSSIAN_HH
28 # define MLN_LINEAR_GAUSSIAN_HH
40 # include <mln/core/concept/image.hh>
41 # include <mln/core/alias/point2d.hh>
42 # include <mln/core/alias/dpoint1d.hh>
43 # include <mln/core/alias/dpoint3d.hh>
44 # include <mln/extension/adjust_fill.hh>
45 # include <mln/geom/ncols.hh>
46 # include <mln/geom/nrows.hh>
47 # include <mln/geom/min_col.hh>
48 # include <mln/geom/max_col.hh>
49 # include <mln/geom/min_row.hh>
50 # include <mln/geom/max_row.hh>
51 # include <mln/geom/min_sli.hh>
52 # include <mln/geom/max_sli.hh>
53 # include <mln/geom/ninds.hh>
54 # include <mln/geom/nslis.hh>
55 # include <mln/data/paste.hh>
56 # include <mln/data/stretch.hh>
57 # include <mln/algebra/vec.hh>
74 gaussian(const Image<I>& input,
float sigma);
82 gaussian(const Image<I>& input,
float sigma,
int dir);
85 # ifndef MLN_INCLUDE_ONLY
90 typedef float norm_fun(
float,
float,
97 struct recursivefilter_coef_
103 recursivefilter_coef_(
float a0,
float a1,
107 float s, norm_fun norm);
108 std::vector<float> n, d, nm, dm;
112 recursivefilter_coef_::recursivefilter_coef_(
float a0,
float a1,
116 float s, norm_fun norm)
134 float n_ = norm(a0, a1, b0, b1, c0, c1, cos0, sin0, cos1, sin1, sign);
142 std::exp(-b1 - 2*b0) * (c1 * sin1 - cos1 * c0) +
143 std::exp(-b0 - 2*b1) * (a1 * sin0 - cos0 * a0);
145 2 * std::exp(-b0 - b1) * ((a0 + c0) * cos1 * cos0 -
148 c0 * std::exp(-2*b0) + a0 * std::exp(-2*b1);
150 std::exp(-b1) * (c1 * sin1 - (c0 + 2 * a0) * cos1) +
151 std::exp(-b0) * (a1 * sin0 - (2 * c0 + a0) * cos0);
156 std::exp(-2 * b0 - 2 * b1);
158 -2 * cos0 * std::exp(-b0 - 2*b1) -
159 2 * cos1 * std::exp(-b1 - 2*b0);
161 4 * cos1 * cos0 * std::exp(-b0 - b1) +
162 std::exp(-2*b1) + std::exp(-2*b0);
164 -2 * std::exp(-b1) * cos1 - 2 * std::exp(-b0) * cos0;
166 for (
unsigned i = 1; i <= 3; ++i)
169 nm[i] =
float(sign) * (n[i] - d[i] * n[0]);
172 nm[4] =
float(sign) * (-d[4] * n[0]);
177 template <
class WorkType,
class I>
180 recursivefilter_(I& ima,
181 const recursivefilter_coef_& c,
182 const mln_psite(I)& start,
183 const mln_psite(I)& finish,
187 std::vector<WorkType> tmp1(len);
188 std::vector<WorkType> tmp2(len);
201 c.n[0] * ima(start + d)
202 + c.n[1] * ima(start)
206 c.n[0] * ima(start + d + d)
207 + c.n[1] * ima(start + d)
208 + c.n[2] * ima(start)
213 c.n[0] * ima(start + d + d + d)
214 + c.n[1] * ima(start + d + d)
215 + c.n[2] * ima(start + d)
216 + c.n[3] * ima(start)
217 - c.d[1] * tmp1[2] - c.d[2] * tmp1[1]
220 mln_psite(I) current(start + d + d + d + d);
221 for (mln_deduce(I,
site,
coord) i = 4; i < len; ++i)
224 c.n[0] * ima(current)
225 + c.n[1] * ima(current - d)
226 + c.n[2] * ima(current - d - d)
227 + c.n[3] * ima(current - d - d - d)
228 - c.d[1] * tmp1[i - 1] - c.d[2] * tmp1[i - 2]
229 - c.d[3] * tmp1[i - 3] - c.d[4] * tmp1[i - 4];
230 current = current + d;
235 tmp2[len - 1] = WorkType();
238 c.nm[1] * ima(finish);
241 c.nm[1] * ima(finish - d)
242 + c.nm[2] * ima(finish)
243 - c.dm[1] * tmp2[len - 2];
246 c.nm[1] * ima(finish - d - d)
247 + c.nm[2] * ima(finish - d)
248 + c.nm[3] * ima(finish)
249 - c.dm[1] * tmp2[len - 3]
250 - c.dm[2] * tmp2[len - 2];
252 current = finish - d - d - d ;
254 for (
int i = len - 5; i >= 0; --i)
257 c.nm[1] * ima(current)
258 + c.nm[2] * ima(current + d)
259 + c.nm[3] * ima(current + d + d)
260 + c.nm[4] * ima(current + d + d + d)
261 - c.dm[1] * tmp2[i + 1] - c.dm[2] * tmp2[i + 2]
262 - c.dm[3] * tmp2[i + 3] - c.dm[4] * tmp2[i + 4];
263 current = current - d;
268 for (
int i = 0; i < len; ++i)
270 ima(current) = tmp1[i] + tmp2[i];
271 current = current + d;
277 float gaussian_norm_coef_(
float a0,
float a1,
280 float cos0,
float sin0,
281 float cos1,
float sin1,
284 float expb0 = std::exp(b0);
285 float exp2b0 = std::exp(2.f * b0);
287 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
288 float scaleA = 2 * a1 * sin0 * expb0 - a0 * (1 - exp2b0);
290 float expb1 = std::exp(b1);
291 float exp2b1 = std::exp(2.f * b1);
293 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
294 float scaleC = 2 * c1 * sin1 * expb1 - c0 * (1 - exp2b1);
296 float sumA = scaleA / scale0;
297 float sumC = scaleC / scale1;
301 return (sumA + sumC);
305 float gaussian_1st_deriv_coef_norm_(
float a0,
float a1,
308 float cos0,
float sin0,
309 float cos1,
float sin1,
312 float expb0 = std::exp(b0);
313 float exp2b0 = std::exp(2.f * b0);
315 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
317 float scaleA = - 2 * a1 * sin0 * expb0 * (1 - exp2b0) +
318 2 * a0 * expb0 * (2 * expb0 - cos0 * (1 + exp2b0));
320 float expb1 = std::exp(b1);
321 float exp2b1 = std::exp(2.f * b1);
323 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
325 float scaleC = - 2 * c1 * sin1 * expb1 * (1 - exp2b1) +
326 2 * c0 * expb1 * (2 * expb1 - cos1 * (1 + exp2b1));
328 float sumA = scaleA / scale0;
329 float sumC = scaleC / scale1;
333 return (sumA + sumC);
337 float gaussian_2nd_deriv_coef_norm_(
float a0,
float a1,
340 float cos0,
float sin0,
341 float cos1,
float sin1,
344 float expb0 = std::exp(b0);
345 float exp2b0 = std::exp(2.f * b0);
347 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
348 scale0 *= scale0 * scale0;
350 float scaleA = a1 * sin0 * expb0 *
351 (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
352 a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) *
353 (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
355 float expb1 = std::exp(b1);
356 float exp2b1 = std::exp(2.f * b1);
358 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
359 scale1 *= scale1 * scale1;
361 float scaleC = c1 * sin1 * expb1 *
362 (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
363 c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) *
364 (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
366 float sumA = scaleA / scale0;
367 float sumC = scaleC / scale1;
370 return (sumA + sumC);
374 template <
class I,
class F>
377 generic_filter_(trait::image::dimension::one_d,
378 Image<I>& img_,
const F& coef,
int dir)
380 I& img =
exact(img_);
382 mln_precondition(dir < I::site::dim);
385 recursivefilter_<mln_value(I)>(img, coef,
386 point1d(static_cast<def::coord>(-img.border())),
393 template <
class I,
class F>
396 generic_filter_(trait::image::dimension::two_d,
397 Image<I>& img_,
const F& coef,
int dir)
399 I& img =
exact(img_);
401 mln_precondition(dir < I::site::dim);
408 recursivefilter_<mln_value(I)>(img, coef,
410 static_cast<def::coord>(j)),
413 static_cast<def::coord>(j)),
422 recursivefilter_<mln_value(I)>(img, coef,
423 point2d(static_cast<def::coord>(i),
425 point2d(static_cast<def::coord>(i),
433 template <
class I,
class F>
436 generic_filter_(trait::image::dimension::three_d,
437 Image<I>& img_,
const F& coef,
int dir)
439 I& img =
exact(img_);
440 mln_precondition(dir < I::site::dim);
447 recursivefilter_<mln_value(I)>(img, coef,
448 point3d(static_cast<def::coord>(-img.border()),
449 static_cast<def::coord>(j),
453 static_cast<def::coord>(j),
466 recursivefilter_<mln_value(I)>(img, coef,
467 point3d(static_cast<def::coord>(i),
468 static_cast<def::coord>(-img.border()),
469 static_cast<def::coord>(k)),
470 point3d(static_cast<def::coord>(i),
473 static_cast<def::coord>(k)),
484 recursivefilter_<mln_value(I)>(img, coef,
485 point3d(static_cast<def::coord>(i),
486 static_cast<def::coord>(j),
487 static_cast<def::coord>(-img.border())),
488 point3d(static_cast<def::coord>(i),
489 static_cast<def::coord>(j),
500 template <
class I,
class F,
class O>
503 generic_filter_common_(trait::value::nature::floating,
509 mln_ch_value(O,
float) work_img(
exact(in).domain());
516 for (
int i = 0; i < I::
site::dim; ++i)
517 generic_filter_(mln_trait_image_dimension(I)(),
524 template <class I, class F, class O>
527 generic_filter_common_(trait::
value::nature::floating,
534 mln_ch_value(O,
float) work_img(
exact(in).domain());
541 generic_filter_(mln_trait_image_dimension(I)(),
542 work_img, coef, dir);
549 template <class I, class F, class O>
552 generic_filter_common_(trait::
value::nature::scalar,
558 mln_ch_value(O,
float) work_img(
exact(in).domain());
565 for (
int i = 0; i < I::
site::dim; ++i)
566 generic_filter_(mln_trait_image_dimension(I)(),
573 template <class I, class F, class O>
576 generic_filter_common_(trait::
value::nature::scalar,
583 mln_ch_value(O,
float) work_img(
exact(in).domain());
590 generic_filter_(mln_trait_image_dimension(I)(),
591 work_img, coef, dir);
599 template <class I, class F, class O>
602 generic_filter_common_(trait::
value::nature::vectorial,
616 for (
int i = 0; i < I::site::dim; ++i)
617 generic_filter_(mln_trait_image_dimension(I)(),
621 template <
class I,
class F,
class O>
624 generic_filter_common_(trait::value::nature::vectorial,
639 generic_filter_(mln_trait_image_dimension(I)(),
656 template <
typename I>
659 gaussian(const Image<I>& input,
float sigma,
int dir)
661 mln_precondition(
exact(input).is_valid());
662 mln_precondition(dir < I::site::dim);
664 mln_concrete(I) output;
666 impl::recursivefilter_coef_ coef(1.68f, 3.735f,
670 sigma, impl::gaussian_norm_coef_);
672 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
673 input, coef, sigma, output, dir);
688 template <typename I>
691 gaussian_1st_derivative(const Image<I>& input,
float sigma,
int dir)
693 mln_precondition(
exact(input).is_valid());
694 mln_precondition(dir < I::site::dim);
696 mln_concrete(I) output;
699 impl::recursivefilter_coef_
700 coef(-0.6472f, -4.531f,
704 sigma, impl::gaussian_1st_deriv_coef_norm_);
706 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
707 input, coef, sigma, output, dir);
721 template <typename I>
724 gaussian_2nd_derivative(const Image<I>& input,
float sigma,
int dir)
726 mln_precondition(
exact(input).is_valid());
727 mln_precondition(dir < I::site::dim);
729 mln_concrete(I) output;
732 impl::recursivefilter_coef_
733 coef(-1.331f, 3.661f,
737 sigma, impl::gaussian_2nd_deriv_coef_norm_);
739 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
740 input, coef, sigma, output, dir);
753 template <typename I>
756 gaussian(const Image<I>& input,
float sigma)
758 mln_precondition(
exact(input).is_valid());
760 mln_concrete(I) output;
763 impl::recursivefilter_coef_
768 sigma, impl::gaussian_norm_coef_);
769 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
770 input, coef, sigma, output);
782 template <typename I>
785 gaussian_1st_derivative(const Image<I>& input,
float sigma)
787 mln_precondition(
exact(input).is_valid());
789 mln_concrete(I) output;
792 impl::recursivefilter_coef_
793 coef(-0.6472f, -4.531f,
797 sigma, impl::gaussian_1st_deriv_coef_norm_);
798 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
799 input, coef, sigma, output);
810 template <typename I>
813 gaussian_2nd_derivative(const Image<I>& input,
float sigma)
815 mln_precondition(
exact(input).is_valid());
817 mln_concrete(I) output;
820 impl::recursivefilter_coef_
821 coef(-1.331f, 3.661f,
825 sigma, impl::gaussian_2nd_deriv_coef_norm_);
826 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
827 input, coef, sigma, output);
831 # endif // ! MLN_INCLUDE_ONLY
838 #endif // ! MLN_LINEAR_GAUSSIAN_HH