* mln/make/rag_and_labeled_wsl.hh: new routine.
* tests/make/Makefile.am,
* tests/make/rag_and_labeled_wsl.cc: new test.
---
milena/ChangeLog | 9 ++
milena/mln/make/rag_and_labeled_wsl.hh | 230 ++++++++++++++++++++++++++++++
milena/tests/make/Makefile.am | 2 +
milena/tests/make/rag_and_labeled_wsl.cc | 90 ++++++++++++
4 files changed, 331 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/make/rag_and_labeled_wsl.hh
create mode 100644 milena/tests/make/rag_and_labeled_wsl.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index e7cf8d9..7334d37 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,12 @@
+2009-04-01 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
+ Add a new routine to create a region adjacency graph.
+
+ * mln/make/rag_and_labeled_wsl.hh: new routine.
+
+ * tests/make/Makefile.am,
+ * tests/make/rag_and_labeled_wsl.cc: new test.
+
2009-04-01 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Several fixes.
diff --git a/milena/mln/make/rag_and_labeled_wsl.hh
b/milena/mln/make/rag_and_labeled_wsl.hh
new file mode 100644
index 0000000..d80b954
--- /dev/null
+++ b/milena/mln/make/rag_and_labeled_wsl.hh
@@ -0,0 +1,230 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MAKE_RAG_AND_ALBL_HH
+# define MLN_MAKE_RAG_AND_ALBL_HH
+
+/// \file mln/make/rag_and_labeled_wsl.hh
+///
+/// Create a region adjacency graph and a label image of the watershed line
+/// from a watershed image.
+///
+/// \sa morpho::watershed::flooding.
+///
+/// \todo Do not use mln_max() as background label!
+
+# include <map>
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/box2d.hh>
+# include <mln/extension/adjust_fill.hh>
+# include <mln/util/graph.hh>
+# include <mln/util/couple.hh>
+
+
+namespace mln
+{
+
+ namespace make
+ {
+
+ /// Create a region adjacency graph and a label image of the watershed line
+ /// from a watershed image.
+ ///
+ /// \param[in] wshd Watershed image.
+ /// \param[in] nbh Neighborhood
+ /// \param[in] nbasins Number of influence zone in \p wshd.
+ ///
+ /// \return A couple. First element is the graph, second element is an
+ /// image with a labeled watershed line.
+ template <typename I, typename N>
+ util::couple<util::graph,mln_concrete(I)>
+ rag_and_labeled_wsl(const Image<I>& wshd_,
+ const Neighborhood<N>& nbh_,
+ const mln_value(I)& nbasins);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ template <typename I, typename N>
+ inline
+ void
+ rag_and_labeled_wsl_tests(const Image<I>& wshd,
+ const Neighborhood<N>& nbh,
+ const mln_value(I)&)
+ {
+ mln_precondition(exact(wshd).is_valid());
+ mln_precondition(exact(nbh).is_valid());
+ (void) wshd;
+ (void) nbh;
+ }
+
+ } // end of namespace mln::make::internal
+
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename N>
+ inline
+ util::couple<util::graph,mln_concrete(I)>
+ rag_and_labeled_wsl(const Image<I>& wshd_,
+ const Neighborhood<N>& nbh_,
+ const mln_value(I)& nbasins)
+ {
+ trace::entering("make::impl::generic::rag_and_labeled_wsl");
+
+ internal::rag_and_labeled_wsl_tests(wshd_, nbh_, nbasins);
+ const I& wshd = exact(wshd_);
+ const N& nbh = exact(nbh_);
+ typedef mln_value(I) L;
+
+ mln::image2d<bool> adj(mln::box2d(nbasins.next(), nbasins.next()));
+ data::fill(adj, false);
+ extension::adjust_fill(wshd, nbh, 0u);
+
+ mln_concrete(I) output(wshd.domain());
+
+ // FIXME: we would like to not use mln_value() but 0 instead.
+ // We can't do that because graph edges are numbered from 0.
+ data::fill(output, mln_max(mln_value(I)).prev());
+
+ std::map<util::couple<L,L>, mln_value(I)> c2la;
+ util::array<util::couple<L,L> > la2c;
+ mln_value(I) nlabels = literal::zero;
+
+ L l1, l2;
+ mln_piter(I) p(wshd.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ if (wshd(p) != 0u)
+ continue;
+ // p is in the watershed line.
+ l1 = l2 = 0;
+ for_all(n)
+ if (wshd.has(n) && wshd(n) != 0u)
+ {
+ if (l1 == 0u) // First label to be stored.
+ l1 = wshd(n);
+ else
+ if (wshd(n) != l1) // Useless: && l2 == 0)
+ { // Second label to be stored.
+ mln_invariant(l2 == 0u);
+ l2 = wshd(n);
+ break;
+ }
+ }
+ if (l2 == 0u || l1 == 0u)
+ continue;
+ if (l2 < l1)
+ std::swap(l1, l2);
+
+ // adjacency l1 l2
+ util::couple<L,L> c = make::couple(l2,l1);
+ if (c2la.find(c) == c2la.end())
+ {
+ c2la[c] = nlabels++;
+ la2c.append(c);
+ }
+ output(p) = c2la[c];
+
+ }
+
+ // Construct graph.
+ util::graph g;
+ g.add_vertices(nbasins.next());
+ for (unsigned i = 0; i < la2c.nelements(); ++i)
+ g.add_edge(la2c[i].first(), la2c[i].second());
+
+ trace::exiting("make::impl::generic::rag_and_labeled_wsl");
+ return make::couple(g, output);
+ }
+
+ } // end of namespace mln::make::impl::generic
+
+ } // end of namespace mln::make::impl
+
+
+
+ namespace internal
+ {
+
+ template <typename I, typename N>
+ inline
+ util::couple<util::graph,mln_concrete(I)>
+ rag_and_labeled_wsl_dispatch(const Image<I>& wshd,
+ const Neighborhood<N>& nbh,
+ const mln_value(I)& nbasins)
+ {
+ return make::impl::generic::rag_and_labeled_wsl(wshd, nbh, nbasins);
+ }
+
+ } // end of namespace mln::make::internal
+
+
+
+ // Facade
+
+ template <typename I, typename N>
+ inline
+ util::couple<util::graph,mln_concrete(I)>
+ rag_and_labeled_wsl(const Image<I>& wshd,
+ const Neighborhood<N>& nbh,
+ const mln_value(I)& nbasins)
+ {
+ trace::entering("make::rag_and_labeled_wsl");
+
+ internal::rag_and_labeled_wsl_tests(wshd, nbh, nbasins);
+
+ util::couple<util::graph,mln_concrete(I)>
+ result = internal::rag_and_labeled_wsl_dispatch(wshd, nbh, nbasins);
+
+ trace::exiting("make::rag_and_labeled_wsl");
+ return result;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MAKE_RAG_AND_ALBL_HH
diff --git a/milena/tests/make/Makefile.am b/milena/tests/make/Makefile.am
index bf96093..7e4c12b 100644
--- a/milena/tests/make/Makefile.am
+++ b/milena/tests/make/Makefile.am
@@ -10,6 +10,7 @@ check_PROGRAMS = \
image3d \
mat \
region_adjacency_graph \
+ rag_and_labeled_wsl \
w_window \
w_window_directional
@@ -20,6 +21,7 @@ image2d_SOURCES = image2d.cc
image3d_SOURCES = image3d.cc
mat_SOURCES = mat.cc
region_adjacency_graph_SOURCES = region_adjacency_graph.cc
+rag_and_labeled_wsl_SOURCES = rag_and_labeled_wsl.cc
w_window_SOURCES = w_window.cc
w_window_directional_SOURCES = w_window_directional.cc
diff --git a/milena/tests/make/rag_and_labeled_wsl.cc
b/milena/tests/make/rag_and_labeled_wsl.cc
new file mode 100644
index 0000000..5abb031
--- /dev/null
+++ b/milena/tests/make/rag_and_labeled_wsl.cc
@@ -0,0 +1,90 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/make/rag_and_labeled_wsl.cc
+///
+/// Tests on mln::make::rag_and_labeled_wsl
+
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/value/label_8.hh>
+
+#include <mln/make/image2d.hh>
+#include <mln/make/rag_and_labeled_wsl.hh>
+
+# include <mln/debug/println.hh>
+
+int main()
+{
+ using namespace mln;
+
+ value::label_8 vals[16] = { 1, 0, 3, 3,
+ 1, 0, 0, 0,
+ 0, 0, 4, 4,
+ 2, 2, 0, 4 };
+
+ typedef image2d<value::label_8> wst_t;
+ wst_t ima = make::image2d(vals);
+
+ util::couple<util::graph, wst_t>
+ res = make::rag_and_labeled_wsl(ima, c4(), 4u);
+
+ // check that adjacency labels map edge labels.
+ mln_piter_(wst_t) p(res.second().domain());
+ mln_niter_(neighb2d) n(c4(),p);
+ for_all(p)
+ if (res.second()(p) != mln_max(value::label_8))
+ {
+ value::label_8 l1 = 0, l2 = 0;
+ for_all(n)
+ if (ima.has(n) && ima(n) != 0u)
+ {
+ if (l1 == 0u) // First label to be stored.
+ l1 = ima(n);
+ else
+ if (ima(n) != l1) // Useless: && l2 == 0)
+ { // Second label to be stored.
+ mln_invariant(l2 == 0u);
+ l2 = ima(n);
+ break;
+ }
+ }
+ if (l2 < l1)
+ std::swap(l1, l2);
+ mln_assertion(res.first().v1(res.second()(p)) == l1);
+ mln_assertion(res.first().v2(res.second()(p)) == l2);
+ }
+
+ mln_assertion(res.first().e_nmax() == 4u);
+ mln_assertion(res.first().v_nmax() == 5u);
+ mln_assertion(res.first().v_nmax_nbh_edges(0) == 0);
+ for (unsigned i = 1; i < 4; ++i)
+ mln_assertion(res.first().v_nmax_nbh_edges(i) == 2);
+}
+
--
1.5.6.5