proto-1.0 229: Allow the user to run the shortest path watershed transform without the lower completion step

ChangeLog | 10 ++++ oln/morpho/shortest_path_watershed.hh | 81 +++++++++++++++++++++++----------- 2 files changed, 66 insertions(+), 25 deletions(-) Index: olena/ChangeLog from Roland Levillain <roland@lrde.epita.fr> Allow the user to run the shortest path watershed transform without the lower completion step (at her own risks!). * oln/morpho/shortest_path_watershed.hh (morpho::shortest_path_watershed): Rename as... (morpho::internal::shortest_path_watershed_): ...this. (morpho::shortest_path_watershed): New facade. 2005-07-04 Roland Levillain <roland@lrde.epita.fr> Index: olena/oln/morpho/shortest_path_watershed.hh --- olena/oln/morpho/shortest_path_watershed.hh (révision 226) +++ olena/oln/morpho/shortest_path_watershed.hh (copie de travail) @@ -101,42 +101,38 @@ return (ls_p + ls_q) / 2; } - } // End of namespace internal. - + /// Shortest path watershed transform implementation. template <typename DestValue, typename I> typename ch_value_type<I, DestValue>::ret - shortest_path_watershed(const abstract::image_with_nbh<I>& input) + shortest_path_watershed_(const abstract::image_with_nbh<I>& input) { mlc_is_a(I, abstract::scalar_valued_image)::ensure(); const DestValue wshed = ntg_min_val(DestValue); - // Get a lower complete image of the input. - typename ch_value_type<I, unsigned>::ret lc = - lower_completion<unsigned>(input); - // We keep a track of already processed points. - typename ch_value_type<I, bool>::ret processed (lc.size(), - lc.nbh_get()); + typename ch_value_type<I, bool>::ret processed (input.size(), + input.nbh_get()); level::fill (processed, false); // Initialise output with the minima components. typename ch_value_type<I, DestValue>::ret output = - level::minima_components<DestValue>(lc); + level::minima_components<DestValue>(input); // Distance. - typedef typename ch_value_type<I, unsigned>::ret dist_type; - dist_type dist (lc.size(), lc.nbh_get()); + typedef ntg_cumul_type(DestValue) cumul_type; + typedef typename ch_value_type<I, cumul_type>::ret dist_type; + dist_type dist (input.size(), input.nbh_get()); level::fill(dist, ntg_max_val(DestValue)); // Initialize distance with values of minima, and mark these - // points as processed (remember that points of LC who have a - // value greater than ntg_min_val(DestValue) belongs to a + // points as processed (remember that points of INPUT who have + // a value greater than ntg_min_val(DestValue) belongs to a // minimum). - oln_type_of(I, piter) p(lc.size()); + oln_type_of(I, piter) p(input.size()); for_all_p (p) - if (output[p].value() > ntg_min_val(DestValue)) - dist[p] = lc[p]; + if (output[p] > ntg_min_val(DestValue)) + dist[p] = input[p]; // Ordered queue. typedef oln_type_of(I, point) point_type; @@ -149,12 +145,13 @@ // Fill the ordered queue with the points of the border of the // minima of the (lower complete) input. for_all_p (p) - if (output[p].value() > ntg_min_val(DestValue)) + if (output[p] > ntg_min_val(DestValue)) { bool border_p = false; - oln_type_of(I, niter) n(lc); + oln_type_of(I, niter) n(input); for_all_n_of_p (n, p) - if (lc.hold(n) and output[n].value() == ntg_min_val(DestValue)) + if (input.hold(n) and + output[n] == ntg_min_val(DestValue)) { // P is both in a minima and adjacent to a non minima: // it's on the border of a minima. @@ -176,19 +173,19 @@ continue; processed[p] = true; - oln_type_of(I, niter) n(lc); + oln_type_of(I, niter) n(input); for_all_n_of_p (n, p) { - if (lc.hold(n)) - if (dist[p] + internal::cost(lc, p, n) < dist[n]) + if (input.hold(n)) + if (dist[p] + internal::cost(input, p, n) < dist[n]) { - dist[n] = dist[p] + internal::cost(lc, p, n); + dist[n] = dist[p] + internal::cost(input, p, n); output[n] = output[p]; q.push(n); } else if (output[n] != wshed and - dist[p] + internal::cost(lc, p, n) == dist[n] and + dist[p] + internal::cost(input, p, n) == dist[n] and output[n] != output[p]) { output[n] = wshed; @@ -200,6 +197,40 @@ return output; } + } // End of namespace oln::morpho::internal. + + + /*! Watershed transform w.r.t. topographical distance based on + image integration via the Dijkstra-Moore shortest path + algorithm. + + This facade lets the user should whether the lower completion + pass shoud be done before actually computing the watershed + transform. Unless you really what you're doing, you probably + want to proceed to this lower completion. + + \param input input image + \param lower_completion_p whether \a input should be turned into a + lower complete image */ + template <typename DestValue, typename I> + typename ch_value_type<I, DestValue>::ret + shortest_path_watershed(const abstract::image_with_nbh<I>& input, + bool lower_completion_p = true) + { + mlc_is_a(I, abstract::scalar_valued_image)::ensure(); + + if (lower_completion_p) + { + // Get a lower complete image of the input. + typedef ntg_cumul_type(DestValue) cumul_type; + typename ch_value_type<I, cumul_type>::ret lc = + lower_completion<cumul_type>(input); + return internal::shortest_path_watershed_<DestValue>(lc); + } + else + return internal::shortest_path_watershed_<DestValue>(input); + } + } // end of namespace oln::morpho } // end of namespace oln
participants (1)
-
Roland Levillain