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>
62 template <
typename I,
typename N,
typename A>
65 const Accumulator<A>& a, const mln_result(A)& lambda,
70 # ifndef MLN_INCLUDE_ONLY
75 template <
typename A,
typename I>
76 void take_as_init_fastest(trait::accumulator::when_pix::use_none, A& accu,
77 const I& input,
const unsigned p)
84 template <
typename A,
typename I,
typename P>
85 void take_as_init(trait::accumulator::when_pix::use_p, A& accu,
86 const I& input,
const P& p)
92 template <
typename A,
typename I,
typename P>
93 void take_as_init(trait::accumulator::when_pix::use_none, A& accu,
94 const I& input,
const P& p)
101 template <
typename A,
typename I,
typename P>
102 void take_as_init(trait::accumulator::when_pix::use_pix, A& accu,
103 const I& input,
const P& p)
108 template <
typename A,
typename I,
typename P>
109 void take_as_init(trait::accumulator::when_pix::use_v, A& accu,
110 const I& input,
const P& p)
112 accu.take_as_init(input(p));
115 template <
typename A,
typename I>
116 void take_as_init_fastest(trait::accumulator::when_pix::use_v, A& accu,
117 const I& input,
const unsigned p)
119 accu.take_as_init(input.element(p));
123 template <
typename A,
typename I,
typename P>
126 take_as_init(mln_trait_accumulator_when_pix(A)(), accu, input, p);
129 template <
typename A,
typename I,
typename P>
130 void take_as_init_fastest(A& accu,
const I& input,
const P& p)
132 take_as_init_fastest(mln_trait_accumulator_when_pix(A)(), accu, input, p);
145 template <
typename I>
148 find_root(I& parent, const mln_psite(I) & x)
153 return parent(x) =
find_root(parent, parent(x));
156 template <
typename I,
typename N,
typename S,
typename A>
159 const Neighborhood<N>& nbh_,
160 const Site_Set<S>& s_,
161 const Accumulator<A>& a_,
162 const mln_result(A)& lambda)
164 mln_trace(
"canvas::morpho::impl::generic::attribute_filter");
167 const I& input =
exact(input_);
168 const N& nbh =
exact(nbh_);
169 const S& s =
exact(s_);
172 mln_concrete(I) output;
176 typedef mln_psite(I) P;
180 mln_ch_value(I,
bool) deja_vu;
181 mln_ch_value(I,
bool) activity;
182 mln_ch_value(I, P) parent;
183 mln_ch_value(I, A)
data;
198 mln_fwd_piter(S) p(s);
199 mln_niter(N) n(nbh, p);
212 if (input.domain().has(n) && deja_vu(n))
218 if (input(r) == input(p) || (activity(r) && (
data(r) < lambda)))
236 if (activity(r) ==
false)
251 mln_bkd_piter(S) p(s);
254 output(p) = input(p);
256 output(p) = output(parent(p));
269 template <typename I>
272 find_root_fastest(I& parent,
unsigned x)
274 if (parent.element(x) == x)
280 template <
typename I,
typename N,
typename A>
282 attribute_filter_fastest(const Image<I>& input_,
283 const Neighborhood<N>& nbh_,
284 const util::array<
unsigned>& s,
285 const Accumulator<A>& a_,
286 const mln_result(A)& lambda)
288 mln_trace(
"canvas::morpho::impl::attribute_filter_fastest");
291 const I& input =
exact(input_);
292 const N& nbh =
exact(nbh_);
297 mln_precondition(
border::get(input) >= nbh.delta());
299 mln_concrete(I) output;
303 typedef mln_psite(I) P;
306 mln_ch_value(I,
bool) deja_vu;
307 mln_ch_value(I,
bool) activity;
308 mln_ch_value(I,
unsigned) parent;
309 mln_ch_value(I, A)
data;
324 util::array<int>
dp = offsets_wrt(input, nbh);
325 const unsigned n_nbhs = dp.nelements();
326 const unsigned n_points = s.nelements();
330 for (
unsigned i = 0; i < n_points; ++i)
335 parent.element(p) =
p;
338 take_as_init_fastest(
data.element(p), input,
p);
340 for (
unsigned j = 0; j < n_nbhs; ++j)
342 unsigned n = p + dp[j];
343 if (! deja_vu.element(n))
349 if (input.element(r) == input.element(p)
350 || (activity.element(r)
351 && (
data.element(r) < lambda)))
353 data.element(p).take(
data.element(r));
354 parent.element(r) =
p;
355 if (activity.element(r) ==
false)
356 activity.element(p) =
false;
359 activity.element(p) =
false;
363 deja_vu.element(p) =
true;
370 for (
int i = n_points - 1; i >= 0 ; --i)
373 if (parent.element(p) ==
p)
374 output.element(p) = input.element(p);
376 output.element(p) = output.element(parent.element(p));
396 template <
typename I,
typename N,
typename A>
399 attribute_filter_dispatch(metal::false_,
400 const Image<I>& input,
401 const Neighborhood<N>& nbh,
402 const Accumulator<A>& a,
403 const mln_result(A)& lambda,
406 p_array<mln_psite(I)> s = increasing ?
416 template <
typename I,
typename N,
typename A>
419 attribute_filter_dispatch(metal::true_,
420 const Image<I>& input,
421 const Neighborhood<N>& nbh,
422 const Accumulator<A>& a,
423 const mln_result(A)& lambda,
428 util::array<unsigned> s =
431 data::sort_offsets_decreasing(input);
433 return impl::attribute_filter_fastest(input, nbh, s, a, lambda);
438 template <
typename I,
typename N,
typename A>
441 attribute_filter_dispatch(const Image<I>& input,
442 const Neighborhood<N>& nbh,
443 const Accumulator<A>& a,
444 const mln_result(A)& lambda,
448 test = (mlc_equal(mln_trait_image_speed(I),
449 trait::image::speed::fastest)::
value &&
450 mln_is_simple_neighborhood(N)::
value &&
451 (mlc_equal(mln_trait_accumulator_when_pix(A),
452 trait::accumulator::when_pix::use_none)::
value ||
453 mlc_equal(mln_trait_accumulator_when_pix(A),
454 trait::accumulator::when_pix::use_v)::
value))
456 return attribute_filter_dispatch(metal::bool_<test>(), input, nbh, a, lambda, increasing);
465 template <
typename I,
typename N,
typename A>
469 const Neighborhood<N>& nbh,
470 const Accumulator<A>& a,
471 const mln_result(A)& lambda,
474 return internal::attribute_filter_dispatch(input, nbh, a, lambda, increasing);
478 # endif // ! MLN_INCLUDE_ONLY
487 #endif // ! MLN_CANVAS_MORPHO_ATTRIBUTE_FILTER_HH