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>
72 gaussian(const Image<I>& input,
float sigma);
77 gaussian(const Image<I>& input,
float sigma,
int dir);
80 # ifndef MLN_INCLUDE_ONLY
85 typedef float norm_fun(
float,
float,
92 struct recursivefilter_coef_
98 recursivefilter_coef_(
float a0,
float a1,
102 float s, norm_fun norm);
103 std::vector<float> n, d, nm, dm;
107 recursivefilter_coef_::recursivefilter_coef_(
float a0,
float a1,
111 float s, norm_fun norm)
123 float sin0 = std::sin(w0);
124 float sin1 = std::sin(w1);
125 float cos0 = std::cos(w0);
126 float cos1 = std::cos(w1);
129 float n_ = norm(a0, a1, b0, b1, c0, c1, cos0, sin0, cos1, sin1, sign);
137 std::exp(-b1 - 2*b0) * (c1 * sin1 - cos1 * c0) +
138 std::exp(-b0 - 2*b1) * (a1 * sin0 - cos0 * a0);
140 2 * std::exp(-b0 - b1) * ((a0 + c0) * cos1 * cos0 -
143 c0 * std::exp(-2*b0) + a0 * std::exp(-2*b1);
145 std::exp(-b1) * (c1 * sin1 - (c0 + 2 * a0) * cos1) +
146 std::exp(-b0) * (a1 * sin0 - (2 * c0 + a0) * cos0);
151 std::exp(-2 * b0 - 2 * b1);
153 -2 * cos0 * std::exp(-b0 - 2*b1) -
154 2 * cos1 * std::exp(-b1 - 2*b0);
156 4 * cos1 * cos0 * std::exp(-b0 - b1) +
157 std::exp(-2*b1) + std::exp(-2*b0);
159 -2 * std::exp(-b1) * cos1 - 2 * std::exp(-b0) * cos0;
161 for (
unsigned i = 1; i <= 3; ++i)
164 nm[i] = float(sign) * (n[i] - d[i] * n[0]);
167 nm[4] = float(sign) * (-d[4] * n[0]);
172 template <
class WorkType,
class I>
175 recursivefilter_(I& ima,
176 const recursivefilter_coef_& c,
177 const mln_psite(I)& start,
178 const mln_psite(I)& finish,
180 const mln_deduce(I, psite, delta)& d)
182 std::vector<WorkType> tmp1(len);
183 std::vector<WorkType> tmp2(len);
196 c.n[0] * ima(start + d)
197 + c.n[1] * ima(start)
201 c.n[0] * ima(start + d + d)
202 + c.n[1] * ima(start + d)
203 + c.n[2] * ima(start)
208 c.n[0] * ima(start + d + d + d)
209 + c.n[1] * ima(start + d + d)
210 + c.n[2] * ima(start + d)
211 + c.n[3] * ima(start)
212 - c.d[1] * tmp1[2] - c.d[2] * tmp1[1]
215 mln_psite(I) current(start + d + d + d + d);
216 for (mln_deduce(I, site, coord) i = 4; i < len; ++i)
219 c.n[0] * ima(current)
220 + c.n[1] * ima(current - d)
221 + c.n[2] * ima(current - d - d)
222 + c.n[3] * ima(current - d - d - d)
223 - c.d[1] * tmp1[i - 1] - c.d[2] * tmp1[i - 2]
224 - c.d[3] * tmp1[i - 3] - c.d[4] * tmp1[i - 4];
225 current = current + d;
230 tmp2[len - 1] = WorkType();
233 c.nm[1] * ima(finish);
236 c.nm[1] * ima(finish - d)
237 + c.nm[2] * ima(finish)
238 - c.dm[1] * tmp2[len - 2];
241 c.nm[1] * ima(finish - d - d)
242 + c.nm[2] * ima(finish - d)
243 + c.nm[3] * ima(finish)
244 - c.dm[1] * tmp2[len - 3]
245 - c.dm[2] * tmp2[len - 2];
247 current = finish - d - d - d ;
249 for (
int i = len - 5; i >= 0; --i)
252 c.nm[1] * ima(current)
253 + c.nm[2] * ima(current + d)
254 + c.nm[3] * ima(current + d + d)
255 + c.nm[4] * ima(current + d + d + d)
256 - c.dm[1] * tmp2[i + 1] - c.dm[2] * tmp2[i + 2]
257 - c.dm[3] * tmp2[i + 3] - c.dm[4] * tmp2[i + 4];
258 current = current - d;
263 for (
int i = 0; i < len; ++i)
265 ima(current) = tmp1[i] + tmp2[i];
266 current = current + d;
272 float gaussian_norm_coef_(
float a0,
float a1,
275 float cos0,
float sin0,
276 float cos1,
float sin1,
279 float expb0 = std::exp(b0);
280 float exp2b0 = std::exp(2.f * b0);
282 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
283 float scaleA = 2 * a1 * sin0 * expb0 - a0 * (1 - exp2b0);
285 float expb1 = std::exp(b1);
286 float exp2b1 = std::exp(2.f * b1);
288 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
289 float scaleC = 2 * c1 * sin1 * expb1 - c0 * (1 - exp2b1);
291 float sumA = scaleA / scale0;
292 float sumC = scaleC / scale1;
296 return (sumA + sumC);
300 float gaussian_1st_deriv_coef_norm_(
float a0,
float a1,
303 float cos0,
float sin0,
304 float cos1,
float sin1,
307 float expb0 = std::exp(b0);
308 float exp2b0 = std::exp(2.f * b0);
310 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
312 float scaleA = - 2 * a1 * sin0 * expb0 * (1 - exp2b0) +
313 2 * a0 * expb0 * (2 * expb0 - cos0 * (1 + exp2b0));
315 float expb1 = std::exp(b1);
316 float exp2b1 = std::exp(2.f * b1);
318 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
320 float scaleC = - 2 * c1 * sin1 * expb1 * (1 - exp2b1) +
321 2 * c0 * expb1 * (2 * expb1 - cos1 * (1 + exp2b1));
323 float sumA = scaleA / scale0;
324 float sumC = scaleC / scale1;
328 return (sumA + sumC);
332 float gaussian_2nd_deriv_coef_norm_(
float a0,
float a1,
335 float cos0,
float sin0,
336 float cos1,
float sin1,
339 float expb0 = std::exp(b0);
340 float exp2b0 = std::exp(2.f * b0);
342 float scale0 = 1 + exp2b0 - 2 * cos0 * expb0;
343 scale0 *= scale0 * scale0;
345 float scaleA = a1 * sin0 * expb0 *
346 (1 + expb0 * (2 * cos0 * (1 + exp2b0) + exp2b0 - 6)) +
347 a0 * expb0 * (2 * expb0 * (2 - cos0 * cos0) *
348 (1 - exp2b0) - cos0 * (1 - exp2b0 * exp2b0));
350 float expb1 = std::exp(b1);
351 float exp2b1 = std::exp(2.f * b1);
353 float scale1 = 1 + exp2b1 - 2 * cos1 * expb1;
354 scale1 *= scale1 * scale1;
356 float scaleC = c1 * sin1 * expb1 *
357 (1 + expb1 * (2 * cos1 * (1 + exp2b1) + exp2b1 - 6)) +
358 c0 * expb1 * (2 * expb1 * (2 - cos1 * cos1) *
359 (1 - exp2b1) - cos1 * (1 - exp2b1 * exp2b1));
361 float sumA = scaleA / scale0;
362 float sumC = scaleC / scale1;
365 return (sumA + sumC);
369 template <
class I,
class F>
372 generic_filter_(trait::image::dimension::one_d,
373 Image<I>& img_,
const F& coef,
int dir)
375 I& img = exact(img_);
376 mln_precondition(dir < I::site::dim);
379 recursivefilter_<mln_value(I)>(img, coef,
380 point1d(static_cast<def::coord>(-img.border())),
387 template <
class I,
class F>
390 generic_filter_(trait::image::dimension::two_d,
391 Image<I>& img_,
const F& coef,
int dir)
393 I& img = exact(img_);
395 mln_precondition(dir < I::site::dim);
402 recursivefilter_<mln_value(I)>(img, coef,
404 static_cast<def::coord>(j)),
407 static_cast<def::coord>(j)),
416 recursivefilter_<mln_value(I)>(img, coef,
417 point2d(static_cast<def::coord>(i),
419 point2d(static_cast<def::coord>(i),
427 template <
class I,
class F>
430 generic_filter_(trait::image::dimension::three_d,
431 Image<I>& img_,
const F& coef,
int dir)
433 I& img = exact(img_);
434 mln_precondition(dir < I::site::dim);
441 recursivefilter_<mln_value(I)>(img, coef,
442 point3d(static_cast<def::coord>(-img.border()),
443 static_cast<def::coord>(j),
447 static_cast<def::coord>(j),
460 recursivefilter_<mln_value(I)>(img, coef,
461 point3d(static_cast<def::coord>(i),
462 static_cast<def::coord>(-img.border()),
463 static_cast<def::coord>(k)),
464 point3d(static_cast<def::coord>(i),
467 static_cast<def::coord>(k)),
478 recursivefilter_<mln_value(I)>(img, coef,
479 point3d(static_cast<def::coord>(i),
480 static_cast<def::coord>(j),
481 static_cast<def::coord>(-img.border())),
482 point3d(static_cast<def::coord>(i),
483 static_cast<def::coord>(j),
494 template <
class I,
class F,
class O>
497 generic_filter_common_(trait::value::nature::floating,
503 mln_ch_value(O,
float) work_img(exact(in).domain());
504 data::paste(in, work_img);
505 extension::adjust_fill(work_img, 4, 0);
510 for (
int i = 0; i < I::site::dim; ++i)
511 generic_filter_(mln_trait_image_dimension(I)(),
515 data::paste(work_img, out);
518 template <class I, class F, class O>
521 generic_filter_common_(trait::value::nature::floating,
528 mln_ch_value(O,
float) work_img(exact(in).domain());
529 data::paste(in, work_img);
530 extension::adjust_fill(work_img, 4, 0);
535 generic_filter_(mln_trait_image_dimension(I)(),
536 work_img, coef, dir);
539 data::paste(work_img, out);
543 template <class I, class F, class O>
546 generic_filter_common_(trait::value::nature::scalar,
552 mln_ch_value(O,
float) work_img(exact(in).domain());
553 data::paste(in, work_img);
554 extension::adjust_fill(work_img, 4, 0);
559 for (
int i = 0; i < I::site::dim; ++i)
560 generic_filter_(mln_trait_image_dimension(I)(),
564 data::paste(
data::stretch(mln_value(I)(), work_img), out);
567 template <class I, class F, class O>
570 generic_filter_common_(trait::value::nature::scalar,
577 mln_ch_value(O,
float) work_img(exact(in).domain());
578 data::paste(in, work_img);
579 extension::adjust_fill(work_img, 4, 0);
584 generic_filter_(mln_trait_image_dimension(I)(),
585 work_img, coef, dir);
588 data::paste(
data::stretch(mln_value(I)(), work_img), out);
593 template <class I, class F, class O>
596 generic_filter_common_(trait::value::nature::vectorial,
610 for (
int i = 0; i < I::site::dim; ++i)
611 generic_filter_(mln_trait_image_dimension(I)(),
615 template <
class I,
class F,
class O>
618 generic_filter_common_(trait::value::nature::vectorial,
633 generic_filter_(mln_trait_image_dimension(I)(),
650 template <
typename I>
655 mln_precondition(exact(input).is_valid());
656 mln_precondition(dir < I::site::dim);
658 mln_concrete(I) output;
660 impl::recursivefilter_coef_ coef(1.68f, 3.735f,
664 sigma, impl::gaussian_norm_coef_);
666 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
667 input, coef, sigma, output, dir);
682 template <
typename I>
687 mln_precondition(exact(input).is_valid());
688 mln_precondition(dir < I::site::dim);
690 mln_concrete(I) output;
693 impl::recursivefilter_coef_
694 coef(-0.6472f, -4.531f,
698 sigma, impl::gaussian_1st_deriv_coef_norm_);
700 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
701 input, coef, sigma, output, dir);
715 template <
typename I>
720 mln_precondition(exact(input).is_valid());
721 mln_precondition(dir < I::site::dim);
723 mln_concrete(I) output;
726 impl::recursivefilter_coef_
727 coef(-1.331f, 3.661f,
731 sigma, impl::gaussian_2nd_deriv_coef_norm_);
733 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
734 input, coef, sigma, output, dir);
747 template <
typename I>
752 mln_precondition(exact(input).is_valid());
754 mln_concrete(I) output;
757 impl::recursivefilter_coef_
762 sigma, impl::gaussian_norm_coef_);
763 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
764 input, coef, sigma, output);
776 template <
typename I>
781 mln_precondition(exact(input).is_valid());
783 mln_concrete(I) output;
784 initialize(output, input);
786 impl::recursivefilter_coef_
787 coef(-0.6472f, -4.531f,
791 sigma, impl::gaussian_1st_deriv_coef_norm_);
792 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
793 input, coef, sigma, output);
804 template <typename I>
809 mln_precondition(exact(input).is_valid());
811 mln_concrete(I) output;
814 impl::recursivefilter_coef_
815 coef(-1.331f, 3.661f,
819 sigma, impl::gaussian_2nd_deriv_coef_norm_);
820 impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
821 input, coef, sigma, output);
825 # endif // ! MLN_INCLUDE_ONLY
832 #endif // ! MLN_LINEAR_GAUSSIAN_HH