https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Convert Meyer's WST implementation to neighborhood-based.
* mln/morpho/meyer_wst.hh: Use neighborhoods instead of windows to
express the connexity of the markers.
Use mln::labeling::regional_minima instead of
mln::morpho::minima_components.
* tests/morpho/meyer_wst.cc,
* tests/morpho/meyer_wst_long.cc:
Adjust tests.
mln/morpho/meyer_wst.hh | 91 ++++++++++++++++++++++++++---------------
tests/morpho/meyer_wst.cc | 10 +---
tests/morpho/meyer_wst_long.cc | 15 ++++--
3 files changed, 70 insertions(+), 46 deletions(-)
Index: mln/morpho/meyer_wst.hh
--- mln/morpho/meyer_wst.hh (revision 1698)
+++ mln/morpho/meyer_wst.hh (working copy)
@@ -45,7 +45,8 @@
# include <mln/util/greater_point.hh>
# include <mln/morpho/includes.hh>
-# include <mln/morpho/extrema_components.hh>
+# include <mln/labeling/regional_minima.hh>
+
namespace mln
@@ -61,34 +62,58 @@
processing it. Then, add a reference to
mln/morpho/lower_completion.hh. */
- /* FIXME: More doc. */
+ /** \brief Meyer's Watershed Transform (WST) algorithm.
- /// Meyer's Watershed Transform (WST) algorithm.
- template <typename DestValue, typename I, typename W>
- mln_ch_value(I, DestValue)
- meyer_wst(const Image<I>& input, const Window<W>& win,
unsigned& nbasins);
-
- /// Meyer's Watershed Transform (WST) algorithm, with no count of
- /// basins.
- template <typename DestValue, typename I, typename W>
- mln_ch_value(I, DestValue)
- meyer_wst(const Image<I>& input, const Window<W>& win);
+ \param[in] input The input image.
+ \param[in] nbh The connexity of markers.
+ \param[out] nbasins The number of basins.
+
+ \li \p L is the type of labels, used to number the watershed
+ itself (with the minimal value), and the basins.
+ \li \p I is the exact type of the input image.
+ \li \p N is the exact type of the neighborhood used to express
+ \a input's connexity. */
+ template <typename L, typename I, typename N>
+ mln_ch_value(I, L)
+ meyer_wst(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nbasins);
+
+ /** \brief Meyer's Watershed Transform (WST) algorithm, with no
+ count of basins.
+
+ \param[in] input The input image.
+ \param[in] nbh The connexity of markers.
+
+ \li \p L is the type of labels, used to number the watershed
+ itself (with the minimal value), and the basins.
+ \li \p I is the exact type of the input image.
+ \li \p N is the exact type of the neighborhood used to express
+ \a input's connexity.
+
+ Note that the first parameter, \p L, is not automatically
+ valued from the type of the actual argument during implicit
+ instantiation: you have to explicitly pass this parameter at
+ call sites. */
+ template <typename L, typename I, typename N>
+ mln_ch_value(I, L)
+ meyer_wst(const Image<I>& input, const Neighborhood<N>& nbh);
# ifndef MLN_INCLUDE_ONLY
- template <typename DestValue, typename I, typename W>
- mln_ch_value(I, DestValue)
- meyer_wst(const Image<I>& input, const Window<W>& win,
unsigned& nbasins)
+ template <typename L, typename I, typename N>
+ mln_ch_value(I, L)
+ meyer_wst(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nbasins)
{
/* FIXME: Ensure the input image has scalar values. */
- typedef DestValue marker;
+ typedef L marker;
const marker unmarked = mln_min(marker);
// Initialize the output with the markers (minima components).
mln_ch_value(I, marker) markers =
- minima_components<marker>(input, win, nbasins);
+ labeling::regional_minima (input, nbh, nbasins);
// Ordered queue.
typedef mln_point(I) point;
@@ -101,11 +126,11 @@
// hierarchical queue, with a priority level corresponding to
// the grey level input(P).
mln_piter(I) p(markers.domain());
- mln_qiter(W) q(win, p);
+ mln_niter(N) n(nbh, p);
for_all (p)
if (markers(p) == unmarked)
- for_all(q)
- if (markers.has(q) && markers(q) != unmarked)
+ for_all(n)
+ if (markers.has(n) && markers(n) != unmarked)
{
queue.push(p);
break;
@@ -122,16 +147,16 @@
marker adjacent_marker = unmarked;
// Has P a single adjacent marker?
bool single_adjacent_marker_p = true;
- mln_qiter(W) q(win, p);
- for_all(q)
- if (markers.has(q) && markers(q) != unmarked)
+ mln_niter(N) n(nbh, p);
+ for_all(n)
+ if (markers.has(n) && markers(n) != unmarked)
if (adjacent_marker == unmarked)
{
- adjacent_marker = markers(q);
+ adjacent_marker = markers(n);
single_adjacent_marker_p = true;
}
else
- if (adjacent_marker != markers(q))
+ if (adjacent_marker != markers(n))
{
single_adjacent_marker_p = false;
break;
@@ -143,20 +168,20 @@
if (single_adjacent_marker_p)
{
markers(p) = adjacent_marker;
- for_all(q)
- if (markers.has(q) && markers(q) == unmarked)
- queue.push(q);
+ for_all(n)
+ if (markers.has(n) && markers(n) == unmarked)
+ queue.push(n);
}
}
return markers;
}
- template <typename DestValue, typename I, typename W>
- mln_ch_value(I, DestValue)
- meyer_wst(const Image<I>& input, const Window<W>& win)
+ template <typename L, typename I, typename N>
+ mln_ch_value(I, L)
+ meyer_wst(const Image<I>& input, const Neighborhood<N>& nbh)
{
- unsigned nbasins;
- return meyer_wst<DestValue>(input, nbasins);
+ L nbasins;
+ return meyer_wst<L>(input, nbh, nbasins);
}
# endif // ! MLN_INCLUDE_ONLY
Index: tests/morpho/meyer_wst.cc
--- tests/morpho/meyer_wst.cc (revision 1698)
+++ tests/morpho/meyer_wst.cc (working copy)
@@ -34,8 +34,6 @@
#include <mln/core/window2d.hh>
#include <mln/core/neighb2d.hh>
-#include <mln/convert/to_window.hh>
-
#include <mln/value/int_u8.hh>
#include <mln/morpho/meyer_wst.hh>
@@ -54,11 +52,9 @@
image2d<int_u8> input;
io::pgm::load(input, MLN_IMG_DIR "/squares.pgm");
- typedef int_u8 output_val;
- unsigned nbasins;
- // FIXME: Do we really need to use a neighborood to express a 4-c window?
- image2d<int_u8> output =
- morpho::meyer_wst<output_val>(input, convert::to_window(c4()), nbasins);
+ typedef int_u8 wst_val;
+ wst_val nbasins;
+ image2d<int_u8> output = morpho::meyer_wst(input, c4(), nbasins);
std::cout << "nbasins = " << nbasins << std::endl;
io::pgm::save(output, "out.pgm");
}
Index: tests/morpho/meyer_wst_long.cc
--- tests/morpho/meyer_wst_long.cc (revision 1698)
+++ tests/morpho/meyer_wst_long.cc (working copy)
@@ -35,15 +35,17 @@
#include <mln/core/window2d.hh>
#include <mln/core/neighb2d.hh>
-#include <mln/convert/to_window.hh>
#include <mln/level/stretch.hh>
#include <mln/value/int_u8.hh>
#include <mln/value/int_u16.hh>
+#include <mln/morpho/gradient.hh>
#include <mln/morpho/closing_area.hh>
#include <mln/morpho/meyer_wst.hh>
+#include <mln/convert/to_window.hh>
+
#include <mln/pw/cst.hh>
#include <mln/pw/value.hh>
@@ -63,16 +65,17 @@
image2d<int_u8> input;
io::pgm::load(input, MLN_IMG_DIR "/lena.pgm");
+ image2d<int_u8> gradient =
+ morpho::gradient (input, convert::to_window(c4()));
+
// Simplify the input image.
image2d<int_u8> work(input.domain());
- morpho::closing_area(input, c4(), 200, work);
+ morpho::closing_area(gradient, c4(), 200, work);
// Perform a Watershed Transform.
typedef int_u16 wst_val;
- unsigned nbasins;
- // FIXME: Do we really need to use a neighborood to express a 4-c window?
- image2d<wst_val> ws =
- morpho::meyer_wst<wst_val>(work, convert::to_window(c4()), nbasins);
+ wst_val nbasins;
+ image2d<wst_val> ws = morpho::meyer_wst(work, c4(), nbasins);
std::cout << "nbasins = " << nbasins << std::endl;
// Save the image in color.