https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a morpho tree computation.
* mln/morpho/tree: New directory.
* mln/morpho/tree/compute_parent.hh: New; revamp of...
* sandbox/geraud/max_tree_nnodes.cc: ...this file.
* tests/morpho/tree: New directory.
* tests/morpho/tree/compute_parent.cc:
* tests/morpho/tree/Makefile.am: New.
* tests/morpho/Makefile.am: Update.
* mln/canvas/morpho/all.hh: Upgrade doc style.
mln/canvas/morpho/all.hh | 16 +-
mln/morpho/tree/compute_parent.hh | 273 +++++++++++++++++++++++-------------
tests/morpho/Makefile.am | 4
tests/morpho/tree/Makefile.am | 11 +
tests/morpho/tree/compute_parent.cc | 80 ++++++++++
5 files changed, 284 insertions(+), 100 deletions(-)
Index: tests/morpho/tree/compute_parent.cc
--- tests/morpho/tree/compute_parent.cc (revision 0)
+++ tests/morpho/tree/compute_parent.cc (revision 0)
@@ -0,0 +1,80 @@
+// Copyright (C) 2008 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/morpho/tree/compute_parent.cc
+///
+/// Tests on mln::morpho::tree::compute_parent.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/debug/println.hh>
+#include <mln/debug/iota.hh>
+
+#include <mln/core/var.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/pw/value.hh>
+
+#include <mln/morpho/tree/compute_parent.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ {
+ bool vals[] = { 1, 1, 1,
+ 0, 1, 0,
+ 0, 0, 1 };
+ image2d<bool> ima = make::image2d(vals);
+ mln_VAR(sub, ima | pw::value(ima));
+ debug::println(sub);
+
+ mln_VAR(par, morpho::tree::compute_parent(sub, c4(), sub.domain()));
+ debug::println(par);
+ }
+
+/*
+ {
+ image2d<unsigned> ima(3, 3);
+ debug::iota(ima);
+ debug::println(ima);
+
+ debug::println( morpho::tree::compute_parent(ima, c4(), ima.domain()) );
+ }
+
+
+ {
+ image2d<unsigned> ima(3, 3);
+ level::fill(ima, 0);
+ debug::println(ima);
+
+ debug::println( morpho::tree::compute_parent(ima, c4(), ima.domain()) );
+ }
+*/
+
+}
Index: tests/morpho/tree/Makefile.am
--- tests/morpho/tree/Makefile.am (revision 0)
+++ tests/morpho/tree/Makefile.am (revision 0)
@@ -0,0 +1,11 @@
+## Process this file through Automake to create Makefile.in -*- Makefile -*-
+
+include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ compute_tree
+
+
+compute_tree_SOURCES = compute_tree_.cc
+
+TESTS = $(check_PROGRAMS)
Index: tests/morpho/Makefile.am
--- tests/morpho/Makefile.am (revision 2937)
+++ tests/morpho/Makefile.am (working copy)
@@ -2,7 +2,9 @@
include $(top_srcdir)/milena/tests/tests.mk
-SUBDIRS = elementary
+SUBDIRS = \
+ elementary \
+ tree
check_PROGRAMS = \
artificial_line_graph_image_wst \
Index: mln/morpho/tree/compute_parent.hh
--- mln/morpho/tree/compute_parent.hh (revision 0)
+++ mln/morpho/tree/compute_parent.hh (working copy)
@@ -1,151 +1,240 @@
+// Copyright (C) 2008 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.
+
+#ifndef MLN_MORPHO_TREE_COMPUTE_PARENT_HH
+# define MLN_MORPHO_TREE_COMPUTE_PARENT_HH
+
+/// \file mln/morpho/tree/compute_parent.hh
+///
+/// Compute a canonized tree from an image.
+///
+/// \todo Specialize for low quant (and try fastest).
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/level/fill.hh>
-# include <mln/util/pix.hh>
-# include <mln/morpho/includes.hh>
-# include <mln/level/sort_psites.hh>
-
-# include <mln/core/image/image2d.hh>
-# include <mln/core/alias/neighb2d.hh>
-# include <mln/value/int_u8.hh>
-# include <mln/io/pgm/load.hh>
namespace mln
{
- template <typename I, typename N>
- struct max_tree_
+ namespace morpho
{
- typedef mln_site(I) point;
- typedef p_array<point> S;
- // in:
- const I& f;
- const N& nbh;
+ namespace tree
+ {
- // aux:
- S s;
- mln_ch_value(I, bool) deja_vu;
- mln_ch_value(I, point) parent;
- mln_ch_value(I, point) zpar;
+ // Remember:
+ // p is root iff parent(p) == p
+ // p is node iff either p is root or f(parent(p)) != f(p)
+
+ template <typename I, typename N, typename S>
+ mln_ch_value(I, mln_psite(I))
+ compute_parent(const Image<I>& f, const Neighborhood<N>& nbh,
+ const Site_Set<S>& s);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Tests.
+
+
+ namespace internal
+ {
- max_tree_(const I& f, const N& nbh)
- : f(f),
- nbh(nbh)
+ template <typename I, typename N, typename S>
+ void
+ compute_parent_tests(const Image<I>& f_,
+ const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_)
{
- run();
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
+
+ mln_precondition(f.has_data());
+ // mln_precondition(nbh.is_valid());
+ mln_precondition(s == f.domain());
+
+ (void) f;
+ (void) nbh;
+ (void) s;
}
- void run()
+
+ } // end of namespace mln::morpho::tree::internal
+
+
+
+ // Implementations.
+
+
+ namespace impl
+ {
+
+ namespace generic
{
- // init
+
+ // Z-Find-Root.
+
+ template <typename T>
+ inline
+ mln_psite(T) zfind_root(T& zpar, const mln_psite(T)& x)
{
+ mlc_equal(mln_value(T), mln_psite(T))::check();
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = zfind_root(zpar, zpar(x));
+ }
+
+ // Compute-Parent.
+
+ template <typename I, typename N, typename S>
+ inline
+ mln_ch_value(I, mln_psite(I))
+ compute_parent(const Image<I>& f_,
+ const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_)
+ {
+ trace::entering("morpho::tree::impl::generic::compute_parent");
+
+ typedef mln_psite(I) P;
+
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
+
+ // Tests.
+ internal::compute_parent_tests(f, nbh, s);
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, P) parent;
+ mln_ch_value(I, P) zpar;
+
initialize(deja_vu, f);
- mln::level::fill(deja_vu, false);
initialize(parent, f);
initialize(zpar, f);
- s = level::sort_psites_decreasing(f);
- }
- // first pass
- {
- mln_fwd_piter(S) p(s);
+ // Initialization.
+ level::fill(deja_vu, false);
+
+ // Body.
+ mln_bkd_piter(S) p(s);
mln_niter(N) n(nbh, p);
for_all(p)
{
- make_set(p);
+ // Make-Set.
+ parent(p) = p;
+ zpar(p) = p;
+
for_all(n)
- if (f.has(n) && deja_vu(n))
- do_union(n, p);
- deja_vu(p) = true;
+ if (f.domain().has(n) && deja_vu(n))
+ {
+ // Do-Union.
+ P r = zfind_root(zpar, n);
+ if (r != p)
+ {
+ parent(r) = p;
+ zpar(r) = p;
}
}
+ deja_vu(p) = true;
+ }
- // second pass: canonization
+ // Canonization.
{
- mln_bkd_piter(S) p(s);
+ mln_fwd_piter(S) p(s);
for_all(p)
{
- point q = parent(p);
+ P q = parent(p);
if (f(parent(q)) == f(q))
parent(p) = parent(q);
}
}
- } // end of run()
-
- void make_set(const point& p)
- {
- parent(p) = p;
- zpar(p) = p;
+ trace::exiting("morpho::tree::impl::generic::compute_parent");
+ return parent;
}
- bool is_root(const point& p) const
- {
- return parent(p) == p;
- }
+ } // end of namespace mln::morpho::tree::impl::generic
+
+ } // end of namespace mln::morpho::tree::impl
- bool is_node(const point& p) const
- {
- return is_root(p) || f(parent(p)) != f(p);
- }
- point find_root(const point& x)
- {
- if (zpar(x) == x)
- return x;
- else
- return zpar(x) = find_root(zpar(x));
- }
- void do_union(const point& n, const point& p)
+ // Dispatch.
+
+ namespace internal
{
- point r = find_root(n);
- if (r != p)
+
+ template <typename I, typename N, typename S>
+ inline
+ mln_ch_value(I, mln_psite(I))
+ compute_parent_dispatch(const Image<I>& f,
+ const Neighborhood<N>& nbh,
+ const Site_Set<S>& s)
{
- parent(r) = p;
- zpar(r) = p;
+ return impl::generic::compute_parent(f, nbh, s);
}
- }
-
- };
+ } // end of namespace mln::morpho::tree::internal
+ // Facade.
- template <typename I, typename N>
- unsigned max_tree(const I& f, const N& nbh)
+ template <typename I, typename N, typename S>
+ inline
+ mln_ch_value(I, mln_psite(I))
+ compute_parent(const Image<I>& f, const Neighborhood<N>& nbh,
+ const Site_Set<S>& s)
{
- max_tree_<I,N> run(f, nbh);
+ trace::entering("morpho::tree::compute_parent");
- mln_piter(I) p(f.domain());
- unsigned nnodes = 0;
- for_all(p)
- if (run.is_node(p))
- ++nnodes;
- return nnodes;
- }
+ internal::compute_parent_tests(f, nbh, s);
+
+ mln_ch_value(I, mln_psite(I)) output;
+ output = internal::compute_parent_dispatch(f, nbh, s);
-} // end of mln
+ trace::exiting("morpho::tree::compute_parent");
+ return output;
+ }
+# endif // ! MLN_INCLUDE_ONLY
+ } // end of namespace mln::morpho::tree
-int main(int argc, char* argv[])
-{
- if (argc != 2)
- {
- std::cerr << "usage: " << argv[0] << "
filename" << std::endl;
- return 1;
- }
+ } // end of namespace mln::morpho
- using namespace mln;
- using value::int_u8;
+} // end of namespace mln
- image2d<int_u8> f;
- io::pgm::load(f, argv[1]);
- std::cout << "n nodes = " << mln::max_tree(f, c8()) <<
std::endl;
-}
+#endif // ! MLN_MORPHO_TREE_COMPUTE_PARENT_HH
Index: mln/canvas/morpho/all.hh
--- mln/canvas/morpho/all.hh (revision 2937)
+++ mln/canvas/morpho/all.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 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
@@ -28,23 +29,24 @@
#ifndef MLN_CANVAS_MORPHO_ALL_HH
# define MLN_CANVAS_MORPHO_ALL_HH
-/*! \file mln/canvas/morpho/all.hh
- *
- * \brief File that includes morphological canvas-related routines.
- */
+/// \file mln/canvas/morpho/all.hh
+///
+/// File that includes morphological canvas-related routines.
namespace mln
{
-
namespace canvas
{
+
/// Namespace of morphological canvas.
namespace morpho {}
- }
}
+}
+
# include <mln/canvas/morpho/algebraic_union_find.hh>
+
#endif // ! MLN_CANVAS_MORPHO_ALL_HH