26 #ifndef MLN_MORPHO_WATERSHED_FLOODING_HH
27 # define MLN_MORPHO_WATERSHED_FLOODING_HH
41 # include <mln/trait/ch_value.hh>
43 # include <mln/morpho/includes.hh>
44 # include <mln/literal/zero.hh>
45 # include <mln/labeling/regional_minima.hh>
47 # include <mln/core/site_set/p_queue_fast.hh>
48 # include <mln/core/site_set/p_priority.hh>
50 # include <mln/extension/adjust_fill.hh>
74 template <
typename L,
typename I,
typename N>
76 flooding(const Image<I>& input, const Neighborhood<N>& nbh,
95 template <typename L, typename I, typename N>
97 flooding(const Image<I>& input, const Neighborhood<N>& nbh);
101 # ifndef MLN_INCLUDE_ONLY
112 template <
typename L,
typename I,
typename N>
114 flooding(const Image<I>& input_, const Neighborhood<N>& nbh_,
117 trace::entering(
"morpho::watershed::impl::generic::flooding");
120 const I input = exact(input_);
121 const N nbh = exact(nbh_);
126 typedef mln_value(I) V;
127 const V max = mln_max(V);
130 mln_ch_value(I, marker) output =
131 labeling::regional_minima (input, nbh, n_basins);
133 typedef mln_psite(I) psite;
136 typedef p_queue_fast<psite> Q;
137 p_priority<V, Q> queue;
140 mln_ch_value(I,
bool) in_queue;
141 initialize(in_queue, input);
142 data::fill(in_queue, false);
147 mln_piter(I) p(output.domain());
148 mln_niter(N) n(nbh, p);
150 if (output(p) == unmarked)
152 if (output.domain().has(n) && output(n) != unmarked)
154 queue.push(max - input(p), p);
162 while (! queue.is_empty())
164 psite p = queue.front();
168 marker adjacent_marker = unmarked;
170 bool single_adjacent_marker_p =
true;
171 mln_niter(N) n(nbh, p);
173 if (output.domain().has(n) && output(n) != unmarked)
175 if (adjacent_marker == unmarked)
177 adjacent_marker = output(n);
178 single_adjacent_marker_p =
true;
181 if (adjacent_marker != output(n))
183 single_adjacent_marker_p =
false;
191 if (single_adjacent_marker_p)
193 output(p) = adjacent_marker;
195 if (output.domain().has(n) && output(n) == unmarked
198 queue.push(max - input(n), n);
204 trace::exiting(
"morpho::watershed::impl::generic::flooding");
214 template <
typename I,
typename N,
typename L>
216 flooding_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_,
219 trace::entering(
"morpho::watershed::impl::flooding_fastest");
222 const I input = exact(input_);
223 const N nbh = exact(nbh_);
228 typedef mln_value(I) V;
229 const V max = mln_max(V);
231 extension::adjust_fill(input, nbh, max);
234 typedef mln_ch_value(I, L) O;
235 O output = labeling::regional_minima(input, nbh, n_basins);
236 extension::fill(output, unmarked);
239 typedef p_queue_fast<
unsigned> Q;
240 p_priority<V, Q> queue;
247 mln_ch_value(I,
bool) in_queue;
248 initialize(in_queue, input);
249 data::fill(in_queue, false);
250 extension::fill(in_queue, true);
255 mln_pixter(const O) p_out(output);
256 mln_nixter(const O, N) n_out(p_out, nbh);
258 if (p_out.val() == unmarked)
260 if (n_out.val() != unmarked)
262 unsigned po = p_out.offset();
263 queue.push(max - input.element(po), po);
264 in_queue.element(po) =
true;
271 util::array<int> dp = offsets_wrt(input, nbh);
272 const unsigned n_nbhs = dp.nelements();
273 while (! queue.is_empty())
275 unsigned p = queue.front();
279 marker adjacent_marker = unmarked;
281 bool single_adjacent_marker_p =
true;
282 for (
unsigned i = 0; i < n_nbhs; ++i)
284 unsigned n = p + dp[i];
286 if (output.element(n) != unmarked)
288 if (adjacent_marker == unmarked)
290 adjacent_marker = output.element(n);
291 single_adjacent_marker_p =
true;
294 if (adjacent_marker != output.element(n))
296 single_adjacent_marker_p =
false;
305 if (single_adjacent_marker_p)
307 output.element(p) = adjacent_marker;
308 for (
unsigned i = 0; i < n_nbhs; ++i)
310 unsigned n = p + dp[i];
311 if (output.element(n) == unmarked
313 && ! in_queue.element(n))
315 queue.push(max - input.element(n), n);
316 in_queue.element(n) =
true;
322 trace::exiting(
"morpho::watershed::impl::flooding_fastest");
336 template <
typename I,
typename N,
typename L>
339 flooding_dispatch(metal::false_,
340 const Image<I>& input, const Neighborhood<N>& nbh,
343 return impl::generic::flooding(input, nbh, n_basins);
347 template <
typename I,
typename N,
typename L>
350 flooding_dispatch(metal::true_,
351 const Image<I>& input, const Neighborhood<N>& nbh,
354 return impl::flooding_fastest(input, nbh, n_basins);
357 template <
typename I,
typename N,
typename L>
360 flooding_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
364 test = mlc_equal(mln_trait_image_speed(I),
365 trait::image::speed::fastest)::
value
367 mln_is_simple_neighborhood(N)::
value
369 return flooding_dispatch(metal::bool_<test>(),
370 input, nbh, n_basins);
378 template <
typename L,
typename I,
typename N>
383 trace::entering(
"morpho::watershed::flooding");
387 mln_ch_value(I, L) output =
388 internal::flooding_dispatch(input, nbh, n_basins);
390 trace::exiting(
"morpho::watershed::flooding");
394 template <
typename L,
typename I,
typename N>
399 return flooding<L>(input, nbh, nbasins);
402 # endif // ! MLN_INCLUDE_ONLY
411 #endif // ! MLN_MORPHO_WATERSHED_FLOODING_HH