27 #ifndef MLN_CANVAS_MORPHO_ATTRIBUTE_FILTER_HH
28 # define MLN_CANVAS_MORPHO_ATTRIBUTE_FILTER_HH
35 # include <mln/core/concept/image.hh>
36 # include <mln/core/concept/neighborhood.hh>
37 # include <mln/core/concept/accumulator.hh>
39 # include <mln/data/sort_offsets.hh>
40 # include <mln/trait/accumulators.hh>
41 # include <mln/util/pix.hh>
43 # include <mln/border/get.hh>
44 # include <mln/data/fill.hh>
45 # include <mln/extension/adjust_fill.hh>
46 # include <mln/data/sort_psites.hh>
59 template <
typename I,
typename N,
typename A>
61 attribute_filter(const Image<I>& input, const Neighborhood<N>& nbh,
62 const Accumulator<A>& a, const mln_result(A)& lambda,
67 # ifndef MLN_INCLUDE_ONLY
72 template <
typename A,
typename I>
73 void take_as_init_fastest(trait::accumulator::when_pix::use_none, A& accu,
74 const I& input,
const unsigned p)
81 template <
typename A,
typename I,
typename P>
82 void take_as_init(trait::accumulator::when_pix::use_p, A& accu,
83 const I& input,
const P& p)
89 template <
typename A,
typename I,
typename P>
90 void take_as_init(trait::accumulator::when_pix::use_none, A& accu,
91 const I& input,
const P& p)
98 template <
typename A,
typename I,
typename P>
99 void take_as_init(trait::accumulator::when_pix::use_pix, A& accu,
100 const I& input,
const P& p)
105 template <
typename A,
typename I,
typename P>
106 void take_as_init(trait::accumulator::when_pix::use_v, A& accu,
107 const I& input,
const P& p)
109 accu.take_as_init(input(p));
112 template <
typename A,
typename I>
113 void take_as_init_fastest(trait::accumulator::when_pix::use_v, A& accu,
114 const I& input,
const unsigned p)
116 accu.take_as_init(input.element(p));
120 template <
typename A,
typename I,
typename P>
121 void take_as_init(A& accu,
const I& input,
const P& p)
123 take_as_init(mln_trait_accumulator_when_pix(A)(), accu, input, p);
126 template <
typename A,
typename I,
typename P>
127 void take_as_init_fastest(A& accu,
const I& input,
const P& p)
129 take_as_init_fastest(mln_trait_accumulator_when_pix(A)(), accu, input, p);
142 template <
typename I>
145 find_root(I& parent, const mln_psite(I) & x)
150 return parent(x) = find_root(parent, parent(x));
153 template <
typename I,
typename N,
typename S,
typename A>
155 attribute_filter(const Image<I>& input_,
156 const Neighborhood<N>& nbh_,
157 const Site_Set<S>& s_,
158 const Accumulator<A>& a_,
159 const mln_result(A)& lambda)
161 trace::entering(
"canvas::morpho::impl::generic::attribute_filter");
164 const I& input = exact(input_);
165 const N& nbh = exact(nbh_);
166 const S& s = exact(s_);
169 mln_concrete(I) output;
173 typedef mln_psite(I) P;
177 mln_ch_value(I,
bool) deja_vu;
178 mln_ch_value(I,
bool) activity;
179 mln_ch_value(I, P) parent;
180 mln_ch_value(I, A)
data;
195 mln_fwd_piter(S) p(s);
196 mln_niter(N) n(nbh, p);
205 take_as_init(
data(p), input, p);
209 if (input.domain().has(n) && deja_vu(n))
212 P r = find_root(parent, n);
215 if (input(r) == input(p) || (activity(r) && (
data(r) < lambda)))
233 if (activity(r) ==
false)
248 mln_bkd_piter(S) p(s);
251 output(p) = input(p);
253 output(p) = output(parent(p));
256 trace::exiting("canvas::morpho::impl::generic::attribute_filter");
267 template <typename I>
270 find_root_fastest(I& parent,
unsigned x)
272 if (parent.element(x) == x)
275 return parent.element(x) = find_root_fastest(parent, parent.element(x));
278 template <
typename I,
typename N,
typename A>
280 attribute_filter_fastest(const Image<I>& input_,
281 const Neighborhood<N>& nbh_,
282 const util::array<
unsigned>& s,
283 const Accumulator<A>& a_,
284 const mln_result(A)& lambda)
286 trace::entering(
"canvas::morpho::impl::attribute_filter_fastest");
289 const I& input = exact(input_);
290 const N& nbh = exact(nbh_);
295 mln_precondition(
border::get(input) >= nbh.delta());
297 mln_concrete(I) output;
301 typedef mln_psite(I) P;
304 mln_ch_value(I,
bool) deja_vu;
305 mln_ch_value(I,
bool) activity;
306 mln_ch_value(I,
unsigned) parent;
307 mln_ch_value(I, A)
data;
322 util::array<int> dp = offsets_wrt(input, nbh);
323 const unsigned n_nbhs = dp.nelements();
324 const unsigned n_points = s.nelements();
328 for (
unsigned i = 0; i < n_points; ++i)
333 parent.element(p) = p;
336 take_as_init_fastest(
data.element(p), input, p);
338 for (
unsigned j = 0; j < n_nbhs; ++j)
340 unsigned n = p + dp[j];
341 if (! deja_vu.element(n))
344 unsigned r = find_root_fastest(parent, n);
347 if (input.element(r) == input.element(p)
348 || (activity.element(r)
349 && (
data.element(r) < lambda)))
351 data.element(p).take(
data.element(r));
352 parent.element(r) = p;
353 if (activity.element(r) ==
false)
354 activity.element(p) =
false;
357 activity.element(p) =
false;
361 deja_vu.element(p) =
true;
368 for (
int i = n_points - 1; i >= 0 ; --i)
371 if (parent.element(p) == p)
372 output.element(p) = input.element(p);
374 output.element(p) = output.element(parent.element(p));
378 trace::exiting(
"canvas::morpho::impl::attribute_filter_fastest");
395 template <
typename I,
typename N,
typename A>
398 attribute_filter_dispatch(metal::false_,
399 const Image<I>& input,
400 const Neighborhood<N>& nbh,
401 const Accumulator<A>& a,
402 const mln_result(A)& lambda,
405 p_array<mln_psite(I)> s = increasing ?
409 return impl::generic::attribute_filter(input, nbh, s, a, lambda);
415 template <
typename I,
typename N,
typename A>
418 attribute_filter_dispatch(metal::true_,
419 const Image<I>& input,
420 const Neighborhood<N>& nbh,
421 const Accumulator<A>& a,
422 const mln_result(A)& lambda,
427 util::array<unsigned> s =
430 data::sort_offsets_decreasing(input);
432 return impl::attribute_filter_fastest(input, nbh, s, a, lambda);
437 template <
typename I,
typename N,
typename A>
440 attribute_filter_dispatch(const Image<I>& input,
441 const Neighborhood<N>& nbh,
442 const Accumulator<A>& a,
443 const mln_result(A)& lambda,
447 test = (mlc_equal(mln_trait_image_speed(I),
448 trait::image::speed::fastest)::
value &&
449 mln_is_simple_neighborhood(N)::
value &&
450 (mlc_equal(mln_trait_accumulator_when_pix(A),
451 trait::accumulator::when_pix::use_none)::
value ||
452 mlc_equal(mln_trait_accumulator_when_pix(A),
453 trait::accumulator::when_pix::use_v)::
value))
455 return attribute_filter_dispatch(metal::bool_<test>(), input, nbh, a, lambda, increasing);
464 template <
typename I,
typename N,
typename A>
467 attribute_filter(const Image<I>& input,
468 const Neighborhood<N>& nbh,
469 const Accumulator<A>& a,
470 const mln_result(A)& lambda,
473 return internal::attribute_filter_dispatch(input, nbh, a, lambda, increasing);
477 # endif // ! MLN_INCLUDE_ONLY
486 #endif // ! MLN_CANVAS_MORPHO_ATTRIBUTE_FILTER_HH