27 #ifndef MLN_MORPHO_SKELETON_CONSTRAINED_HH
28 # define MLN_MORPHO_SKELETON_CONSTRAINED_HH
37 # include <mln/core/concept/image.hh>
38 # include <mln/core/concept/neighborhood.hh>
39 # include <mln/core/site_set/p_queue_fast.hh>
40 # include <mln/core/site_set/p_priority.hh>
41 # include <mln/extension/adjust_duplicate.hh>
42 # include <mln/extension/adjust_fill.hh>
43 # include <mln/data/fill.hh>
45 # include <mln/util/timer.hh>
54 typename N,
typename F,
55 typename K,
typename R>
57 skeleton_constrained(const Image<I>& input,
58 const Neighborhood<N>& nbh, const F& is_simple,
59 const Image<K>& constraint, const Image<R>& priority);
63 # ifndef MLN_INCLUDE_ONLY
73 typename N,
typename F,
74 typename K,
typename R>
77 skeleton_constrained(const Image<I>& input_,
78 const Neighborhood<N>& nbh_, const F& is_simple,
79 const Image<K>& constraint_, const Image<R>& priority_)
81 trace::entering(
"morpho::skeleton_constrained");
83 const I& input = exact(input_);
84 const N& nbh = exact(nbh_);
85 const K& constraint = exact(constraint_);
86 const R& priority = exact(priority_);
88 mln_precondition(input.is_valid());
89 mln_precondition(nbh.is_valid());
90 mln_precondition(constraint.is_valid());
91 mln_precondition(priority.is_valid());
93 typedef mln_value(I) V;
94 mlc_is(V,
bool)::check();
96 extension::adjust_duplicate(input, nbh);
97 extension::adjust_duplicate(constraint, nbh);
98 extension::adjust_duplicate(priority, nbh);
102 typedef mln_psite(I) P;
103 typedef p_queue_fast<P> Q;
104 p_priority<mln_value(R), Q> q;
106 mln_concrete(I) output;
113 mln_piter(I) p(input.domain());
115 if (input(p) == false &&
116 is_simple.check(input, p))
119 q.push(priority(p), p);
127 mln_niter(N) n(nbh, p);
128 while (! q.is_empty())
134 constraint(n) == false &&
135 is_simple.check(output, n))
138 q.push(priority(n), n);
143 trace::exiting(
"morpho::skeleton_constrained");
150 template <
typename I,
151 typename N,
typename F,
152 typename K,
typename R>
154 mln_ch_value(I,
bool)
155 skeleton_constrained_fast(const Image<I>& input_,
156 const Neighborhood<N>& nbh_,
158 const Image<K>& constraint_,
159 const Image<R>& priority_)
161 trace::entering(
"morpho::skeleton_constrained_fast");
163 const I& input = exact(input_);
164 const N& nbh = exact(nbh_);
165 const K& constraint = exact(constraint_);
166 const R& priority = exact(priority_);
168 mln_precondition(input.is_valid());
169 mln_precondition(nbh.is_valid());
170 mln_precondition(constraint.is_valid());
171 mln_precondition(priority.is_valid());
173 typedef mln_value(I) V;
174 mlc_is(V,
bool)::check();
181 extension::adjust_fill(input, nbh, false);
182 extension::adjust_fill(constraint, nbh, false);
186 typedef p_queue_fast<
unsigned> Q;
187 p_priority<mln_value(R), Q> q;
189 mln_concrete(I) output;
196 mln_pixter(
const I) p_in(input);
198 if (p_in.val() == false &&
199 is_simple.check__(input, p_in))
202 q.push(priority.element(p_in.offset()), p_in);
208 util::array<int> dp = offsets_wrt(input, nbh.foreground());
209 const unsigned n_nbhs = dp.nelements();
210 while (! q.is_empty())
212 unsigned p = q.pop_front();
214 for (
unsigned i = 0; i < n_nbhs; ++i)
216 unsigned n = p + dp[i];
218 if (output.element(n) ==
true &&
219 constraint.element(n) ==
false &&
220 is_simple.check__(output, n))
222 output.element(n) =
false;
223 q.push(priority.element(n), n);
229 trace::exiting(
"morpho::skeleton_constrained_fast");
240 template <
typename I,
241 typename N,
typename F,
242 typename K,
typename R>
244 mln_ch_value(I,
bool)
245 skeleton_constrained_dispatch(
246 mln::trait::image::value_access::any,
247 mln::trait::image::value_storage::any,
248 const Image<I>& input,
249 const Neighborhood<N>& nbh,
251 const Image<K>& constraint,
252 const Image<R>& priority)
254 return impl::generic::skeleton_constrained(input, nbh,
260 template <
typename I,
261 typename N,
typename F,
262 typename K,
typename R>
264 mln_ch_value(I,
bool)
265 skeleton_constrained_dispatch(
266 mln::trait::image::value_access::direct,
267 mln::trait::image::value_storage::one_block,
268 const Image<I>& input,
269 const Neighborhood<N>& nbh,
271 const Image<K>& constraint,
272 const Image<R>& priority)
274 return impl::skeleton_constrained_fast(input, nbh,
284 template <
typename I,
285 typename N,
typename F,
286 typename K,
typename R>
288 mln_ch_value(I,
bool)
289 skeleton_constrained(const Image<I>& input,
290 const Neighborhood<N>& nbh, const F& is_simple,
291 const Image<K>& constraint, const Image<R>& priority)
293 trace::entering(
"morpho::skeleton_constrained");
295 mln_ch_value(I,
bool)
296 output = internal::skeleton_constrained_dispatch(
297 mln_trait_image_value_access(I)(),
298 mln_trait_image_value_storage(I)(),
299 input, nbh, is_simple, constraint, priority);
301 trace::exiting("morpho::skeleton_constrained");
305 # endif // ! MLN_INCLUDE_ONLY
312 #endif // ! MLN_MORPHO_SKELETON_CONSTRAINED_HH