Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
May 2010
- 6 participants
- 142 discussions
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch dist-xz has been created
at f62ea1f61ad96620adacb43da6a8b3a05820c5d8 (commit)
- Log -----------------------------------------------------------------
f62ea1f bootstrap: Check for xz (>= 4.999.9).
f6e5d4d Distribute xz archives.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
1
0
07 May '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch automake-1.11 has been updated
discards 392429a4c3d8c534e48aed676b06376a0e11656f (commit)
discards b398c7400467eba1e6b388eaa246520013aef784 (commit)
discards a40246acf27813036746eb25f0be1a52d8fa07b5 (commit)
discards a0e11516e9a62c6c8bf3eda0559be9f80d571e53 (commit)
discards adcea166b0a12407b34bfeabee93586cb0c39001 (commit)
discards 67db7f5293429f6ed95248503d8a9b64df706abd (commit)
discards 12aca471e1e52ba01f57de8f4e905be59e970029 (commit)
discards b4e8d98a3aaff52ba0d53a3b3dc83b278078f0cf (commit)
discards 8705382504aff47f8791199ae31b17dc55192159 (commit)
discards 3fd31fafdf95fbcdc76e409eec6b8c3712031d29 (commit)
via 7aacb61a0046adfcd926193d2a78de91cdbbb9d0 (commit)
via 4def5f0d7d19e7dd01c7ed42b1dc6019689c56f5 (commit)
via 5c1e70424e2d99a22cad909500f167b6189466d2 (commit)
via d134e182361389ad6c3e00a6a4a8fd50fe30c03a (commit)
via 74142adbc2697eeb721f42e6104a311b0aa23fbb (commit)
via 3240a14f9500348960cfe86b465182bac885780e (commit)
via ea5d26525d6e6db053348d79c86b3e0699d882ed (commit)
via d916229ffca1d1611531146d96757c40265f3508 (commit)
This update added new revisions after undoing existing revisions. That is
to say, the old revision is not a strict subset of the new revision. This
situation occurs when you --force push a change and generate a repository
containing something like this:
* -- * -- B -- O -- O -- O (392429a4c3d8c534e48aed676b06376a0e11656f)
\
N -- N -- N (7aacb61a0046adfcd926193d2a78de91cdbbb9d0)
When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
7aacb61 Enable parallel tests.
4def5f0 Canonize Swilena's tests' output file names to support parallel tests.
5c1e704 Canonize Milena's tests' output file names to support parallel tests.
d134e18 Factor Makefiles' helpers.
74142ad Use AM_DEFAULT_SOURCE_EXT to simplify Scribo's Makefiles.
3240a14 tests/unit_test/unit-tests.mk: Regen.
ea5d265 Simplify build_unit_test.sh thanks to AM_DEFAULT_SOURCE_EXT.
d916229 Use AM_DEFAULT_SOURCE_EXT to simplify Milena's Makefiles.
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 10 ----------
bootstrap | 3 ---
configure.ac | 2 +-
3 files changed, 1 insertions(+), 14 deletions(-)
hooks/post-receive
--
Olena, a generic and efficient image processing platform
1
0
last-svn-commit-1-g3925ac9 Unified structure for simple/dual input min/max tree.
by edwin carlinet 04 May '10
by edwin carlinet 04 May '10
04 May '10
* mln/core/concept/tree.hh: New component concept.
* mln/core/image/attribute_image.hh: New attribute image.
* mln/core/site_set/p_nodes.hh: Nodes site set.
* mln/core/site_set/p_nodes_piter.hh: Nodes set iterators.
* mln/tag/tree.hh: Tags for min/max tree.
* mln/util/ctree/ctree.hh: New tree structure.
* mln/util/ctree/internal/tree_base.hh: Base type for tree structure.
* mln/util/ctree/node.hh,
* mln/util/ctree/tree_ids.hh: Node site type.
---
milena/ChangeLog | 14 +
milena/mln/core/concept/tree.hh | 148 +++++
milena/mln/core/image/attribute_image.hh | 477 ++++++++++++++++
milena/mln/core/site_set/p_nodes.hh | 484 ++++++++++++++++
milena/mln/core/site_set/p_nodes_piter.hh | 244 ++++++++
milena/mln/tag/tree.hh | 52 ++
milena/mln/util/ctree/ctree.hh | 806 +++++++++++++++++++++++++++
milena/mln/util/ctree/internal/tree_base.hh | 141 +++++
milena/mln/util/ctree/node.hh | 351 ++++++++++++
milena/mln/util/ctree/tree_ids.hh | 53 ++
10 files changed, 2770 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/core/concept/tree.hh
create mode 100644 milena/mln/core/image/attribute_image.hh
create mode 100644 milena/mln/core/site_set/p_nodes.hh
create mode 100644 milena/mln/core/site_set/p_nodes_piter.hh
create mode 100644 milena/mln/tag/tree.hh
create mode 100644 milena/mln/util/ctree/ctree.hh
create mode 100644 milena/mln/util/ctree/internal/tree_base.hh
create mode 100644 milena/mln/util/ctree/node.hh
create mode 100644 milena/mln/util/ctree/tree_ids.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index b3cd42e..0529b68 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,17 @@
+2010-04-09 edwin carlinet <carlinet(a)lrde.epita.fr>
+
+ Unified structure for simple/dual input min/max tree.
+
+ * mln/core/concept/tree.hh: New component concept.
+ * mln/core/image/attribute_image.hh: New attribute image.
+ * mln/core/site_set/p_nodes.hh: Nodes site set.
+ * mln/core/site_set/p_nodes_piter.hh: Nodes set iterators.
+ * mln/tag/tree.hh: Tags for min/max tree.
+ * mln/util/ctree/ctree.hh: New tree structure.
+ * mln/util/ctree/internal/tree_base.hh: Base type for tree structure.
+ * mln/util/ctree/node.hh,
+ * mln/util/ctree/tree_ids.hh: Node site type.
+
2009-11-18 Guillaume Lazzara <z(a)lrde.epita.fr>
* doc/white_paper/white_paper.tex: Fix an invalid URL.
diff --git a/milena/mln/core/concept/tree.hh b/milena/mln/core/concept/tree.hh
new file mode 100644
index 0000000..2378bd8
--- /dev/null
+++ b/milena/mln/core/concept/tree.hh
@@ -0,0 +1,148 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_CORE_CONCEPT_TREE_HH
+# define MLN_CORE_CONCEPT_TREE_HH
+
+# include <mln/core/concept/object.hh>
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename E> struct Tree;
+
+ // Tree category flag type.
+ template <>
+ struct Tree<void>
+ {
+ typedef Object<void> super;
+ };
+
+ template <typename E>
+ struct Tree : public Object<E>
+ {
+ typedef Tree<void> category;
+
+ /*
+ // Original image related
+ typedef site;
+ typedef psite;
+
+ typedef value;
+ typedef rvalue;
+ typedef lvalue;
+
+ // Node/Site related material.
+ typedef domain_t;
+ const domain_t& domain() const;
+
+ typedef nodes_t;
+ const nodes_t& nodes() const;
+
+ bool has(const node_t&) const;
+ bool has(const psite&) const;
+
+ // Value related material.
+ rvalue f() (const psite&) const;
+ lvalue f() (const psite&);
+ rvalue f[] (const node_t&) const;
+ lvalue f[] (const node_t&);
+
+ // Node relationship.
+ node_t node(const psite&) const;
+ void set_node(const psite&, const node_t&);
+ node_t parent(const node_id_t&) const;
+ void set_parent(const node_t&, const node_t&);
+
+ // Node test materials
+ bool is_a_leaf(const node_t&) const;
+ bool is_a_root(const node_t&) const;
+ */
+
+ protected:
+ Tree();
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename E>
+ inline
+ Tree<E>::Tree()
+ {
+ typedef mln_site(E) site;
+ typedef mln_psite(E) psite;
+
+ typedef mln_value(E) value;
+ typedef mln_rvalue(E) rvalue;
+ typedef mln_lvalue(E) lvalue;
+
+ typedef typename E::node_t node_t;
+
+ // Site/Node related material.
+ typedef mln_domain(E) domain_t;
+ typedef typename E::nodes_t nodes_t;
+
+ const domain_t& (E::*m1)() const = & E::domain;
+ m1 = 0;
+ nodes_t (E::*m2)() const = & E::nodes;
+ m2 = 0;
+ bool (E::*m3)(const node_t&) const = & E::has;
+ m3 = 0;
+ bool (E::*m4)(const psite&) const = & E::has;
+ m4 = 0;
+
+ // Value related material.
+ rvalue (E::*m5)(const psite&) const = & E::f;
+ m5 = 0;
+ lvalue (E::*m6)(const psite&) = & E::f;
+ m6 = 0;
+ rvalue (E::*m7)(const node_t&) const = & E::f;
+ m7 = 0;
+ lvalue (E::*m8)(const node_t&) = & E::f;
+ m8 = 0;
+
+ // Node relationship.
+ node_t (E::*m9)(const psite&) const = & E::node;
+ m9 = 0;
+ void (E::*m10)(const psite&, const node_t&) = & E::set_node;
+ m10 = 0;
+ node_t (E::*m11)(const node_t&) const = & E::parent;
+ m11 = 0;
+ void (E::*m12)(const node_t&, const node_t&) = & E::set_parent;
+ m12 = 0;
+
+ // Node tests
+ bool (E::*m13)(const node_t&) const = & E::is_a_leaf;
+ m13 = 0;
+ bool (E::*m14)(const node_t&) const = & E::is_a_root;
+ m14 = 0;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // !MLN_CORE_CONCEPT_TREE_HH
diff --git a/milena/mln/core/image/attribute_image.hh b/milena/mln/core/image/attribute_image.hh
new file mode 100644
index 0000000..1331a6f
--- /dev/null
+++ b/milena/mln/core/image/attribute_image.hh
@@ -0,0 +1,477 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_CORE_IMAGE_ATTRIBUTE_IMAGE_HH
+# define MLN_CORE_IMAGE_ATTRIBUTE_IMAGE_HH
+
+# include <mln/core/internal/image_primary.hh>
+# include <mln/core/concept/tree.hh>
+# include <mln/tag/tree.hh>
+# include <mln/metal/converts_to.hh>
+# include <mln/metal/unref.hh>
+
+namespace mln
+{
+ // Forward declaration.
+ template <typename T, typename V> class attribute_image;
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::attribute_image
+ template <typename T, typename V>
+ struct data< mln::attribute_image<T, V> >
+ {
+ data();
+ data(const T& tree);
+ ~data();
+
+ std::vector<V> values_;
+ T tree_; // An attribute image can hold the tracked-data of the tree.
+ typename T::nodes_t domain_;
+ };
+
+ } // end of namespace mln::internal
+
+ namespace trait
+ {
+
+ template <typename T, typename V>
+ struct image_< attribute_image<T, V> > : default_image_< V, attribute_image<T, V> >
+ {
+ // misc
+ typedef trait::image::category::primary category;
+ typedef trait::image::speed::fastest speed;
+ typedef trait::image::size::regular size;
+
+ // value
+ typedef trait::image::vw_io::none vw_io;
+ typedef trait::image::vw_set::none vw_set;
+ // Fixme: value_access is direct, but if so, the duplicate function doesn't work anymore.
+ typedef trait::image::value_access::computed value_access;
+ typedef trait::image::value_alignment::irrelevant value_alignment;
+ typedef trait::image::value_browsing::site_wise_only value_browsing;
+ typedef trait::image::value_storage::one_block value_storage;
+ typedef trait::image::value_io::read_write value_io;
+
+ // site / domain
+ typedef trait::image::pw_io::read_write pw_io;
+ typedef trait::image::localization::none localization;
+ typedef trait::image::dimension::none dimension;
+
+ // extended domain
+ typedef trait::image::ext_domain::none ext_domain;
+ typedef trait::image::ext_value::irrelevant ext_value;
+ typedef trait::image::ext_io::irrelevant ext_io;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace convert
+ {
+
+ namespace over_load
+ {
+ template <typename T, typename V, typename I>
+ void
+ from_to_(const mln::attribute_image<T, V>& from, Image<I>& to_)
+ {
+ typedef mln::attribute_image<T, V> A;
+ I& to = exact(to_);
+
+ mlc_converts_to(V, mln_value(I))::check();
+ mlc_converts_to(typename T::domain_t, mln_domain(I))::check();
+
+ mln_precondition(from.is_valid());
+ to.init_(from.tree().domain());
+
+ mln_fwd_piter(I) p(to.domain());
+ for_all(p)
+ convert::from_to(from(from.tree().node(p)), to(p));
+ }
+
+ } // enf of namespace mln::convert::over_load
+
+ } // end of namespace mln::convert
+
+
+ /// Basic attribute image class.
+ ///
+ /// The parameter \c V is the type of pixel values (usually the
+ /// result type of the attribute). This image class stores data in
+ /// memory.
+ ///
+ /// \ingroup modimageconcrete
+ //
+ template <typename T, typename V>
+ class attribute_image : public internal::image_primary< V, typename T::nodes_t, attribute_image<T, V> >
+ {
+ typedef internal::image_primary< V, typename T::nodes_t, attribute_image<T, V> > super_;
+ typedef attribute_image<T, V> self_;
+
+ public:
+
+ /// Value associated type.
+ typedef V value;
+ /// Return type of read-only access.
+ typedef const V& rvalue;
+ /// Return type of read-write access.
+ typedef V& lvalue;
+
+ /// Associated tree type.
+ typedef T tree_t;
+
+ /// Site (node) assocatied type.
+ typedef typename T::node_t node_t;
+ typedef node_t site;
+ typedef node_t psite;
+
+ /// Site set (node set) associated type.
+ typedef typename T::nodes_t nodes_t;
+
+ /// Skeleton.
+ typedef attribute_image< tag::tree_<T>, tag::value_<V> > skeleton;
+
+ /// Constructors
+ /// \{
+ /// Constructor without argument.
+ attribute_image();
+ /// Allocate an attribute image respecting the size of the tree.
+ attribute_image(const Tree<T>& tree);
+ /// \}
+
+ /// Initialize an empty image.
+ void init_(const Tree<T>& tree);
+
+ /// Test if the node \p n is valid.
+ bool has(const node_t& n) const;
+
+ /// Give the node site set.
+ const nodes_t& domain() const;
+
+ /// Read-only access to the image value at node \p n.
+ rvalue operator()(const node_t& n) const;
+
+ /// Read-write access to the image value at node \p n.
+ lvalue operator()(const node_t& n);
+
+ // Specific methods:
+ // ----------------
+
+ /// Read access to the value at point \p p.
+ /// Note: can be ambigous if the node content is a node set.
+ rvalue operator()(const mln_psite(T)& p) const;
+
+ /// Return the tree.
+ const T& tree() const;
+
+ /// Change the target tree.
+ void change_tree(const Tree<T>& tree);
+
+ // As a fastest image.
+ // ------------------
+
+ /// Give the number of elements.
+ unsigned nelements() const;
+
+ /// Read-only access to the image value lacated at index \p i.
+ rvalue element(unsigned i) const;
+
+ /// Read-write access to the image value lacated at index \p i.
+ lvalue element(unsigned i);
+
+ /// Return the border. (Required by image fastest / return always 0).
+ unsigned border() const;
+
+ /// Give the delta_index corresponding to the delta point.
+ int delta_index(const mln_delta(node_t)& dp) const;
+
+ /// Give the point corresponding to the index \p i;
+ node_t point_at_index(unsigned i) const;
+
+ /// Give the index corresponding to the point \p p;
+ unsigned index_of_point(const node_t& p) const;
+
+ /// Give a hook to the value buffer.
+ const V* buffer() const;
+
+ /// Give a hook to the value buffer.
+ V* buffer();
+
+ /// Give a hook to the std::vector.
+ std::vector<V>& vector() {
+ mln_precondition(this->is_valid());
+ return this->data_->values_;
+ }
+ };
+
+ /// Avoid instanciation of attribute image of bool because of the very
+ /// bad idea of the STL to optimize vector<bool> with non adressable
+ /// type.
+ /// Use vector<char> instead of vector<bool>
+ template <typename T>
+ class attribute_image<T, bool>;
+
+
+ // Forward declaration.
+ template <typename T, typename V, typename V2>
+ void init_(tag::image_t, mln::attribute_image<T, V>& target, const mln::attribute_image<T, V2>& model);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // init_
+
+ template <typename T, typename V, typename V2>
+ inline
+ void
+ init_(tag::image_t, mln::attribute_image<T, V>& target, const mln::attribute_image<T, V2>& model)
+ {
+ target.init_(model.tree());
+ }
+
+ // internal::data
+
+ namespace internal
+ {
+
+ template <typename T, typename V>
+ inline
+ data< attribute_image<T, V> >::data()
+ {
+ }
+
+ template <typename T, typename V>
+ inline
+ data< attribute_image<T, V> >::data(const T& tree)
+ : values_ (tree.n_nodes()),
+ tree_ (tree)
+ {
+ typedef typename T::nodes_t S;
+ typedef typename T::node_t node_t;
+ domain_ = S(tree_, node_t(tree_, 0), tree_.n_nodes());
+ }
+
+ template <typename T, typename V>
+ inline
+ data< attribute_image<T, V> >::~data()
+ {
+ }
+
+ } // end of namespace mln::internal
+
+
+ template <typename T, typename V>
+ inline
+ attribute_image<T, V>::attribute_image()
+ {
+ }
+
+
+ template <typename T, typename V>
+ inline
+ attribute_image<T, V>::attribute_image(const Tree<T>& tree_)
+ {
+ const T& tree = exact(tree_);
+ mln_precondition(tree.is_valid());
+ this->data_ = new internal::data< self_ >(tree);
+ }
+
+ template <typename T, typename V>
+ inline
+ unsigned
+ attribute_image<T, V>::border() const
+ {
+ return 0;
+ }
+
+ template <typename T, typename V>
+ inline
+ void
+ attribute_image<T, V>::init_(const Tree<T>& tree_)
+ {
+ const T& tree = exact(tree_);
+
+ mln_precondition(!this->is_valid());
+ mln_precondition(tree.is_valid());
+ this->data_ = new internal::data< self_ >(tree);
+ }
+
+ template <typename T, typename V>
+ inline
+ bool
+ attribute_image<T, V>::has(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ return this->domain().has(n);
+ }
+
+ template <typename T, typename V>
+ inline
+ const typename T::nodes_t&
+ attribute_image<T, V>::domain() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->domain_;
+ }
+
+ template <typename T, typename V>
+ inline
+ const V&
+ attribute_image<T, V>::operator()(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return this->data_->values_[n.index()];
+ }
+
+ template <typename T, typename V>
+ inline
+ V&
+ attribute_image<T, V>::operator()(const node_t& n)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return this->data_->values_[n.index()];
+ }
+
+ // Specific methods:
+ // ----------------
+
+
+ template <typename T, typename V>
+ inline
+ const V&
+ attribute_image<T, V>::operator()(const mln_psite(T)& p) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->data_->tree_.has(p));
+ return this->data_->values_[this->data_->tree_.node_at_(p)];
+ }
+
+ template <typename T, typename V>
+ inline
+ const T&
+ attribute_image<T, V>::tree() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->tree_;
+ }
+
+ template <typename T, typename V>
+ inline
+ void
+ attribute_image<T, V>::change_tree(const Tree<T>& tree_)
+ {
+ const T& tree = exact(tree_);
+ mln_precondition(tree.is_valid());
+ this->data_->tree_ = tree;
+ }
+
+ template <typename T, typename V>
+ inline
+ unsigned
+ attribute_image<T, V>::nelements() const
+ {
+ mln_precondition(this->is_valid());
+ return this->domain().nsites();
+ }
+
+ template <typename T, typename V>
+ inline
+ const V&
+ attribute_image<T, V>::element(unsigned i) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(i < this->nelements());
+ return this->data_->values_[i];
+ }
+
+ template <typename T, typename V>
+ inline
+ V&
+ attribute_image<T, V>::element(unsigned i)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(i < this->nelements());
+ return this->data_->values_[i];
+ }
+
+ template <typename T, typename V>
+ inline
+ int
+ attribute_image<T, V>::delta_index(const mln_delta(node_t)& dp) const
+ {
+ mln_precondition(this->is_valid());
+ return dp;
+ }
+
+ template <typename T, typename V>
+ inline
+ typename T::node_t
+ attribute_image<T, V>::point_at_index(unsigned i) const
+ {
+ mln_precondition(this->is_valid());
+ node_t tmp(this->data_->tree_, i);
+ return tmp;
+ }
+
+ template <typename T, typename V>
+ inline
+ const V*
+ attribute_image<T, V>::buffer() const
+ {
+ mln_precondition(this->is_valid());
+ return &(this->data_->values_[0]);
+ }
+
+ template <typename T, typename V>
+ inline
+ V*
+ attribute_image<T, V>::buffer()
+ {
+ mln_precondition(this->is_valid());
+ return &(this->data_->values_[0]);
+ }
+
+ template <typename T, typename V>
+ inline
+ unsigned
+ attribute_image<T, V>::index_of_point(const node_t& p) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+
+ unsigned i = p.index();
+ //mln_postcondition(p == this->point_at_index(i));
+ return i;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // !MLN_CORE_IMAGE_ATTRIBUTE_IMAGE_HH
diff --git a/milena/mln/core/site_set/p_nodes.hh b/milena/mln/core/site_set/p_nodes.hh
new file mode 100644
index 0000000..7025ee9
--- /dev/null
+++ b/milena/mln/core/site_set/p_nodes.hh
@@ -0,0 +1,484 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_CORE_SITE_SET_P_NODES_HH
+# define MLN_CORE_SITE_SET_P_NODES_HH
+
+/// \file
+///
+/// Definition of a run of nodes.
+///
+/// \todo Use a lazy approach (in subj) like in p_array psite.
+///
+
+# include <mln/util/ctree/node.hh>
+# include <mln/core/internal/site_set_base.hh>
+# include <mln/core/internal/pseudo_site_base.hh>
+
+namespace mln
+{
+
+ // Forward declarations.
+ template <typename T> class p_nodes;
+ template <typename T> class p_nodes_psite;
+ template <typename T> class p_nodes_fwd_piter_;
+ template <typename T> class p_nodes_bkd_piter_;
+
+ namespace trait
+ {
+
+ template <typename T>
+ struct site_set_< p_nodes<T> >
+ {
+ typedef trait::site_set::nsites::known nsites;
+ typedef trait::site_set::bbox::unknown bbox;
+ typedef trait::site_set::contents::fixed contents;
+ typedef trait::site_set::arity::unique arity;
+ };
+
+ template <typename T>
+ struct set_precise_unary_< op::ord, p_nodes<T> >
+ {
+ typedef set_precise_unary_< op::ord, p_nodes<T> > ret; // Itself.
+ bool strict(const p_nodes<T>& lhs, const p_nodes<T>& rhs) const;
+ };
+
+ } // end of namespace trait
+
+
+
+ /// \brief Site set class in run.
+ ///
+ /// \ingroup modsitesetbasic
+ template <typename T>
+ class p_nodes : public internal::site_set_base_< util::ctree::node<T>, p_nodes<T> >
+ {
+ public:
+
+ /// Element associated type.
+ typedef util::ctree::node<T> element;
+
+ /// Psite associated type.
+ typedef p_nodes_psite<T> psite;
+
+ /// Forward Site_Iterator associated type.
+ typedef p_nodes_fwd_piter_<T> fwd_piter;
+
+ /// Backward Site_Iterator associated type.
+ typedef p_nodes_bkd_piter_<T> bkd_piter;
+
+ /// Site_Iterator associated type.
+ typedef fwd_piter piter;
+
+
+ /// Constructor without argument.
+ p_nodes();
+
+ /// Constructors.
+ /// \{
+ p_nodes(const Tree<T>& tree);
+ /// Create the node set [\p start, \p start + \p len [
+ p_nodes(const Tree<T>& tree, const element& start, unsigned len);
+ /// Create the node set [\p start, \p end [
+ p_nodes(const Tree<T>& tree, const element& start, const element& end);
+ /// \}
+
+ /// Init.
+ /// \{
+ void init(const Tree<T>& tree, const element& start, unsigned len);
+ void init(const Tree<T>& tree, const element& start, const element& end);
+ /// \}
+
+ /// Test if \p p belongs to this site set.
+ bool has(const psite& p) const;
+
+ /// Test if \p p belongs to this site set.
+ bool has(const element& p) const;
+
+ /// Test if index \p i belongs to this site set.
+ bool has_index(unsigned i) const;
+
+ /// Give the number of sites.
+ unsigned nsites() const;
+
+ /// Return the \p i-th site.
+ element operator[](int i) const;
+
+ /// Return the starting site.
+ const element& start() const;
+
+ /// Return (compute) the ending site.
+ element end() const;
+
+ /// Test if this run is valid, i.e., with length >= 0.
+ bool is_valid() const;
+
+ /// Return the size of this site set in memory.
+ std::size_t memory_size() const;
+
+ /// Return the attached tree.
+ const T& tree() const;
+
+ protected:
+ const T* tree_;
+
+ /// The first site of the run.
+ util::ctree::node<T> start_;
+
+ /// The length of the run.
+ unsigned len_;
+ };
+
+ template <typename T>
+ class p_nodes_psite : public internal::pseudo_site_base_< const util::ctree::node<T>&, p_nodes_psite<T> >
+ {
+ typedef p_nodes_psite<T> self;
+ typedef internal::pseudo_site_base_<const util::ctree::node<T>&, self> super;
+
+ public:
+
+ // This associated type is important to know that this particular
+ // pseudo site knows the site set it refers to.
+ typedef p_nodes<T> target;
+
+ // As a Proxy:
+ const util::ctree::node<T>& subj_();
+
+ p_nodes_psite();
+ p_nodes_psite(const p_nodes<T>& run, int i);
+
+ /// Index materials
+ /// \{
+ int index() const;
+ void change_index(int i);
+ void inc_index();
+ void dec_index();
+ /// \}
+
+ /// Run materials
+ /// \{
+ const p_nodes<T>* target_() const;
+ const p_nodes<T>& run() const;
+ void change_target(const p_nodes<T>& new_target);
+ /// \}
+
+ bool is_valid() const;
+
+ private:
+ const p_nodes<T>* run_;
+ int i_;
+ mutable util::ctree::node<T> p_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T>
+ inline
+ p_nodes<T>::p_nodes() :
+ tree_ (0), len_ (0)
+ {
+ }
+
+ template <typename T>
+ inline
+ p_nodes<T>::p_nodes(const Tree<T>& tree)
+ : tree_ (&(exact(tree))), len_ (0)
+ {
+ mln_precondition(tree_.is_valid());
+ }
+
+ template <typename T>
+ inline
+ p_nodes<T>::p_nodes(const Tree<T>& tree,
+ const util::ctree::node<T>& start,
+ unsigned len)
+ : tree_ (&(exact(tree))), start_(start), len_ (len)
+ {
+ mln_precondition(tree_->is_valid() && start.is_valid());
+ mln_postcondition(is_valid());
+ }
+
+ template <typename T>
+ inline
+ p_nodes<T>::p_nodes(const Tree<T>& tree,
+ const util::ctree::node<T>& start,
+ const util::ctree::node<T>& end)
+ : tree_ (&(exact(tree))), start_(start)
+ {
+ mln_precondition(tree_.is_valid() && start.is_valid() && end.is_valid());
+ mln_precondition(start.index() <= end.index());
+ len_ = end.index() - start.index();
+ mln_postcondition(is_valid());
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes<T>::init(const Tree<T>& tree, const util::ctree::node<T>& start, unsigned len)
+ {
+ tree_ = &(exact(tree));
+ mln_precondition(start.is_valid());
+ mln_precondition(tree_->is_valid());
+ start_ = start;
+ len_ = len;
+ mln_postcondition(is_valid());
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes<T>::init(const Tree<T>& tree,
+ const util::ctree::node<T>& start,
+ const util::ctree::node<T>& end)
+ {
+ tree_ = &(exact(tree));
+ mln_precondition(tree_->is_valid());
+ mln_precondition(start.is_valid() && end.is_valid());
+ mln_precondition(start.index() <= end.index());
+ start_ = start;
+ len_ = end.index() - start.index();
+ mln_postcondition(is_valid());
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes<T>::is_valid() const
+ {
+ return tree_->is_valid() && start_.is_valid();
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes<T>::has(const psite& p) const
+ {
+ mln_precondition(p.target_() == this);
+ return p.index() >= 0 && p.index() < (int)len_;
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes<T>::has(const util::ctree::node<T>& node) const
+ {
+ mln_precondition(is_valid());
+ return (this->start_.index() <= node.index()) && (node.index() < this->end().index());
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes<T>::has_index(unsigned i) const
+ {
+ mln_precondition(is_valid());
+ return i < len_;
+ }
+
+ template <typename T>
+ inline
+ unsigned
+ p_nodes<T>::nsites() const
+ {
+ mln_precondition(is_valid());
+ return len_;
+ }
+
+ template <typename T>
+ inline
+ const T&
+ p_nodes<T>::tree() const
+ {
+ mln_precondition(is_valid());
+ return *tree_;
+ }
+
+ template <typename T>
+ inline
+ util::ctree::node<T>
+ p_nodes<T>::operator[](int i) const
+ {
+ mln_precondition(is_valid());
+ mln_precondition(i >= 0);
+ mln_precondition(i < len_);
+ util::ctree::node<T> p = start_;
+ p.change_index(start_.index() + i);
+ return p;
+ }
+
+ template <typename T>
+ inline
+ const util::ctree::node<T>&
+ p_nodes<T>::start() const
+ {
+ return start_;
+ }
+
+ template <typename T>
+ inline
+ util::ctree::node<T>
+ p_nodes<T>::end() const
+ {
+ util::ctree::node<T> n = start_;
+ n.change_index(start_.index() + len_);
+ return n;
+ }
+
+ template <typename T>
+ inline
+ std::size_t
+ p_nodes<T>::memory_size() const
+ {
+ return sizeof(*this);
+ }
+
+ template <typename T>
+ std::ostream& operator<<(std::ostream& ostr, const p_nodes<T>& r)
+ {
+ ostr << '(' << r.start() << ", " << r.nsites() << ')';
+ return ostr;
+ }
+
+ // p_nodes_psite<P>
+
+ template <typename T>
+ inline
+ p_nodes_psite<T>::p_nodes_psite()
+ : run_(0),
+ i_(0)
+ {
+ }
+
+ template <typename T>
+ inline
+ p_nodes_psite<T>::p_nodes_psite(const p_nodes<T>& run, int i)
+ : run_(&run),
+ i_(i),
+ p_(run.start())
+ {
+ p_.change_index(p_.index() + i_);
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes_psite<T>::is_valid() const
+ {
+ return run_ != 0 && run_->has_index(i_);
+ }
+
+ template <typename T>
+ inline
+ int
+ p_nodes_psite<T>::index() const
+ {
+ return i_;
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_psite<T>::change_index(int i)
+ {
+ p_.change_index(run_->start().index() + i);
+ i_ = i;
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_psite<T>::dec_index()
+ {
+ --i_;
+ p_.dec_index();
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_psite<T>::inc_index()
+ {
+ ++i_;
+ p_.inc_index();
+ }
+
+ template <typename T>
+ inline
+ const p_nodes<T>*
+ p_nodes_psite<T>::target_() const
+ {
+ return run_;
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_psite<T>::change_target(const p_nodes<T>& new_target)
+ {
+ run_ = &new_target;
+ i_ = 0;
+ p_ = run_->start();
+ }
+
+ template <typename T>
+ inline
+ const util::ctree::node<T>&
+ p_nodes_psite<T>::subj_()
+ {
+ return p_;
+ }
+
+ template <typename T>
+ inline
+ const p_nodes<T>&
+ p_nodes_psite<T>::run() const
+ {
+ mln_precondition(run_ != 0);
+ return *run_;
+ }
+
+ namespace trait
+ {
+
+ template <typename T>
+ inline
+ bool
+ set_precise_unary_< op::ord, p_nodes<T> >::strict(const p_nodes<T>& lhs, const p_nodes<T>& rhs) const
+ {
+ return util::ord_strict(lhs.start().index(), rhs.start().index());
+ }
+
+ } // end of namespace trait
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+# include <mln/core/site_set/p_nodes_piter.hh>
+
+
+#endif // ! MLN_CORE_SITE_SET_P_NODES_HH
diff --git a/milena/mln/core/site_set/p_nodes_piter.hh b/milena/mln/core/site_set/p_nodes_piter.hh
new file mode 100644
index 0000000..d8fbf12
--- /dev/null
+++ b/milena/mln/core/site_set/p_nodes_piter.hh
@@ -0,0 +1,244 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_CORE_SITE_SET_P_NODES_PITER_HH
+# define MLN_CORE_SITE_SET_P_NODES_PITER_HH
+
+/*! \file
+ *
+ * \brief Definition of point iterators on mln::p_nodes.
+ */
+
+# include <mln/core/site_set/p_nodes.hh>
+# include <mln/core/internal/site_set_iterator_base.hh>
+
+
+namespace mln
+{
+
+ /*! \brief Forward iterator on points of a p_nodes<T>.
+ *
+ */
+ template <typename T>
+ class p_nodes_fwd_piter_
+ :
+ public internal::site_set_iterator_base< p_nodes<T>,
+ p_nodes_fwd_piter_<T> >
+ {
+ typedef p_nodes_fwd_piter_<T> self_;
+ typedef internal::site_set_iterator_base< p_nodes<T>, self_ > super_;
+ public:
+
+ /// Constructor without arguments.
+ p_nodes_fwd_piter_();
+
+ /// Coordinate associated type.
+ p_nodes_fwd_piter_(const p_nodes<T>& r);
+
+ /// Test if the iterator is valid.
+ bool is_valid_() const;
+
+ /// Invalidate the iterator.
+ void invalidate_();
+
+ /// Start an iteration.
+ void start_();
+
+ /// Go to the next point.
+ void next_();
+
+ /// Go to the brother.
+ void go_to_brother();
+
+ /// Go to
+ void go_to(const typename T::node_t& node);
+
+ protected:
+ using super_::p_;
+ using super_::s_;
+ };
+
+
+
+ /*! \brief Backward iterator on points of a p_nodes<T>.
+ *
+ */
+ template <typename T>
+ class p_nodes_bkd_piter_
+ :
+ public internal::site_set_iterator_base< p_nodes<T>,
+ p_nodes_bkd_piter_<T> >
+ {
+ typedef p_nodes_bkd_piter_<T> self_;
+ typedef internal::site_set_iterator_base< p_nodes<T>, self_ > super_;
+ public:
+
+ /// Constructor without arguments.
+ p_nodes_bkd_piter_();
+
+ /// Coordinate associated type.
+ p_nodes_bkd_piter_(const p_nodes<T>& r);
+
+ /// Test if the iterator is valid.
+ bool is_valid_() const;
+
+ /// Invalidate the iterator.
+ void invalidate_();
+
+ /// Start an iteration.
+ void start_();
+
+ /// Go to the next point.
+ void next_();
+
+ protected:
+ using super_::p_;
+ using super_::s_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // p_nodes_fwd_piter_<T>
+
+ template <typename T>
+ inline
+ p_nodes_fwd_piter_<T>::p_nodes_fwd_piter_()
+ {
+ }
+
+ template <typename T>
+ inline
+ p_nodes_fwd_piter_<T>::p_nodes_fwd_piter_(const p_nodes<T>& r)
+ {
+ this->change_target(r);
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes_fwd_piter_<T>::is_valid_() const
+ {
+ mln_invariant(p_.index() >= 0);
+ return p_.index() < int(s_->nsites());
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_fwd_piter_<T>::invalidate_()
+ {
+ p_.change_index(s_->nsites());
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_fwd_piter_<T>::start_()
+ {
+ p_.change_index(0);
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_fwd_piter_<T>::next_()
+ {
+ p_.inc_index();
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_fwd_piter_<T>::go_to_brother()
+ {
+ unsigned l = s_->tree().length_(p_.subj_());
+ p_.change_index(p_.index() + l);
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_fwd_piter_<T>::go_to(const typename T::node_t& node)
+ {
+ p_.change_index(node.index());
+ }
+
+ // p_nodes_bkd_piter_<T>
+
+ template <typename T>
+ inline
+ p_nodes_bkd_piter_<T>::p_nodes_bkd_piter_()
+ {
+ }
+
+ template <typename T>
+ inline
+ p_nodes_bkd_piter_<T>::p_nodes_bkd_piter_(const p_nodes<T>& r)
+ {
+ this->change_target(r);
+ }
+
+ template <typename T>
+ inline
+ bool
+ p_nodes_bkd_piter_<T>::is_valid_() const
+ {
+ mln_invariant(p_.index() < int(s_->nsites()));
+ return p_.index() >= 0;
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_bkd_piter_<T>::invalidate_()
+ {
+ p_.change_index(-1);
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_bkd_piter_<T>::start_()
+ {
+ p_.change_index(s_->nsites() - 1);
+ }
+
+ template <typename T>
+ inline
+ void
+ p_nodes_bkd_piter_<T>::next_()
+ {
+ p_.dec_index();
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_SITE_SET_P_NODES_PITER_HH
diff --git a/milena/mln/tag/tree.hh b/milena/mln/tag/tree.hh
new file mode 100644
index 0000000..275c250
--- /dev/null
+++ b/milena/mln/tag/tree.hh
@@ -0,0 +1,52 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_TAG_TREE_HH
+# define MLN_TAG_TREE_HH
+
+namespace mln
+{
+
+ namespace tag
+ {
+
+ namespace tree
+ {
+
+ template <typename T>
+ struct tree_t : Object<T> { protected: tree_t(){} };
+ struct max_t : tree_t<max_t> {};
+ struct min_t : tree_t<min_t> {};
+
+ static max_t max;
+ static min_t min;
+
+ } // end of namespace mln::tag::tree
+
+ } // end of namespace mln::tag
+
+} // end of namespace mln
+
+#endif // !MLN_TAG_TREE_HH
diff --git a/milena/mln/util/ctree/ctree.hh b/milena/mln/util/ctree/ctree.hh
new file mode 100644
index 0000000..e1c7148
--- /dev/null
+++ b/milena/mln/util/ctree/ctree.hh
@@ -0,0 +1,806 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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.
+
+
+// \todo definition of site, psite is ambigous, replace with content_t
+// or other.
+// \todo node operator ?
+//
+// \todo handle forest in case of non contiguous domain pictures.
+
+
+
+#ifndef MLN_UTIL_CTREE_CTREE_HH
+# define MLN_UTIL_CTREE_CTREE_HH
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/site_set.hh>
+# include <mln/util/ctree/internal/tree_base.hh>
+# include <mln/util/array.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <algorithm>
+
+# define mln_node(T) typename T::node_t
+
+namespace mln
+{
+
+ /// Forward declaration.
+ namespace util { namespace ctree { template <typename I> class ctree; } }
+
+ namespace morpho
+ {
+
+ namespace tree
+ {
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ union_find_fast(const tag::tree::tree_t<T>& tree_tag,
+ const Image<I>& f,
+ const Neighborhood<N>& nbh);
+
+ } // end of namespace morpho::tree::impl::generic
+
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ hqueue_fast(const tag::tree::tree_t<T>&,
+ const Image<I>& f,
+ const Neighborhood<N>& nbh);
+
+ } // end of namespace morpho::tree::impl
+
+ } // end of namespace morpho::tree
+
+ } // end of namespace morpho
+
+
+ namespace internal
+ {
+ /// Data structure for component tree.
+ template <>
+ template <typename I>
+ struct data< util::ctree::ctree<I> >
+ {
+ typedef util::ctree::ctree<I> T;
+ typedef typename T::node_t::index_t index_t;
+
+ data(const I&);
+ ~data();
+
+ mln_ch_value(I, index_t) map_;
+ std::vector<index_t> parent_;
+ std::vector<unsigned> length_;
+ std::vector<mln_value(I)> values_;
+
+ const mln_domain(I)& domain_;
+ int nnodes;
+ };
+
+ } // end of namespace mln::internal
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+
+ template <typename I>
+ struct ctree : public internal::tree_base< I, ctree<I> >
+ {
+ /// The super class.
+ typedef internal::tree_base<I, ctree<I> > super;
+
+ /// Self class
+ typedef ctree<I> self;
+
+ /// Site related type definitions.
+ /// \{
+ /// The type of site.
+ typedef mln_site(I) site;
+ /// The type of pseudo-site.
+ typedef mln_psite(I) psite;
+ /// The type of domain.
+ typedef mln_domain(I) domain_t;
+ /// \}
+
+ /// Node related type definions.
+ /// \{
+ /// The type of node.
+ typedef util::ctree::node<self> node_t;
+ /// The type of node set.
+ typedef p_nodes<self> nodes_t;
+ /// \}
+
+ /// Node/Site value related type definitions.
+ /// \{
+ /// The type of node value
+ typedef mln_value(I) value;
+ /// The type of node rvalue.
+ typedef mln_rvalue(I) rvalue;
+ /// The type of node lvalue.
+ typedef mln_lvalue(I) lvalue;
+ /// \}
+
+ typedef mln_ch_value(I, typename node_t::index_t) map_t;
+
+ /// Constructors
+ /// \{
+ ctree();
+ /// \}
+
+ /// Reserve space for tree.
+ void reserve(const Image<I>& ima, unsigned nnodes);
+
+
+ /// Constructor from union-find results.
+ /// \param[in] f The input image.
+ /// \param[in] parent The (not necessary canonized) parent image.
+ /// \param[in] area The number of nodes in each sub-tree.
+ /// \param[in] s The sorted site set.
+ /// \param[in] nb_nodes The total number of nodes.
+ template <typename S>
+ ctree(const Image<I>& f_,
+ const S& s,
+ mln_ch_value(I, unsigned)& parent,
+ mln_ch_value(I, unsigned)& area,
+ unsigned nb_nodes);
+
+ // ctree(const Image<I>& f,
+ // const Site_Set<S>& s,
+ // mln_ch_value(I, psite)& parent,
+ // mln_ch_value(I, unsigned)& area,
+ // unsigned nb_nodes);
+
+ /// \}
+
+ ctree(const Image<I>& f,
+ const mln_ch_value(I, unsigned)& map,
+ const std::vector<unsigned>& nodes,
+ const std::vector<unsigned>& parent,
+ const std::vector<unsigned>& area);
+
+ /// Misc.
+ /// \{
+ const domain_t& domain() const;
+ const map_t& map() const;
+ nodes_t nodes() const;
+ bool has(const psite&) const;
+ bool has(const node_t&) const;
+
+ int n_nodes() const;
+ /// \}
+
+ /// Value access material.
+ /// \{
+ rvalue f(const psite&) const;
+ lvalue f(const psite&);
+ rvalue f(const node_t&) const;
+ lvalue f(const node_t&);
+ /// \}
+
+ /// Node relationship material.
+ /// \{
+ node_t node(const psite&) const;
+ void set_node(const psite&, const node_t&);
+ node_t parent(const node_t&) const;
+ void set_parent(const node_t& n, const node_t& parent);
+
+ /// Return the node set of the sub-tree of \p n.
+ /// \post Non empty set: n belongs to desc(n).
+ nodes_t desc(const node_t& n) const;
+
+ /// Return the node set of ancestors of \p n.
+ nodes_t anc(const node_t& n) const;
+
+ /// Return the number of descendants of \p n.
+ /// Equivalent to desc(n).nsites() - 1.
+ unsigned length_(const node_t& n) const;
+ /// \}
+
+ /// Node tests material.
+ /// \{
+ bool is_a_leaf(const node_t&) const;
+ bool is_a_root(const node_t&) const;
+ /// \}
+
+ /// Fast access material.
+ /// \{
+
+ /// The type of index.
+ typedef typename node_t::index_t index_t;
+
+ bool has_index(index_t i) const;
+
+ /// Return the number of descendants of the node at index \p i.
+ /// Equivalent to desc(tree.node_at(i)).nsites().
+ unsigned length_at_(index_t i) const;
+ unsigned& length_at_(index_t i);
+ rvalue f_at_(index_t i) const;
+ lvalue f_at_(index_t i);
+ index_t parent_at_(index_t i) const;
+ index_t& parent_at_(index_t i);
+ index_t node_at_(const psite& p) const;
+ index_t& node_at_(const psite& p);
+ /// \}
+
+ /// To attribute image
+ attribute_image<ctree<I>, value> to_image() const;
+ void to_image(attribute_image<ctree<I>, value>& a) const;
+
+
+ /// Friend functions.
+ /// \{
+ template <typename T, typename J, typename N>
+ friend util::ctree::ctree<J>
+ morpho::tree::impl::generic::union_find_fast(const tag::tree::tree_t<T>&, const Image<J>&, const Neighborhood<N>&);
+
+ template <typename T, typename J, typename N>
+ friend util::ctree::ctree<J>
+ morpho::tree::impl::hqueue_fast(const tag::tree::tree_t<T>&, const Image<J>&, const Neighborhood<N>&);
+ /// \}
+
+ };
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::util
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ data< util::ctree::ctree<I> >::data(const I& f)
+ : domain_ (f.domain())
+ {
+ }
+
+ template <typename I>
+ inline
+ data< util::ctree::ctree<I> >::~data()
+ {
+ }
+
+ } // end of namespace mln::internal
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+ namespace internal
+ {
+ template <typename T>
+ struct create_node : Function_v2v< create_node<T> >
+ {
+ typedef typename T::index_t param;
+ typedef typename T::node_t result;
+
+ create_node(const T& tree)
+ : tree_ (tree)
+ {
+ }
+
+ result
+ operator()(const param& idx) const
+ {
+ result tmp(tree_, idx);
+ return tmp;
+ }
+
+ private:
+ const T& tree_;
+ };
+ }
+
+
+ template <typename I>
+ inline
+ ctree<I>::ctree()
+ {
+ }
+
+ template <typename I>
+ inline
+ void
+ ctree<I>::reserve(const Image<I>& f_, unsigned nnodes)
+ {
+ const I& f = exact(f_);
+
+ mln_precondition(f.is_valid());
+ this->data_ = new mln::internal::data< ctree<I> >(f);
+
+ initialize(this->data_->map_, f);
+ this->data_->parent_.resize(nnodes);
+ this->data_->length_.resize(nnodes);
+ this->data_->values_.resize(nnodes);
+ this->data_->nnodes = nnodes;
+# ifndef DNDEBUG
+ data::fill(this->data_->map_, 0);
+ std::fill(this->data_->parent_.begin(), this->data_->parent_.end(), 0);
+ std::fill(this->data_->length_.begin(), this->data_->length_.end(), 0);
+# endif
+ }
+
+
+ template <typename I>
+ template <typename S>
+ inline
+ ctree<I>::ctree(const Image<I>& f_,
+ const S& s,
+ mln_ch_value(I, unsigned)& parent,
+ mln_ch_value(I, unsigned)& area,
+ unsigned nb_nodes)
+ {
+ const I& f = exact(f_);
+
+ mln_precondition(f.is_valid());
+ mln_precondition(parent.is_valid());
+ mln_precondition(area.is_valid());
+ mln_precondition(f.domain() == parent.domain());
+ mln_precondition(f.domain() == area.domain());
+
+ this->data_ = new mln::internal::data< ctree<I> >(f);
+
+ initialize(this->data_->map_, f);
+ this->data_->parent_.resize(nb_nodes);
+ this->data_->length_.resize(nb_nodes);
+ this->data_->values_.resize(nb_nodes);
+ this->data_->nnodes = nb_nodes;
+
+ //debug::println("Parent: ", parent);
+ //debug::println("Area: ", area);
+
+ unsigned root_offset = 0;
+
+ const unsigned nvalues = mln_card(mln_value(I));
+
+ // FIXME: max tree only
+ for (unsigned v = 0; v < nvalues; ++v)
+ {
+ const util::array<unsigned>& s_v = s[v];
+ unsigned n_p = s_v.nelements();
+
+ for (int i = n_p - 1; i >= 0; --i)
+ {
+ unsigned p = s_v[i];
+ unsigned q = parent.element(p);
+
+ if (f.element(parent.element(q)) == f.element(q)) // Canonization
+ q = (parent.element(p) = parent.element(q));
+
+ if (f.element(p) == f.element(q) && p != q) // Not a node.
+ {
+ mln_assertion(q == parent.element(p));
+ this->data_->map_.element(p) =
+ this->data_->map_.element(q);
+ }
+ else
+ {
+ unsigned& offset = (p == q) ? root_offset : area.element(q);
+
+ // Insert Node.
+ mln_assertion(offset < nb_nodes);
+ this->data_->map_.element(p) = offset;
+ this->data_->parent_[offset] = this->data_->map_.element(q);
+ this->data_->values_[offset] = f.element(p);
+ this->data_->length_[offset] = area.element(p);
+ area.element(p) = offset + 1;
+ offset += this->data_->length_[offset] + 1;
+ }
+ }
+ }
+ }
+
+// template <typename T>
+// std::ostream&
+// operator<< (std::ostream& os, const std::vector<T>& v)
+// {
+// for (unsigned i = 0; i < v.size(); i++)
+// os << v[i] << " ";
+// return os;
+// }
+
+ template <typename I>
+ inline
+ ctree<I>::ctree(const Image<I>& f_,
+ const mln_ch_value(I, unsigned)& map,
+ const std::vector<unsigned>& location,
+ const std::vector<unsigned>& parent,
+ const std::vector<unsigned>& area)
+ {
+ const I& f = exact(f_);
+ unsigned n_nodes = location.size();
+
+ mln_precondition(f.is_valid());
+ mln_precondition(map.is_valid());
+ mln_precondition(parent.size() == n_nodes);
+ mln_precondition(area.size() == n_nodes);
+
+ this->data_ = new mln::internal::data< ctree<I> >(f);
+
+ initialize(this->data_->map_, f);
+ this->data_->parent_.resize(n_nodes);
+ this->data_->length_.resize(n_nodes);
+ this->data_->values_.resize(n_nodes);
+ this->data_->nnodes = n_nodes;
+
+
+ // debug::println("F:", f);
+ // debug::println("map:", map);
+ // std::cout << "Location: " << location << std::endl;
+ // std::cout << "Parent: " << parent << std::endl;
+ // std::cout << "Area: " << area << std::endl;
+
+
+ std::vector<char> deja_vu(n_nodes, 0);
+ mln_pixter(const I) pix(f);
+ for_all(pix)
+ {
+ unsigned idx = map.element(pix.offset());
+ unsigned loc = n_nodes - location[idx] - 1;
+ this->data_->map_.element(pix.offset()) = loc;
+
+ if (!deja_vu[idx])
+ {
+ this->data_->values_[loc] = pix.val();
+ this->data_->parent_[loc] = n_nodes - location[parent[idx]] - 1;
+ this->data_->length_[loc] = area[idx];
+ deja_vu[idx] = true;
+ }
+ }
+
+ // debug::println("map:", this->data_->map_);
+ // std::cout << "Parent: " << this->data_->parent_ << std::endl;
+ // std::cout << "Area: " << this->data_->length_ << std::endl;
+ // std::cout << "Values: " << this->data_->values_ << std::endl;
+
+ }
+
+ template <typename I>
+ inline
+ const mln_domain(I)&
+ ctree<I>::domain() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->domain_;
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::nodes_t
+ ctree<I>::nodes() const
+ {
+ mln_precondition(this->is_valid());
+ nodes_t nodes_(*this, node_t(*this, 0), this->data_->nnodes);
+ return nodes_;
+ }
+
+ template <typename I>
+ inline
+ const typename ctree<I>::map_t&
+ ctree<I>::map() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->map_;
+ }
+
+ template <typename I>
+ inline
+ int
+ ctree<I>::n_nodes() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->nnodes;
+ }
+
+ template <typename I>
+ inline
+ bool
+ ctree<I>::has(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->domain_.has(p);
+ }
+
+ template <typename I>
+ inline
+ bool
+ ctree<I>::has(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(n.is_valid());
+ mln_invariant(n.tree().data_.ptr_ == this->data_.ptr_);
+ return n.index() < this->data_->nnodes;
+ }
+
+ template <typename I>
+ inline
+ mln_rvalue(I)
+ ctree<I>::f (const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ return this->data_->values_[this->data_->map_(p)];
+ }
+
+ template <typename I>
+ inline
+ mln_lvalue(I)
+ ctree<I>::f (const mln_psite(I)& p)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ return this->data_->values_[this->data_->map_(p)];
+ }
+
+ template <typename I>
+ inline
+ mln_rvalue(I)
+ ctree<I>::f (const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return this->data_->values_[n.index()];
+ }
+
+ template <typename I>
+ inline
+ mln_lvalue(I)
+ ctree<I>::f (const node_t& n)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return this->data_->values_[n.index()];
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::node_t
+ ctree<I>::node(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ node_t tmp(*this, this->data_->map_(p));
+ mln_postcondition(this->has(tmp));
+ return tmp;
+ }
+
+ template <typename I>
+ inline
+ void
+ ctree<I>::set_node(const mln_psite(I)& p, const node_t& n)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ mln_precondition(this->has(n));
+ this->data_->map_(p) = n.index();
+ }
+
+
+ template <typename I>
+ inline
+ typename ctree<I>::node_t
+ ctree<I>::parent(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ node_t tmp(*this, this->data_->parent_[n.index()]);
+ mln_postcondition(tmp.index() <= n.index());
+ mln_postcondition(this->has(tmp));
+ return tmp;
+ }
+
+ template <typename I>
+ inline
+ void
+ ctree<I>::set_parent(const node_t& n, const node_t& parent)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ mln_precondition(this->has(parent));
+ this->data_->parent_[n.index()] = parent.index();
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::nodes_t
+ ctree<I>::desc(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ nodes_t tmp(*this, n, this->data_->length_[n.index()] + 1);
+ mln_postcondition(tmp.nsites() >= 1);
+ return tmp;
+ }
+
+ template <typename I>
+ inline
+ bool
+ ctree<I>::is_a_root(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return (this->data_->parent_[n.index()] == n.index());
+ }
+
+ template <typename I>
+ inline
+ bool
+ ctree<I>::is_a_leaf(const node_t& n) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(n));
+ return (this->data_->length_[n.index()] == 0);
+ }
+
+ template <typename I>
+ inline
+ bool
+ ctree<I>::has_index(index_t i) const
+ {
+ mln_precondition(this->is_valid());
+ return 0 <= i && i <= this->n_nodes();
+ }
+
+
+ template <typename I>
+ inline
+ unsigned
+ ctree<I>::length_(const node_t& node) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(node));
+ return this->data_->length_[node.index()];
+ }
+
+ template <typename I>
+ inline
+ unsigned
+ ctree<I>::length_at_(index_t i) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ return this->data_->length_[i];
+ }
+
+ template <typename I>
+ inline
+ unsigned&
+ ctree<I>::length_at_(index_t i)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ return this->data_->length_[i];
+ }
+
+
+
+ template <typename I>
+ inline
+ mln_rvalue(I)
+ ctree<I>::f_at_(index_t i) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ return this->data_->values_[i];
+ }
+
+ template <typename I>
+ inline
+ mln_lvalue(I)
+ ctree<I>::f_at_(index_t i)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ return this->data_->values_[i];
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::index_t
+ ctree<I>::parent_at_(index_t i) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ mln_postcondition(this->has_index(this->data_->parent_[i]));
+ return this->data_->parent_[i];
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::index_t&
+ ctree<I>::parent_at_(index_t i)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has_index(i));
+ mln_postcondition(this->has_index(this->data_->parent_[i]));
+ return this->data_->parent_[i];
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::index_t
+ ctree<I>::node_at_(const psite& p) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ mln_postcondition(this->has_index(this->data_->map_(p)));
+ return this->data_->map_(p);
+ }
+
+ template <typename I>
+ inline
+ typename ctree<I>::index_t&
+ ctree<I>::node_at_(const psite& p)
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(this->has(p));
+ mln_postcondition(this->has_index(this->data_->map_(p)));
+ return this->data_->map_(p);
+ }
+
+ template <typename I>
+ inline
+ attribute_image<ctree<I>, mln_value(I)>
+ ctree<I>::to_image() const
+ {
+ mln_precondition(this->is_valid());
+
+ attribute_image<ctree<I>, value> to(*this);
+ this->to_image(to);
+ return to;
+ }
+
+ template <typename I>
+ inline
+ void
+ ctree<I>::to_image(attribute_image<ctree<I>, value>& a) const
+ {
+ mln_precondition(this->is_valid());
+ mln_precondition(a.is_valid());
+ mln_precondition(a.tree().data_.ptr_ == this->data_.ptr_);
+
+ std::copy(this->data_->values_.begin(), this->data_->values_.end(), a.buffer());
+ }
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::util
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // !MLN_UTIL_CTREE_CTREE_HH
diff --git a/milena/mln/util/ctree/internal/tree_base.hh b/milena/mln/util/ctree/internal/tree_base.hh
new file mode 100644
index 0000000..23c76b3
--- /dev/null
+++ b/milena/mln/util/ctree/internal/tree_base.hh
@@ -0,0 +1,141 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_UTIL_CTREE_INTERNAL_TREE_BASE_HH
+# define MLN_UTIL_CTREE_INTERNAL_TREE_BASE_HH
+
+# include <mln/core/concept/object.hh>
+# include <mln/core/concept/tree.hh>
+# include <mln/core/concept/proxy.hh>
+# include <mln/core/internal/data.hh>
+
+# include <mln/core/site_set/p_nodes.hh>
+
+# include <mln/util/ctree/node.hh>
+# include <mln/util/tracked_ptr.hh>
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+
+ namespace internal
+ {
+
+ template <typename I, typename E>
+ class tree_base : public Tree<E>
+ {
+ public:
+ /// Site related type definitions.
+ /// \{
+ /// The type of site.
+ typedef mln_site(I) site;
+ /// The type of pseudo-site.
+ typedef mln_psite(I) psite;
+ /// The type of domain.
+ typedef mln_domain(I) domain_t;
+ /// \}
+
+ /// Node related type definions.
+ /// \{
+ /// The type of the node.
+ typedef node<E> node_t;
+ /// The type of node set.
+ typedef p_nodes<E> nodes_t;
+ /// \}
+
+ /// Node/Site value related type definitions.
+ /// \{
+ /// The type of node value
+ typedef mln_value(I) value;
+ /// The type of node rvalue.
+ typedef mln_rvalue(I) rvalue;
+ /// The type of node lvalue.
+ typedef mln_lvalue(I) lvalue;
+ /// \}
+
+ /// Check validity.
+ bool is_valid() const;
+ void invalidate();
+
+ /// Hook to data; for debugging purpose.
+ const util::tracked_ptr< mln::internal::data<E> >& data_hook_() const;
+
+ protected:
+ tree_base();
+
+ protected:
+ util::tracked_ptr< mln::internal::data<E> > data_;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template<typename I, typename E>
+ inline
+ tree_base<I,E>::tree_base()
+ : data_ (0)
+ {
+ }
+
+ template <typename I, typename E>
+ inline
+ bool
+ tree_base<I,E>::is_valid() const
+ {
+ return data_ != 0;
+ }
+
+ template <typename I, typename E>
+ inline
+ void
+ tree_base<I,E>::invalidate()
+ {
+ data_.clean_();
+ }
+
+ template<typename I, typename E>
+ inline
+ const util::tracked_ptr< mln::internal::data<E> >&
+ tree_base<I,E>::data_hook_() const
+ {
+ return data_;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::util::ctree::internal
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif // !MLN_UTIL_CTREE_INTERNAL_TREE_BASE_HH
diff --git a/milena/mln/util/ctree/node.hh b/milena/mln/util/ctree/node.hh
new file mode 100644
index 0000000..d22c48e
--- /dev/null
+++ b/milena/mln/util/ctree/node.hh
@@ -0,0 +1,351 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_UTIL_CTREE_NODE_HH
+# define MLN_UTIL_CTREE_NODE_HH
+
+# include <mln/core/concept/proxy.hh>
+# include <mln/core/concept/site.hh>
+# include <mln/core/internal/pseudo_site_base.hh>
+
+namespace mln
+{
+
+ /// Node category flag type.
+ template <typename E> struct Node {};
+
+ template <>
+ struct Node<void>
+ {
+ typedef Site<void> super;
+ };
+
+ /// Fwd declaration.
+ namespace util
+ {
+ namespace ctree
+ {
+ template <typename T>
+ class node;
+ }
+
+ }
+
+ namespace trait
+ {
+ template <typename T>
+ struct set_precise_unary_< op::ord, util::ctree::node<T> >
+ {
+ typedef set_precise_unary_< op::ord, util::ctree::node<T> > ret; // Itself.
+ bool strict(const util::ctree::node<T>& lhs, const util::ctree::node<T>& rhs) const;
+ };
+
+ } // end of namespace trait
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+
+ template <typename T>
+ class node
+ {
+ public:
+ /// Object category.
+ typedef Node<void> category;
+
+ /// The node index.
+ typedef int index_t;
+
+ /// Tree associated type.
+ typedef T tree_t;
+
+ /// FIXME:
+ typedef int delta;
+
+ /// Constructors
+ /// \{
+ node();
+ explicit node(const Tree<T>& tree);
+ node(const Tree<T>& tree, int idx);
+ /// \}
+
+ /// Misc
+ /// \{
+ /// Return whether the node is valid.
+ bool is_valid() const;
+
+ /// Index manipulation.
+ /// \{
+ int index() const;
+ void inc_index();
+ void dec_index();
+ void change_index(int idx);
+ /// \}
+
+ /// Return a reference to the graph holding this node.
+ const T& tree() const;
+
+ /// Change target.
+ void change_tree(const Tree<T>& tree);
+ /// \}
+
+
+ private:
+ const T* tree_;
+ int idx_;
+ };
+
+ /*
+ ** Operators.
+ */
+ template <typename T>
+ bool
+ operator== (const node<T>& n1, const node<T>& n2);
+
+ template <typename T>
+ bool
+ operator!= (const node<T>& n1, const node<T>& n2);
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::util
+
+
+ namespace internal
+ {
+
+ /// subject_impl specialization (Proxy)
+ /// \{
+
+ template <typename T, typename E>
+ struct subject_impl< const util::ctree::node<T>, E >
+ {
+ int index() const;
+ const T& tree() const;
+
+ private:
+ const E& exact_() const;
+ };
+
+ template <typename T, typename E>
+ struct subject_impl< util::ctree::node<T>, E > :
+ subject_impl< const util::ctree::node<T>, E >
+ {
+ void change_index(int idx);
+
+ private:
+ E& exact_();
+ };
+
+ /// \}
+
+ } // end of namespace mln::internal
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+
+ template <typename T>
+ inline
+ node<T>::node()
+ : tree_ (0)
+ {
+ }
+
+ template <typename T>
+ inline
+ node<T>::node(const Tree<T>& tree)
+ : tree_ (&(exact(tree)))
+ {
+ }
+
+
+ template <typename T>
+ inline
+ node<T>::node(const Tree<T>& tree, int idx)
+ : tree_ (&(exact(tree))),
+ idx_ (idx)
+ {
+ mln_precondition(tree_->is_valid());
+ }
+
+ template <typename T>
+ inline
+ int
+ node<T>::index() const
+ {
+ return idx_;
+ }
+
+ template <typename T>
+ inline
+ void
+ node<T>::inc_index()
+ {
+ ++idx_;
+ }
+
+ template <typename T>
+ inline
+ void
+ node<T>::dec_index()
+ {
+ --idx_;
+ }
+
+ template <typename T>
+ inline
+ void
+ node<T>::change_index(int idx)
+ {
+ idx_ = idx;
+ }
+
+ template <typename T>
+ inline
+ const T&
+ node<T>::tree() const
+ {
+ mln_precondition(this->is_valid());
+ return *tree_;
+ }
+
+ template <typename T>
+ inline
+ void
+ node<T>::change_tree(const Tree<T>& tree)
+ {
+ tree_ = &(exact(tree));
+ }
+
+ template <typename T>
+ inline
+ bool
+ node<T>::is_valid() const
+ {
+ return tree_ != 0 && tree_->is_valid();
+ }
+
+ /*
+ ** Operators
+ */
+ template <typename T>
+ inline
+ bool
+ operator== (const node<T>& n1, const node<T>& n2)
+ {
+ return n1.index() == n2.index();
+ }
+
+ template <typename T>
+ inline
+ bool
+ operator!= (const node<T>& n1, const node<T>& n2)
+ {
+ return n1.index() != n2.index();
+ }
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::util
+
+ namespace internal
+ {
+
+ /*-----------------------------------------`
+ | subject_impl< const util::ctree::node<G> |
+ \-----------------------------------------*/
+
+ template <typename T, typename E>
+ inline
+ const E&
+ subject_impl< const util::ctree::node<T>, E >::exact_() const
+ {
+ return internal::force_exact<const E>(*this);
+ }
+
+ template <typename T, typename E>
+ inline
+ int
+ subject_impl< const util::ctree::node<T>, E >::index() const
+ {
+ return exact_().get_subject().index();
+ }
+
+ template <typename T, typename E>
+ inline
+ const T&
+ subject_impl< const util::ctree::node<T>, E >::tree() const
+ {
+ return exact_().get_subject().tree();
+ }
+
+ /*------------------------------------------`
+ | subject_impl< util::ctree::node<T> |
+ \-----------------------------------------*/
+
+ template <typename T, typename E>
+ inline
+ E&
+ subject_impl< util::ctree::node<T>, E >::exact_()
+ {
+ return internal::force_exact<E>(*this);
+ }
+
+ template <typename T, typename E>
+ inline
+ void
+ subject_impl< util::ctree::node<T>, E >::change_index(int idx)
+ {
+ return exact_().get_subject().change_index(idx);
+ }
+
+ } // end of namespace mln::internal
+
+ namespace trait
+ {
+
+ template <typename T>
+ inline
+ bool
+ set_precise_unary_< op::ord, util::ctree::node<T> >::strict(const util::ctree::node<T>& lhs, const util::ctree::node<T>& rhs) const
+ {
+ return util::ord_strict(lhs.index(), rhs.index());
+ }
+
+ } // end of namespace trait
+
+
+# endif // !MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // !MLN_UTIL_CTREE_NODE_HH
diff --git a/milena/mln/util/ctree/tree_ids.hh b/milena/mln/util/ctree/tree_ids.hh
new file mode 100644
index 0000000..f9a2eae
--- /dev/null
+++ b/milena/mln/util/ctree/tree_ids.hh
@@ -0,0 +1,53 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_UTIL_CTREE_TREE_IDS_HH
+# define MLN_UTIL_CTREE_TREE_IDS_HH
+
+# include <mln/util/object_id.hh>
+
+
+namespace mln
+{
+
+ namespace util
+ {
+
+ namespace ctree
+ {
+
+ /// Object Id node tag.
+ struct node_tag;
+
+ /// Node id type.
+ typedef object_id<node_tag, unsigned> node_id_t;
+
+ } // end of namespace mln::util::ctree
+
+ } // end of namespace mln::util
+
+} // end of namespace mln
+
+#endif // !MLN_UTIL_CTREE_TREE_IDS_HH
--
1.5.6.5
1
0
04 May '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch features/maxtree has been created
at 7d671b90984a791d6146eb5d510c1bf827ed073c (commit)
- Log -----------------------------------------------------------------
7d671b9 Tree debug tools.
ee79ab0 Comparaison of tree build algorithms.
70d045f Tree build algorithms and tree management routines
3925ac9 Unified structure for simple/dual input min/max tree.
-----------------------------------------------------------------------
hooks/post-receive
--
Olena, a generic and efficient image processing platform
1
0
* mln/debug/all.hh: Update.
* mln/debug/ctree.hh: New.
---
milena/ChangeLog | 24 ++++++++++++++++++++++++
milena/mln/debug/all.hh | 2 +-
milena/{sandbox/edwin => }/mln/debug/ctree.hh | 5 +++--
3 files changed, 28 insertions(+), 3 deletions(-)
copy milena/{sandbox/edwin => }/mln/debug/ctree.hh (97%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 0529b68..bb30678 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,27 @@
+2010-05-04 edwin carlinet <carlinet(a)lrde.epita.fr>
+
+ Tree build algorithms and tree management routines
+
+ * mln/core/image/all.hh: Update.
+ * mln/morpho/tree/all.hh: Update.
+ * mln/tag/skeleton.hh: Update.
+ * mln/morpho/tree/component_tree.hh: Routines to build component
+ trees.
+ * mln/morpho/tree/compute_attribute_image.hh: Routines to compute
+ attribute images.
+ * mln/morpho/tree/dual_input_tree.hh: Routines to build dual-input
+ trees.
+ * mln/morpho/tree/filter/direct.hh,
+ * mln/morpho/tree/filter/max.hh,
+ * mln/morpho/tree/filter/min.hh,
+ * mln/morpho/tree/filter/subtractive.hh: Filtering routines.
+ * mln/morpho/tree/impl/hqueue.hh,
+ * mln/morpho/tree/impl/hqueue_fast.hh,
+ * mln/morpho/tree/impl/union_find.hh,
+ * mln/morpho/tree/impl/union_find_fast.hh: Tree computation algorithms.
+ * mln/morpho/tree/leaf_last.hh,
+ * mln/morpho/tree/propagate_node.hh: Tree management routines.
+
2010-04-09 edwin carlinet <carlinet(a)lrde.epita.fr>
Unified structure for simple/dual input min/max tree.
diff --git a/milena/mln/debug/all.hh b/milena/mln/debug/all.hh
index 68021ee..2e50185 100644
--- a/milena/mln/debug/all.hh
+++ b/milena/mln/debug/all.hh
@@ -44,7 +44,7 @@ namespace mln
}
}
-
+# include <mln/debug/ctree.hh>
# include <mln/debug/draw_graph.hh>
# include <mln/debug/format.hh>
# include <mln/debug/histo.hh>
diff --git a/milena/sandbox/edwin/mln/debug/ctree.hh b/milena/mln/debug/ctree.hh
similarity index 97%
copy from milena/sandbox/edwin/mln/debug/ctree.hh
copy to milena/mln/debug/ctree.hh
index 1cb5cbd..c8e576d 100644
--- a/milena/sandbox/edwin/mln/debug/ctree.hh
+++ b/milena/mln/debug/ctree.hh
@@ -105,7 +105,8 @@ namespace mln
depth = 0;
else
{
- while (old != tree.parent(n))
+ typename T::node_t par = tree.parent(n);
+ while (old != par)
{
--depth;
old = tree.parent(old);
@@ -115,7 +116,7 @@ namespace mln
for (unsigned i = 0; i < depth; i++)
std::cout << " ";
- std::cout << n;
+ std::cout << n.index();
for (unsigned i = depth; i < height + 1; i++)
std::cout << " ";
--
1.5.6.5
1
0
04 May '10
* edwin/TreeAlgorithmsComp/dual/dual.hh
* edwin/TreeAlgorithmsComp/dual/dual_main
* edwin/TreeAlgorithmsComp/dual/dual_main.cc
* edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c
* edwin/TreeAlgorithmsComp/makefile.rules
* edwin/TreeAlgorithmsComp/max_tree.cc
* edwin/TreeAlgorithmsComp/max_tree_with_rank.cc
* edwin/TreeAlgorithmsComp/parallel_apply.hh
* edwin/TreeAlgorithmsComp/parallel_union_find.hh
* edwin/TreeAlgorithmsComp/tbb_union_find_8.cc
* edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc
* edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc
* edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc
* edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc
---
milena/sandbox/ChangeLog | 20 +
.../sandbox/edwin/TreeAlgorithmsComp/dual/dual.hh | 52 ++
.../edwin/TreeAlgorithmsComp/dual/dual_main | Bin 0 -> 770633 bytes
.../edwin/TreeAlgorithmsComp/dual/dual_main.cc | 34 +
.../edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c | 738 ++++++++++++++++++++
.../edwin/TreeAlgorithmsComp/makefile.rules | 1 +
.../sandbox/edwin/TreeAlgorithmsComp/max_tree.cc | 232 ++++++
.../edwin/TreeAlgorithmsComp/max_tree_with_rank.cc | 201 ++++++
.../edwin/TreeAlgorithmsComp/parallel_apply.hh | 89 +++
.../TreeAlgorithmsComp/parallel_union_find.hh | 394 +++++++++++
.../edwin/TreeAlgorithmsComp/tbb_union_find_8.cc | 59 ++
.../TreeAlgorithmsComp/test_salembier_fast_16.cc | 62 ++
.../TreeAlgorithmsComp/test_salembier_fast_8.cc | 62 ++
.../TreeAlgorithmsComp/test_union_find_fast_16.cc | 62 ++
.../TreeAlgorithmsComp/test_union_find_fast_8.cc | 62 ++
15 files changed, 2068 insertions(+), 0 deletions(-)
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual.hh
create mode 100755 milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/makefile.rules
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/max_tree.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/max_tree_with_rank.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/parallel_apply.hh
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/parallel_union_find.hh
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/tbb_union_find_8.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc
create mode 100644 milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 9e7f25b..15f7fa8 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,23 @@
+2010-05-04 edwin carlinet <carlinet(a)lrde.epita.fr>
+
+ Comparison of tree build algorithms.
+
+ * edwin/TreeAlgorithmsComp/dual/dual.hh,
+ * edwin/TreeAlgorithmsComp/dual/dual_main,
+ * edwin/TreeAlgorithmsComp/dual/dual_main.cc,
+ * edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c,
+ * edwin/TreeAlgorithmsComp/makefile.rules,
+ * edwin/TreeAlgorithmsComp/max_tree.cc,
+ * edwin/TreeAlgorithmsComp/max_tree_with_rank.cc,
+ * edwin/TreeAlgorithmsComp/parallel_apply.hh,
+ * edwin/TreeAlgorithmsComp/parallel_union_find.hh,
+ * edwin/TreeAlgorithmsComp/tbb_union_find_8.cc,
+ * edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc,
+ * edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc,
+ * edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc,
+ * edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc:
+ Comparison algorithms.
+
2009-11-17 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add some bench + canvas + subsampling + browsing code.
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual.hh b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual.hh
new file mode 100644
index 0000000..23995e1
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual.hh
@@ -0,0 +1,52 @@
+#ifndef DUAL_HH_
+# define DUAL_HH_
+
+#include <mln/border/all.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/tree/dual_input_tree.hh>
+#include <mln/core/image/attribute_image.hh>
+#include <mln/morpho/attribute/card.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/debug/ctree.hh>
+#include <mln/io/pgm/save.hh>
+
+using namespace mln;
+
+typedef value::int_u8 V;
+typedef image2d<V> I;
+typedef util::ctree::ctree<I> tree_t;
+typedef morpho::attribute::card<I> attr_t;
+typedef mln_result_(attr_t) S;
+typedef attribute_image<tree_t, S > A;
+typedef neighb2d N;
+
+using value::int_u8;
+
+
+void
+inline
+test(const int_u8* f_, const int_u8* m_, int n)
+{
+ box<point2d> domain(point2d(0, 0), point2d(0, n-1));
+ image2d<int_u8> f(domain), m(domain);
+ N nbh = c4();
+ for (int i = 0; i < n ; ++i)
+ {
+ f.at_(0, i) = f_[i];
+ m.at_(0, i) = m_[i];
+ }
+
+ io::pgm::save(f, "input.pgm");
+ io::pgm::save(m, "mask.pgm");
+
+ tree_t tree = morpho::tree::dual_input_max_tree(f, m, nbh);
+ std::cout << "Volume info " << "" << std::endl
+ << "\tSize: " << geom::nsites(f) << std::endl
+ << "\tQuant: " << sizeof(V) * 4 << std::endl
+ << "\tNodes: " << tree.n_nodes() << std::endl;
+
+ debug::println(tree);
+}
+
+#endif
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main
new file mode 100755
index 0000000000000000000000000000000000000000..8b9a058018c900ab3d28aa7de43388a3c3b8d917
GIT binary patch
literal 770633
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
literal 0
HcmV?d00001
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main.cc
new file mode 100644
index 0000000..d895fcb
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/dual_main.cc
@@ -0,0 +1,34 @@
+#include "dual.hh"
+
+int main(int argc, char** argv)
+{
+ {
+ int_u8 f[] = {2, 1, 2};
+ int_u8 m[] = {2, 2, 2};
+ int n = sizeof(f);
+ test(f, m, n);
+ }
+
+ {
+ int_u8 f[] = {2, 1, 1, 2, 0};
+ int_u8 m[] = {2, 3, 3, 2, 3};
+ int n = sizeof(f);
+ test(f, m, n);
+ }
+
+ // With internmediate level creation
+ {
+ int_u8 f[] = {10, 1, 1, 10, 5, 10, 5};
+ int_u8 m[] = {12, 8, 8, 12, 12, 12, 5};
+ int n = sizeof(f);
+ test(f, m, n);
+ }
+
+ // With singleton creation
+ {
+ int_u8 f[] = {15, 1, 1, 15, 18, 5};
+ int_u8 m[] = {12, 8, 8, 12, 12, 5};
+ int n = sizeof(f);
+ test(f, m, n);
+ }
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c
new file mode 100644
index 0000000..fea9ddf
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/dual/wilkinson_ref.c
@@ -0,0 +1,738 @@
+/**********************************************************/
+/* */
+/* Area/shape preserving extensive and anti-extensive */
+/* operators using Max-Trees */
+/* */
+/* by Georgios K Ouzounis - Jan. 2004 */
+/* original Max-Tree code by Erik Urbach June 2000. */
+/* */
+/**********************************************************/
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/times.h>
+#include <unistd.h>
+
+#include <FreeImage.h>
+
+
+typedef short bool;
+#define false 0
+#define true 1
+
+typedef unsigned char ubyte;
+
+typedef unsigned short greyval;
+
+
+
+#define NUMLEVELS 65536
+#define CONNECTIVITY 4
+
+double kbase, background = 0, alpha=0;
+
+typedef struct FIFOQueue
+{
+ long *Pixels;
+ long Head;
+ long Tail; /* First free place in queue, or -1 when the queue is full */
+} FIFOQueue;
+
+
+
+/*** Max-Tree definition ***/
+
+typedef struct MaxNode MaxNode;
+typedef struct MaxNode *MaxTree;
+
+/* MaxNode Status */
+#define MTS_Ok 0
+#define MTS_Deleted 1
+
+struct MaxNode
+{
+ long Parent;
+ long Status;
+ long Area;
+ int PeakLevel;
+ int kPrime;
+ int Level;
+ int NewLevel;
+};
+
+MaxTree Tree;
+
+
+
+/*** Globals used by Max-Tree ***/
+
+long numbernodes[NUMLEVELS]; /* Number of nodes C^k_h at level h */
+greyval **P_ORI; /* Denotes the original gray level value of pixel p in processed image*/
+greyval **ORI; /* Denotes the original ... in the unproceesed input image */
+
+/* STATUS stores the information of the pixel status: the pixel can be
+ * NotAnalyzed, InTheQueue or assigned to node k at level h. In this
+ * last case STATUS(p)=k. */
+#define ST_NotAnalyzed -1
+#define ST_InTheQueue -2
+long *STATUS;
+
+bool NodeAtLevel[NUMLEVELS];
+
+/*** HQueue globals ***/
+long MaxPixelsPerLevel[NUMLEVELS]; /* Original image */
+long PMaxPixelsPerLevel[NUMLEVELS]; /* Processed image */
+FIFOQueue HQueue[NUMLEVELS];
+
+/*** Other globals ***/
+long ImageWidth;
+long ImageHeight;
+long ImageSize;
+long NumPlanes;
+
+long NumPixelsBelowLevel[NUMLEVELS];
+long PNumPixelsBelowLevel[NUMLEVELS];
+
+#define ReadPixel(t,i,h) (t[NumPixelsBelowLevel[h]+i].NewLevel)
+
+/*** Queue functions ***/
+#define HQueueFirst(h) (HQueue[h].Pixels[HQueue[h].Head++])
+#define HQueueAdd(h,p) HQueue[h].Pixels[HQueue[h].Tail++] = p
+#define HQueueNotEmpty(h) (HQueue[h].Head != HQueue[h].Tail)
+void HQueueCreate(void);
+void HQueueDelete(void);
+
+/***********************************************/
+/* HQueue is an array segmented based on the */
+/* processed image histogram. */
+/***********************************************/
+
+void HQueueCreate(void)
+{
+ int i;
+
+ HQueue->Pixels = calloc((size_t)2*ImageSize, sizeof(long));
+ assert(HQueue->Pixels != NULL);
+ HQueue->Head = HQueue->Tail = 0;
+ for (i=1; i<NUMLEVELS; i++)
+ {
+ HQueue[i].Pixels = HQueue[i-1].Pixels + PMaxPixelsPerLevel[i-1] + MaxPixelsPerLevel[i-1];
+ HQueue[i].Head = HQueue[i].Tail = 0;
+ }
+
+} /* HQueueCreate */
+
+
+/***********************************************/
+/* Image I/O functions */
+/***********************************************/
+
+
+
+/** Generic image loader
+@param lpszPathName Pointer to the full file name
+@param flag Optional load flag constant
+@return Returns the loaded dib if successful, returns NULL otherwise
+*/
+FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+// check the file signature and deduce its format
+// (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // ok, let's load the file
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
+ // unless a bad file format, we are done !
+ return dib;
+ }
+ return NULL;
+}
+
+greyval **ReadTIFF(char *fnm, long *width, long *height, long *numplanes){
+ FIBITMAP *dib = GenericLoader(fnm,0);
+ unsigned long bitsperpixel;
+ greyval **im;
+ unsigned int x,y,i,j,imsize;
+ if (dib == NULL) return NULL;
+
+ bitsperpixel = FreeImage_GetBPP(dib);
+ *numplanes=1;
+ if ((bitsperpixel==24) ||(bitsperpixel==48))
+ *numplanes=3;
+ *height = FreeImage_GetHeight(dib),
+ *width = FreeImage_GetWidth(dib);
+
+ imsize = (*width)*(*height);
+ im = calloc((size_t)*numplanes, sizeof(greyval *));
+ assert(im!=NULL);
+ for (i=0;i<*numplanes;i++){
+ im[i] = calloc((size_t)imsize, sizeof(greyval));
+ assert(im[i]!=NULL);
+ }
+ switch(bitsperpixel) {
+ case 8 :
+ i=0;
+ for(y = 0; y <*height; y++) {
+ BYTE *bits = (BYTE *)FreeImage_GetScanLine(dib, *height - y -1);
+ //printf("y=%d\n",y);
+ for(x = 0; x < *width; x++,i++) {
+ im[0][i] = bits[x];
+ }
+ }
+
+ FreeImage_Unload(dib);
+ return im;
+ case 16 :
+ i=0;
+ for(y = 0; y < *height; y++) {
+ unsigned short *bits = (unsigned short *)FreeImage_GetScanLine(dib,*height - y -1);
+ for(x = 0; x < *width; x++,i++) {
+ im[0][i] = bits[x];
+ }
+ }
+ FreeImage_Unload(dib);
+ return im;
+ case 24 :
+ i=0;
+ for(y = 0; y <*height; y++) {
+ BYTE *bits = (BYTE *)FreeImage_GetScanLine(dib, *height - y -1);
+ //printf("y=%d\n",y);
+ for(x = 0; x < *width; x++,i++) {
+ for (j=0;j<*numplanes;j++)
+ im[j][i] = bits[3*x+j];
+ }
+ }
+
+ FreeImage_Unload(dib);
+ return im;
+ case 48 :
+ i=0;
+ for(y = 0; y <*height; y++) {
+ unsigned short *bits = (unsigned short *)FreeImage_GetScanLine(dib, *height - y -1);
+ //printf("y=%d\n",y);
+ for(x = 0; x < *width; x++,i++) {
+ for (j=0;j<*numplanes;j++)
+ im[j][i] = bits[3*x+j];
+ }
+ }
+
+ FreeImage_Unload(dib);
+ return im;
+
+ default :
+ FreeImage_Unload(dib);
+ fprintf(stderr, "unsupported format\n"); exit(-1);
+ return NULL;
+ }
+
+}
+
+
+void WriteTIFF(char *fname, long width, long height, int bitspp, long numplanes){
+ FIBITMAP *outmap;
+ long i,j,y,x,plane;
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(fname);
+
+ if (bitspp == 8){
+ ubyte *imagebuf;
+ RGBQUAD *pal;
+ outmap = FreeImage_AllocateT(FIT_BITMAP,width,height,numplanes*bitspp,0xFF,0xFF,0xFF);
+ if (numplanes==1){
+ pal = FreeImage_GetPalette(outmap);
+ for (i = 0; i < 256; i++) {
+ pal[i].rgbRed = i;
+ pal[i].rgbGreen = i;
+ pal[i].rgbBlue = i;
+ }
+ }
+ i = 0;
+ for (j=height-1; j>=0; j--){
+ imagebuf = FreeImage_GetScanLine(outmap,j);
+ for (x=0;x<width;x++,i++)
+ for (plane=0;plane<numplanes;plane++)
+ imagebuf[numplanes*x+plane]=ORI[plane][i];
+ }
+
+ } else {
+ greyval *imagebuf;
+ if (numplanes==1)
+ outmap = FreeImage_AllocateT(FIT_UINT16,width,height,16,0xFFFF,0xFFFF,0xFFFF);
+ else
+ outmap = FreeImage_AllocateT(FIT_RGB16,width,height,48,0xFFFF,0xFFFF,0xFFFF);
+
+ i = 0;
+ for (j=height-1; j>=0; j--){
+ imagebuf = (greyval *)FreeImage_GetScanLine(outmap,j);
+ for (x=0;x<width;x++,i++)
+ for (plane=0;plane<numplanes;plane++)
+ imagebuf[numplanes*x+plane]=ORI[plane][i];
+
+ }
+ }
+
+ FreeImage_Save(fif,outmap,fname,0);
+ FreeImage_Unload(outmap);
+
+}
+
+
+void ReadPGM(char *fname,short buffer)
+{
+ long width, height;
+ int c;
+
+
+ if(buffer==1)
+ {
+ ORI = ReadTIFF( fname, &width, &height, &NumPlanes);
+ ImageWidth = width;
+ ImageHeight = height;
+ ImageSize = width*height;
+
+ }
+ else
+ {
+ P_ORI = ReadTIFF(fname, &width, &height, &NumPlanes);
+ ImageWidth = width;
+ ImageHeight = height;
+ ImageSize = width*height;
+ }
+
+} /* ReadPGM */
+
+
+greyval FindMax(greyval *buf, long width, long height){
+ greyval max = buf[0];
+ long i,size = width*height;
+ for (i = 1; i<size;i++){
+ max = (buf[i]>max) ? buf[i] : max;
+ }
+ return max;
+}
+
+
+void WritePGM(char *fname, long width, long height, long numplanes)
+{
+
+
+ if (FindMax(ORI[0],width,height)>255)
+ WriteTIFF(fname, width, height, 16, numplanes);
+ else
+ WriteTIFF(fname, width, height, 8, numplanes);
+
+
+} /* WritePGM */
+
+/***********************************************/
+/* Setting up the Max-Tree structure */
+/* MaxPixelsPerLevel already initialized */
+/***********************************************/
+
+MaxTree MaxTreeCreate(long size)
+{
+ MaxTree t;
+ int i;
+
+ t = calloc((size_t)2*size, sizeof(MaxNode));
+ if (t)
+ {
+ *NumPixelsBelowLevel = 0;
+ for (i=1; i<NUMLEVELS; i++)
+ {
+ NumPixelsBelowLevel[i] = NumPixelsBelowLevel[i-1] + MaxPixelsPerLevel[i-1] + PMaxPixelsPerLevel[i-1];
+ }
+ }
+ return(t);
+} /* MaxTreeCreate */
+
+/***************************************************/
+/* Finds a pixel of minimum intensity in the image */
+/* MaxPixelsPerLevel : Histogram of original image */
+/* PMaxPixelsPerLevel: Histogram of processed image*/
+/***************************************************/
+
+long FindHMinPixel(greyval *ORI,greyval *P_ORI)
+/* */
+{
+ long i, p=0;
+
+ /* initialise level entries */
+ for (i=0; i<NUMLEVELS; i++)
+ {
+ MaxPixelsPerLevel[i] = 0;
+ PMaxPixelsPerLevel[i] = 0;
+ }
+ /* compute histogram */
+ for (i=0; i<ImageSize; i++)
+ {
+ MaxPixelsPerLevel[ORI[i]]++;
+ PMaxPixelsPerLevel[P_ORI[i]]++;
+ if (P_ORI[i]<P_ORI[p]) p = i;
+ }
+ return(p);
+} /* FindHMinPixel */
+
+/***********************************************/
+/* Retrieves the neighbors of pixel p */
+/***********************************************/
+
+int GetNeighbors(long p, long *neighbors)
+{
+ long x;
+ int n=0;
+
+ x = p % ImageWidth;
+ if (x<(ImageWidth-1)) neighbors[n++] = p+1;
+ if (p>=ImageWidth) neighbors[n++] = p-ImageWidth;
+ if (x>0) neighbors[n++] = p-1;
+ p += ImageWidth;
+ if (p<ImageSize) neighbors[n++] = p;
+ return(n);
+} /* GetNeighbors */
+
+
+/***********************************************/
+/* Max-Tree Creation: Here it is the modified */
+/* image that is being processed */
+/***********************************************/
+
+int flood(greyval *ORI, greyval *P_ORI, int h,
+ long *thisarea, int *thispeaklevel)
+{
+ long neighbors[CONNECTIVITY];
+ long p, q,idx;
+ long area = *thisarea, childarea;
+ int numneighbors, i, m, level, peaklevel = h, childpeaklevel;
+ MaxNode *node;
+
+ while(HQueueNotEmpty(h)){
+ p = HQueueFirst(h);
+ STATUS[p] = numbernodes[ORI[p]]; /* in all cases */
+
+ if(ORI[p]!=h){/* unstable regions */
+ level = ORI[p];
+ NodeAtLevel[level]=true;
+
+ /* Detect the node */
+ node = Tree + (NumPixelsBelowLevel[level] + numbernodes[level]);
+ node->Area++;
+ peaklevel = (peaklevel<level)? level : peaklevel;
+ if(level>h){ /* Anti-extensive case */
+
+ /* set the singleton node at ORI[p]*/
+ node->Parent = NumPixelsBelowLevel[h] + numbernodes[h];
+ node->Status = MTS_Ok;
+ node->Level = level;
+ node->PeakLevel = level;
+ numbernodes[level] += 1; /* increase this for next time */
+ NodeAtLevel[level] = false; /* finalise this node */
+ area++; /* Need to update the parent area also */
+ }
+ }else /* Stable or background regions */
+ area++;
+ /* process the neighbors */
+ numneighbors = GetNeighbors(p, neighbors);
+ for (i=0; i<numneighbors; i++){
+ q = neighbors[i];
+ if (STATUS[q]==ST_NotAnalyzed){
+ HQueueAdd(P_ORI[q],q);
+ STATUS[q] = ST_InTheQueue;
+ NodeAtLevel[P_ORI[q]] = true;
+ /* The neighbor is greater than p */
+ if (P_ORI[q] > P_ORI[p])
+ {
+ m = P_ORI[q];
+ childarea = 0;
+ childpeaklevel = m;
+ do
+ {
+ m = flood(ORI, P_ORI, m, &childarea,&childpeaklevel);
+ } while (m!=h);
+ area += childarea;
+ peaklevel = (peaklevel<childpeaklevel)? childpeaklevel : peaklevel;
+ }
+ }
+ }
+ }/* end of while loop*/
+
+ /* Retrieve the parent and finalise the node*/
+ numbernodes[h] = numbernodes[h]+1;
+ m = h-1;
+ while ((m>=0) && (NodeAtLevel[m]==false)) m--;
+ if (m>=0)
+ {
+ node = Tree + (NumPixelsBelowLevel[h] + numbernodes[h]-1);
+ node->Parent = NumPixelsBelowLevel[m] + numbernodes[m];
+ }
+ else
+ {
+ idx = NumPixelsBelowLevel[h];
+ node = Tree + idx;
+ node->Parent = idx;
+ }
+ node->Area += area;
+ node->Status = MTS_Ok;
+ node->Level = h;
+ node->PeakLevel = h;
+ NodeAtLevel[h] = false;
+ *thisarea = node->Area;
+ *thispeaklevel = node->PeakLevel;
+ return(m);
+} /* flood */
+
+
+/***********************************************/
+/* Filtering Functions */
+/***********************************************/
+
+typedef long (*kFunc)(long);
+
+long kflatConstant(long greylevel){
+ return (long) kbase;
+}
+
+long kflatLinear(long greylevel){
+ return (long) (kbase*(double)greylevel/100.0);
+}
+
+
+void MaxTreeProcessNode(MaxTree t, long lambda, long idx, kFunc kf, long maxarea)
+/* Deletes node idx and possible one or more of its parents. */
+{
+ long k,parent, diflevel,newlevel;
+
+ parent = t[idx].Parent;
+
+ diflevel = t[idx].Level - t[parent].Level;
+ newlevel = t[parent].NewLevel + diflevel;
+ k = (*kf)(newlevel);
+ if ((t[idx].PeakLevel - t[parent].Level> k) && (t[idx].Area>=lambda) &&(t[idx].Area<=maxarea)){
+ t[idx].NewLevel = t[parent].NewLevel + diflevel;
+ t[idx].kPrime = k;
+ } else {
+ if (diflevel>t[parent].kPrime){
+ t[idx].NewLevel = t[parent].NewLevel + t[parent].kPrime;
+ t[idx].kPrime = 0;
+ } else {
+ t[idx].NewLevel = t[parent].NewLevel + diflevel;
+ t[idx].kPrime = t[parent].kPrime - diflevel;
+ }
+ }
+
+} /* MaxTreeProcessNode */
+
+void SetPeakLevels(MaxTree t)
+{
+ long i, idx,parent;
+ int h;
+
+ for ( h= NUMLEVELS-1; h>=0;h-- )
+ {
+ for (i=0; i<numbernodes[h]; i++)
+ {
+ idx = NumPixelsBelowLevel[h] + i;
+ parent = t[idx].Parent;
+ if (t[parent].PeakLevel < t[idx].PeakLevel)
+ t[parent].PeakLevel = t[idx].PeakLevel;
+ }
+
+ }
+
+} /* SetPeakLevels */
+
+
+void MaxTreeFilter(greyval *ORI, MaxTree t, long lambda, kFunc k, long maxarea)
+{
+ long i, idx;
+ int h=0;
+
+ SetPeakLevels(t);
+ while (numbernodes[h]==0)
+ h++; /* find root*/
+ /*process root*/
+
+ idx = NumPixelsBelowLevel[h];
+
+ if ((t[idx].Area>=lambda) &&(t[idx].Area<=maxarea)){
+ t[idx].kPrime = (*k)(t[idx].Level);
+
+ t[idx].NewLevel = t[idx].Level;
+ } else {
+ t[idx].kPrime = 0;
+ t[idx].NewLevel = 0;
+ }
+
+ h++;
+
+ while ( h< NUMLEVELS )
+ {
+ for (i=0; i<numbernodes[h]; i++)
+ {
+ idx = NumPixelsBelowLevel[h] + i;
+ MaxTreeProcessNode(t, lambda, idx, k,maxarea);
+ }
+ h++;
+ }
+ /* Modify the output image */
+ for (i=0; i<ImageSize; i++)
+ ORI[i] = ReadPixel(t, STATUS[i], ORI[i]);
+
+} /* MaxTreeFilter */
+
+/* --------------------------------------------------------------- */
+/* Notes : If the attribute threshold lambda is set to a large */
+/* value, the extensive log reports the parent node index */
+/* as a number out of the node index range for that level.*/
+/* That is because although the node level reduces, the */
+/* parents of each child nodes above that are different. */
+/* --------------------------------------------------------------- */
+
+
+
+
+/***********************************************/
+/* Initialisation */
+/***********************************************/
+
+void InitLevels(void)
+{
+ int i;
+
+ for (i=0; i<NUMLEVELS; i++)
+ {
+ numbernodes[i] = 0;
+ NodeAtLevel[i] = false;
+ }
+} /* InitLevels */
+
+
+void CreateLog(MaxTree t,int hmin, char *fname1, char *fname2)
+{
+ FILE *fp;
+ int l,i;
+ long idx,area,level,parent,status, parent_level, parent_node;
+
+ fp = fopen("MaxTreeReport.txt","a");
+ fprintf(fp,"\n--- Start of Session ---\n");
+ fprintf(fp,"Filenames: '%s' - '%s'\n",fname1, fname2);
+ fprintf(fp,"Image Size %d\n",ImageSize);
+ fprintf(fp,"h_min:%d\n",hmin);
+
+ for (l=NUMLEVELS-1; l>=0; l--)
+ {
+ for (i=0; i<numbernodes[l]; i++)
+ {
+ idx = NumPixelsBelowLevel[l] + i;
+ level = t[idx].Level;
+ area = t[idx].Area;
+ parent = t[idx].Parent;
+ /* parent level*/
+ parent_level = t[parent].Level;
+ parent_node = parent - NumPixelsBelowLevel[parent_level];
+ status = t[idx].Status;
+ /*if(status==0)*/
+ fprintf(fp,"level: %d, node: %d, area: %d, parent_level: %d, parent_node: %d, status: %d\n",l,i,area,parent_level,parent_node,status);
+ }
+ }
+ fprintf(fp,"--- End of Session ---\n");
+ fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+ long i, p,plane;
+ long area=0,k=0, maxarea;
+ int peaklevel;
+ long lambda;
+ int hmin;
+ short buffer;
+ struct tms timestruct;
+ clock_t start;
+ long ticksize=sysconf(_SC_CLK_TCK);
+ float museconds;
+
+ if (argc<4)
+ {
+ printf("Usage: %s <original inputimage> <processed input image> <lambda> [k][maxarea]\n", argv[0]);
+ exit(0);
+ }
+ else lambda = atol(argv[3]);
+ FreeImage_Initialise(0);
+
+ ReadPGM(argv[1],buffer=1); /* ORI image buffer */
+ ReadPGM(argv[2],buffer=2); /* P_ORI image buffer */
+ /*printf("\n Read Buffers Ready\n");*/
+ if (argc>4)
+ k=atoi(argv[4]);
+ if (argc>5)
+ maxarea = atoi(argv[5]);
+ else
+ maxarea = ImageSize;
+ if (maxarea<0)
+ maxarea = -(maxarea*ImageSize)/100;
+ /* STATUS keeps track of each pixel's labelling */
+ /*printf("\n Levels initialised\n"); */
+
+ kbase = k;
+
+ /*printf("%f\n",kbase);*/
+ times(×truct);
+ start=timestruct.tms_utime;
+
+ for (plane=0; plane<NumPlanes; plane++){
+
+ STATUS = calloc((size_t)ImageSize, sizeof(long));
+ assert(STATUS!=NULL);
+ for (i=0; i<ImageSize; i++) STATUS[i] = ST_NotAnalyzed;
+ InitLevels();
+ p = FindHMinPixel(ORI[plane],P_ORI[plane]);
+ hmin = P_ORI[plane][p];
+ peaklevel = hmin;
+ NodeAtLevel[hmin] = true;
+ HQueueCreate();
+ /* printf("\n Hierarchical Queues Ready\n");*/
+
+ HQueueAdd(hmin, p);
+ STATUS[p] = ST_InTheQueue;
+ Tree = MaxTreeCreate(ImageSize);
+ assert(Tree!=NULL);
+ printf("\n Max-Tree structure Ready\n");
+
+ flood(ORI[plane],P_ORI[plane],hmin, &area, &peaklevel);
+ printf("\n MaxTree Structure Completed!\n");
+
+ MaxTreeFilter(ORI[plane],Tree, lambda, kflatConstant,maxarea);
+ printf("\n Area Opening Completed!\n");
+
+ /* Generate a log file */
+ CreateLog(Tree,hmin,argv[1],argv[2]);
+
+ free(Tree);
+ free(HQueue->Pixels);
+ free(STATUS);
+ }
+ times(×truct);
+ museconds=1E6*(timestruct.tms_utime-start)/(float) (ticksize);
+ printf ("%8d %10.4f\n", lambda, museconds/1000000);
+
+ WritePGM("out.tif", ImageWidth, ImageHeight, NumPlanes);
+ for(plane=0; plane<NumPlanes; plane++){
+ free(ORI[plane]);
+ free(P_ORI[plane]);
+ }
+ free(ORI);
+ free(P_ORI);
+ FreeImage_DeInitialise();
+ return(0);
+
+} /* main */
+
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/makefile.rules b/milena/sandbox/edwin/TreeAlgorithmsComp/makefile.rules
new file mode 100644
index 0000000..9946526
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/makefile.rules
@@ -0,0 +1 @@
+RELEASE=1
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree.cc
new file mode 100644
index 0000000..95d5dc1
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree.cc
@@ -0,0 +1,232 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/value/int_u8.hh>
+
+#include <mln/data/sort_offsets.hh>
+#include <mln/extension/adjust.hh>
+#include <mln/extension/fill.hh>
+#include <mln/debug/println.hh>
+#include <mln/util/timer.hh>
+
+static mln::util::timer tm;
+static const int ITERATION = 4;
+
+
+#define START_BENCH() \
+ tm.restart(); \
+ for (int i = 0; i < ITERATION; ++i) {
+
+#define END_BENCH() \
+ } \
+ std::cout << ((float)(tm.stop() * 1000.0) / ITERATION) << std::endl;
+
+
+namespace mln
+{
+
+
+ template <typename Z>
+ inline
+ unsigned zfind_root(Z& zpar, unsigned x)
+ {
+ mlc_equal(mln_value(Z), unsigned)::check();
+ if (zpar.element(x) == x)
+ return x;
+ else
+ return zpar.element(x) = zfind_root(zpar, zpar.element(x));
+ }
+
+
+
+// template <typename I>
+// void
+// radix_decreasing_sort(const I& f, util::array<unsigned>& loc, util::array<unsigned>& s)
+// {
+// typedef mln_value(I) T;
+// const unsigned n = unsigned(mln_max(T)) + 1;
+
+// // h
+// util::array<unsigned> h(n, 0);
+// mln_fwd_pixter(const I) pxl(f);
+// for_all(pxl)
+// ++h[pxl.val()];
+
+// // preparing output data
+// util::array<unsigned> loc(n);
+// loc[n-1] = 0;
+// for (int i = n - 2; i >= 0; --i)
+// loc[i] = loc[i+1] + h[i+1];
+// // computing output data
+// s.resize(f.domain().nsites());
+// for_all(pxl)
+// s[ loc[pxl.val()]++ ] = pxl.offset();
+// }
+
+
+
+ template <typename I>
+ void
+ radix_decreasing_sort(const I& f, util::array< util::array<unsigned> >& s)
+ {
+ typedef mln_value(I) T;
+ const unsigned n = unsigned(mln_max(T)) + 1;
+ s.resize(n);
+
+ // h
+ util::array<unsigned> h(n, 0);
+ mln_fwd_pixter(const I) pxl(f);
+ for_all(pxl)
+ ++h[pxl.val()];
+
+ for (unsigned v = 0; v < n; ++v)
+ s[v].reserve(h[v]);
+
+ // computing output data
+ for_all(pxl)
+ s[pxl.val()].append(pxl.offset());
+ }
+
+
+
+ template <typename I, typename N>
+ mln_ch_value(I, unsigned)
+ compute_max_tree(const I& f, const N& nbh,
+ bool run_compression_finalization = true,
+ bool run_tree_canonization = true)
+ {
+ typedef mln_value(I) T;
+ const unsigned n_values = unsigned(mln_max(T)) + 1;
+
+ extension::adjust(f, nbh);
+ extension::fill(f, mln_max(T));
+
+ util::array< util::array<unsigned> > s;
+ radix_decreasing_sort(f, s); // so a max-tree
+
+ util::array<int> dp = offsets_wrt(f, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ mln_ch_value(I, unsigned) parent, zpar;
+
+ // initialization.
+ initialize(parent, f);
+ initialize(zpar, f);
+ data::fill(zpar, 0);
+
+ // Tree construction.
+ for (int v = n_values - 1; v >= 0; --v)
+ {
+
+ const util::array<unsigned>& s_v = s[v];
+ unsigned n_p = s_v.nelements();
+ for (unsigned i = 0; i < n_p; ++i)
+ {
+ unsigned p = s_v[i];
+
+ parent.element(p) = p;
+ zpar.element(p) = p;
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+
+ if (zpar.element(n) == 0) // not deja-vu
+ continue;
+
+ unsigned r = zfind_root(zpar, n);
+ if (r != p)
+ {
+ parent.element(r) = p;
+ zpar.element(r) = p;
+ }
+ }
+ }
+
+ if (run_compression_finalization)
+ // Finalizing compression per gray-level.
+ for (int i = n_p - 1; i >= 0; --i)
+ {
+ unsigned p = s_v[i];
+ zpar.element(p) = zpar.element(zpar.element(p));
+ }
+
+ }
+
+
+ if (run_tree_canonization)
+ // Tree canonization.
+ for (int v = 0; v < n_values; ++v)
+ {
+ const util::array<unsigned>& s_v = s[v];
+ unsigned n_p = s_v.nelements();
+ for (int i = n_p - 1; i >= 0; --i)
+ {
+ unsigned
+ p = s_v[i],
+ q = parent.element(p);
+ if (f.element(parent.element(q)) == f.element(q))
+ parent.element(p) = parent.element(q);
+ }
+ }
+
+ return parent;
+ }
+
+
+ template <typename I, typename J>
+ unsigned nnodes(const I& f, const J& parent)
+ {
+ mlc_equal(mln_value(J), unsigned)::check();
+ unsigned n = 0;
+ mln_piter(I) p(parent.domain());
+ for_all(p)
+ {
+ unsigned o = parent.index_of_point(p);
+ if (parent(p) == o || f.element(parent(p)) != f(p))
+ ++n;
+ }
+ return n;
+ }
+
+
+} // mln
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
+ std::cerr << " max-tree with full optimizations" << std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ usage(argv);
+
+ using namespace mln;
+
+ neighb2d nbh = c4();
+
+ image2d<value::int_u8> f;
+ io::pgm::load(f, argv[1]);
+
+ // go go go
+ image2d<unsigned> parent = compute_max_tree(f, nbh);
+
+ tm.start();
+
+ START_BENCH();
+ compute_max_tree(f, nbh);
+ END_BENCH();
+
+ // debug::println(parent);
+ std::cout << "nnodes = " << nnodes(f, parent) << std::endl;
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree_with_rank.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree_with_rank.cc
new file mode 100644
index 0000000..1e80b12
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/max_tree_with_rank.cc
@@ -0,0 +1,201 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/dump/save.hh>
+
+#include <mln/data/sort_offsets.hh>
+#include <mln/extension/adjust.hh>
+#include <mln/extension/fill.hh>
+
+#include <mln/util/timer.hh>
+#include <mln/debug/println.hh>
+
+
+
+namespace mln
+{
+
+
+ template <typename Z>
+ inline
+ unsigned zfind_root(Z& zpar, unsigned x)
+ {
+ mlc_equal(mln_value(Z), unsigned)::check();
+ if (zpar.element(x) == x)
+ return x;
+ else
+ return zpar.element(x) = zfind_root(zpar, zpar.element(x));
+ }
+
+
+
+ template <typename I>
+ void
+ sort_decreasing(const I& input, std::vector<unsigned>& vec)
+ {
+ const unsigned n = 256;
+
+ // h
+ std::vector<unsigned> h(n, 0);
+ mln_fwd_pixter(const I) pxl(input);
+ for_all(pxl)
+ ++h[pxl.val()];
+
+ // preparing output data
+ std::vector<unsigned> loc(n);
+ loc[n-1] = 0;
+ for (int i = n - 2; i >= 0; --i)
+ loc[i] = loc[i+1] + h[i+1];
+
+ // computing output data
+ for_all(pxl)
+ vec[loc[pxl.val()]++] = pxl.offset();
+ }
+
+
+
+ template <typename I, typename N>
+ mln_ch_value(I, unsigned)
+ compute_max_tree(const I& f, const N& nbh,
+ bool run_tree_canonization = false)
+ {
+ const unsigned npixels = f.domain().nsites();
+
+ extension::adjust(f, nbh);
+ extension::fill(f, 255);
+
+ std::vector<unsigned> s;
+ s.reserve(npixels);
+ sort_decreasing(f, s);
+
+
+ util::array<int> dp = offsets_wrt(f, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ mln_ch_value(I, unsigned) parent, zpar, rnk, last;
+
+ // initialization.
+ initialize(parent, f);
+ initialize(rnk, f);
+ data::fill(rnk, 0);
+ initialize(zpar, f);
+ data::fill(zpar, 0);
+ initialize(last, f);
+
+
+ // Tree construction.
+ for (unsigned i = 0; i < npixels; ++i)
+ {
+ unsigned p = s[i];
+
+ parent.element(p) = p;
+ zpar.element(p) = p;
+ last.element(p) = i;
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+
+ if (zpar.element(n) == 0) // not deja-vu
+ continue;
+
+ unsigned r_ = zfind_root(zpar, n);
+ unsigned p_ = zfind_root(zpar, p);
+ if (r_ != p_)
+ {
+ unsigned r = s[last.element(r_)];
+ parent.element(r) = p;
+
+ // Parenthood goes towards root, e.g., to lower levels:
+ mln_invariant(f.element(p) <= f.element(r));
+
+ // Link.
+ if (rnk.element(r_) <= rnk.element(p_))
+ {
+ zpar.element(r_) = p_;
+ ++rnk.element(p_);
+ if (last.element(r_) > last.element(p_))
+ last.element(p_) = last.element(r_);
+ }
+ else
+ {
+ zpar.element(p_) = r_;
+ ++rnk.element(r_);
+ if (last.element(p_) > last.element(r_))
+ last.element(r_) = last.element(p_);
+ }
+ }
+
+ } // j
+
+ } // i
+
+
+// if (run_tree_canonization)
+// // Tree canonization.
+// for (int i = npixels - 1; i >= 0; --i)
+// {
+// unsigned
+// p = s[i],
+// q = parent.element(p);
+// if (f.element(parent.element(q)) == f.element(q))
+// parent.element(p) = parent.element(q);
+// }
+
+ return parent;
+ }
+
+
+ template <typename I, typename J>
+ unsigned nnodes(const I& f, const J& parent)
+ {
+ mlc_equal(mln_value(J), unsigned)::check();
+ unsigned n = 0;
+ mln_piter(I) p(parent.domain());
+ for_all(p)
+ {
+ unsigned o = parent.index_of_point(p);
+ if (parent(p) == o || f.element(parent(p)) != f(p))
+ ++n;
+ }
+ return n;
+ }
+
+} // mln
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
+ std::cerr << " max-tree with full optimizations" << std::endl;
+ std::abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ usage(argv);
+
+ using namespace mln;
+
+ neighb2d nbh = c4();
+
+ image2d<value::int_u8> f;
+ io::pgm::load(f, argv[1]);
+
+ util::timer t;
+ t.start();
+
+ // go go go
+ image2d<unsigned> parent = compute_max_tree(f, nbh);
+
+ float ts = t.stop();
+ std::cout << ts * 1000 << std::endl;
+
+ std::cout << "nnodes = " << nnodes(f, parent) << std::endl;
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_apply.hh b/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_apply.hh
new file mode 100644
index 0000000..d9a19c1
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_apply.hh
@@ -0,0 +1,89 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 PARALLEL_APPLY_HH
+# define PARALLEL_APPLY_HH
+
+///
+/// Milena concept check for TBB wrapper.
+/// FIXME: it's currently only for 2D images.
+///
+
+
+#include <tbb/blocked_range.h>
+#include <tbb/parallel_reduce.h>
+#include <tbb/partitioner.h>
+
+#include <mln/core/alias/box2d.hh>
+#include <mln/metal/is.hh>
+#include <mln/debug/println.hh>
+
+namespace mln
+{
+
+ template < typename E>
+ struct Parallel_app : Object< E >
+ {
+ Parallel_app();
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename E>
+ inline
+ Parallel_app<E>::Parallel_app()
+ {
+ typedef typename E::domain_t domain_t;
+ mlc_is(domain_t, box2d)::check();
+
+ // // Constructor check
+ // E c(exact(*this), tbb::split ());
+ // (void) c;
+
+ void (E::*m1)(const tbb::blocked_range<int>&) = &E::operator();
+ m1 = 0;
+
+ void (E::*m2)(E&) = &E::join;
+ m2 = 0;
+ }
+
+ template <typename T, typename F>
+ void parallel_apply(const image2d<T>& ima, Parallel_app<F>& fun_)
+ {
+ point2d pmin = ima.domain().pmin();
+ point2d pmax = ima.domain().pmax();
+ F& fun = exact(fun_);
+ tbb::blocked_range<int> r(pmin[0], pmax[0] + 1, 3);
+ std::cout << "Entree" << std::endl;
+
+ tbb::auto_partitioner partitioner;
+ tbb::parallel_reduce(r, fun, partitioner);
+ std::cout << "Sortie" << std::endl;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+}
+
+#endif // !PARALLEL_APPLY_HH
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_union_find.hh b/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_union_find.hh
new file mode 100644
index 0000000..a11253b
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/parallel_union_find.hh
@@ -0,0 +1,394 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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 PARALLEL_UNION_FIND_HH
+# define PARALLEL_UNION_FIND_HH
+
+#include <tbb/tick_count.h>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/data/sort_offsets.hh>
+# include <mln/extension/adjust.hh>
+# include <mln/extension/fill.hh>
+
+# include <sstream>
+# include "parallel_apply.hh"
+
+#define BENCH_START(TASK) \
+ { tbb::tick_count t0 = tbb::tick_count::now(); \
+ std::stringstream task__; \
+ task__ << TASK; \
+ std::cout << "Start task: " << task__.str() << std::endl;
+
+
+#define BENCH_END() \
+ tbb::tick_count t1 = tbb::tick_count::now(); \
+ std::cout << "End task: " << task__.str() << " in " << (t1-t0).seconds() << std::endl; \
+ }
+
+
+
+
+namespace mln
+{
+
+template <typename I, typename N>
+struct ll_union_find : public Parallel_app< ll_union_find<I, N> >
+{
+ typedef mln_domain(I) domain_t;
+
+ ll_union_find(const Image<I>& f, const Neighborhood<N>& nbh,
+ mln_ch_value(I, unsigned)& parent,
+ mln_ch_value(I, unsigned)& zpar);
+
+ ll_union_find(ll_union_find<I, N>&, tbb::split);
+
+ void operator() (const tbb::blocked_range<int>& subrange);
+ void join(ll_union_find<I, N>& o);
+
+ void build(const box2d& subdomain);
+ void merge(const box2d& domain);
+
+private:
+ typedef mln_value(I) T;
+
+ const I& f;
+ const N& nbh;
+ box2d domain;
+public:
+ mln_ch_value(I, unsigned)& parent;
+ mln_ch_value(I, unsigned)& zpar;
+};
+
+ template <typename I, typename N>
+ mln_ch_value(I, unsigned)
+ compute_max_tree(const Image<I>& f_, const Neighborhood<N>& nbh_);
+
+# ifndef MLN_INCLUDE_ONLY
+
+template <typename I, typename N>
+inline
+ll_union_find<I, N>::ll_union_find(const Image<I>& f_, const Neighborhood<N>& nbh_,
+ mln_ch_value(I, unsigned)& parent_,
+ mln_ch_value(I, unsigned)& zpar_)
+ : f (exact(f_)),
+ nbh (exact(nbh_)),
+ parent (parent_),
+ zpar (zpar_)
+{
+ mln_precondition(f.is_valid());
+ mln_precondition(nbh.is_valid());
+ mln_precondition(parent.is_valid());
+ mln_precondition(zpar.is_valid());
+ domain.pmax() = point2d(-1, -1);
+}
+
+template <typename I, typename N>
+inline
+ll_union_find<I, N>::ll_union_find(ll_union_find<I, N>& o, tbb::split) :
+ f (o.f),
+ nbh (o.nbh),
+ parent (o.parent),
+ zpar (o.zpar)
+{
+ mln_precondition(f.is_valid());
+ mln_precondition(nbh.is_valid());
+ mln_precondition(parent.is_valid());
+ mln_precondition(zpar.is_valid());
+}
+
+
+namespace internal
+{
+
+ template <typename Z>
+ inline
+ unsigned zfind_root(Z& zpar, unsigned x)
+ {
+ mlc_equal(mln_value(Z), unsigned)::check();
+ if (zpar.element(x) == x)
+ return x;
+ else
+ return zpar.element(x) = zfind_root(zpar, zpar.element(x));
+ }
+
+ template <typename T>
+ void
+ radix_decreasing_sort(const image2d<T>& f, const box2d& subdomain,
+ util::array< util::array<unsigned> >& s)
+ {
+ const unsigned n = unsigned(mln_max(T)) + 1;
+ s.resize(n);
+
+ // histogram computation
+ util::array<unsigned> h(n, 0);
+
+ // Hack because f | subdomain is not fastest .i.e no pixter
+ const int stride = f.delta_index(dpoint2d(1, 0));
+
+ {
+ const T* offset = &f(subdomain.pmin());
+ for (int y = subdomain.pmin()[0]; y <= subdomain.pmax()[0]; ++y, offset += stride)
+ {
+ const T* pxl = offset;
+ for (int x = subdomain.pmin()[1]; x <= subdomain.pmax()[1]; ++x, ++pxl)
+ ++h[*pxl];
+ }
+ }
+
+ for (unsigned v = 0; v < n; ++v)
+ s[v].reserve(h[v]);
+
+ // computing output data
+ {
+ unsigned offset =
+ (f.border() + subdomain.pmin()[0]) * stride +
+ (f.border() + subdomain.pmin()[1]);
+ assert(offset == f.index_of_point(subdomain.pmin()));
+ for (int y = subdomain.pmin()[0]; y <= subdomain.pmax()[0]; ++y, offset += stride)
+ for (int x = subdomain.pmin()[1], pxl = offset; x <= subdomain.pmax()[1]; ++x, ++pxl)
+ s[f.element(pxl)].append(pxl);
+ }
+ }
+
+ template <typename T>
+ inline
+ void
+ find_node(const image2d<T>& f, image2d<unsigned>& parent, unsigned& x)
+ {
+ unsigned& z = parent.element(x);
+ if (f.element(z) == f.element(x) && z != x)
+ {
+ find_node(f, parent, z);
+ x = z;
+ }
+ }
+
+
+ /// Merge two trees.
+ ///
+ ///
+ /// \param f
+ /// \param parent
+ /// \param x
+ /// \param y
+ ///
+ template <typename T>
+ inline
+ void
+ connect(const image2d<T>& f, image2d<unsigned>& parent,
+ unsigned x, unsigned y)
+ {
+ find_node(f, parent, x);
+ find_node(f, parent, y);
+
+ if (f.element(y) > f.element(x)) // fixme: max tree only
+ std::swap(x, y);
+ while (x != y)
+ if (parent.element(x) == x) // root
+ {
+ parent.element(x) = y;
+ return;
+ }
+ else
+ {
+ unsigned z = parent.element(x);
+ find_node(f, parent, z);
+ if (f.element(z) < f.element(y))
+ {
+ parent.element(x) = y;
+ x = y;
+ y = z;
+ }
+ else
+ x = z;
+ }
+ }
+
+
+}
+
+template <typename I, typename N>
+void
+ll_union_find<I, N>::operator() (const tbb::blocked_range<int>& r)
+{
+ if (!this->domain.is_valid())
+ {
+ this->domain = f.domain();
+ this->domain.pmin()[0] = r.begin();
+ this->domain.pmax()[0] = r.end() - 1;
+ this->build(this->domain);
+ }
+ else
+ {
+ box2d subdomain = f.domain();
+ subdomain.pmin()[0] = r.begin();
+ subdomain.pmax()[0] = r.end() - 1;
+
+ this->build(subdomain);
+ std::cout << "Warning: Not parallel merge. " << std::endl;
+ this->merge(subdomain);
+ this->domain.pmax() = subdomain.pmax();
+ }
+}
+
+
+template <typename I, typename N>
+void
+ll_union_find<I, N>::build(const box2d& subdomain)
+{
+ BENCH_START("Build: " << subdomain)
+
+ mln_precondition(subdomain.is_valid());
+ const unsigned n_values = unsigned(mln_max(T)) + 1;
+
+ util::array<int> dp = offsets_wrt(f, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ util::array< util::array<unsigned> > s;
+ radix_decreasing_sort(f, subdomain, s); // so a max-tree
+
+ const int stride = f.delta_index(dpoint2d(1, 0));
+
+ // Tree construction.
+ for (int v = n_values - 1; v >= 0; --v)
+ {
+ const util::array<unsigned>& s_v = s[v];
+ unsigned n_p = s_v.nelements();
+ for (unsigned i = 0; i < n_p; ++i)
+ {
+ unsigned p = s_v[i];
+ parent.element(p) = p;
+ zpar.element(p) = p;
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (zpar.element(n) == 0) // not deja vu || << 3s a l'exec
+ continue;
+ int col = (n / stride - f.border());
+ if (subdomain.pmin()[0] > col || col > subdomain.pmax()[0]) // !subdomain.has(f.point_at_index(n))
+ continue;
+
+ unsigned r = zfind_root(zpar, n);
+ if (r != p)
+ {
+ parent.element(r) = p;
+ zpar.element(r) = p;
+ }
+ }
+ }
+
+ // Finalizing compression per gray-level.
+ for (int i = n_p - 1; i >= 0; --i)
+ {
+ unsigned p = s_v[i];
+ zpar.element(p) = zpar.element(zpar.element(p));
+ }
+ }
+ BENCH_END()
+}
+
+
+template <typename I, typename N>
+void
+ll_union_find<I, N>::merge(const box2d& d2)
+{
+ const int stride = f.delta_index(dpoint2d(1, 0));
+ box2d& d1 = this->domain;
+
+ BENCH_START("Merge: " << d1 << "&" << d2)
+
+ // Split along x axis
+ assert(d1.pmin()[1] == d2.pmin()[1]);
+ assert(d1.pmax()[1] == d2.pmax()[1]);
+ assert((d1.pmax()[0] + 1) == d2.pmin()[0]);
+
+ int x2 = f.index_of_point(d2.pmin());
+ int x1 = x2;
+ x1 -= stride;
+ for (int x = d1.pmin()[1]; x <= d1.pmax()[1]; ++x)
+ {
+ internal::connect(f, parent, x1, x2);
+ ++x1;
+ ++x2;
+ }
+
+ BENCH_END()
+}
+
+/// Merge two trees.
+///
+///
+template <typename I, typename N>
+void
+ll_union_find<I, N>::join(ll_union_find& o)
+{
+ this->merge(o.domain);
+ this->domain.pmax() = o.domain.pmax();
+}
+
+ template <typename I, typename N>
+ mln_ch_value(I, unsigned)
+ compute_max_tree(const Image<I>& f_, const Neighborhood<N>& nbh_)
+ {
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(f.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ extension::adjust(f, nbh);
+ extension::fill(f, mln_max(mln_value(I)));
+
+ typedef mln_ch_value(I, unsigned) P;
+ P parent, zpar;
+ BENCH_START("Compute Max Tree");
+ initialize(zpar, f);
+ initialize(parent, f);
+ data::fill(zpar, 0);
+ //data::fill(parent, 69);
+
+ ll_union_find<I, N> fun(f, nbh, parent, zpar);
+ parallel_apply(f, fun);
+
+ BENCH_START("Canonisation");
+ mln_pixter(P) px(parent);
+ for_all(px)
+ {
+ unsigned q = parent.element(px.val());
+ if (f.element(q) == f.element(px.val()))
+ px.val() = q;
+ }
+ BENCH_END();
+
+ BENCH_END()
+ return parent;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#endif // !PARALLEL_UNION_FIND_HH
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/tbb_union_find_8.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/tbb_union_find_8.cc
new file mode 100644
index 0000000..4de9132
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/tbb_union_find_8.cc
@@ -0,0 +1,59 @@
+#include <tbb/task_scheduler_init.h>
+#include "parallel_union_find.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>
+#include <mln/debug/println.hh>
+
+ namespace mln
+ {
+
+ template <typename I, typename J>
+ unsigned nnodes(const I& f, const J& parent)
+ {
+ mlc_equal(mln_value(J), unsigned)::check();
+ unsigned n = 0;
+ mln_piter(I) p(parent.domain());
+ for_all(p)
+ {
+ unsigned o = parent.index_of_point(p);
+ if (parent(p) == o || f.element(parent(p)) != f(p))
+ ++n;
+ }
+ return n;
+ }
+
+ }
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm" << std::endl;
+ std::cerr << " max-tree parallel" << std::endl;
+ std::abort();
+}
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ usage(argv);
+
+ tbb::task_scheduler_init init;
+ using namespace mln;
+
+ neighb2d nbh = c4();
+ image2d<value::int_u8> f;
+ io::pgm::load(f, argv[1]);
+
+ image2d<unsigned> parent = compute_max_tree(f, nbh);
+ // debug::println(parent);
+
+ // tm.start();
+ // START_BENCH(1);
+ // //compute_max_tree(f, nbh);
+ // END_BENCH();
+ std::cout << "nnodes = " << nnodes(f, parent) << std::endl;
+}
+
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc
new file mode 100644
index 0000000..0999f20
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_16.cc
@@ -0,0 +1,62 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/morpho/tree/component_tree.hh>
+
+
+static mln::util::timer tm;
+
+#define START_BENCH(N_ITERATION) \
+ { \
+ tm.restart(); \
+ const int n_iteration__ = N_ITERATION; \
+ for (int i__ = 0; i__ < n_iteration__; ++i__) {
+
+
+#define END_BENCH(MSG) \
+ } \
+ std::cout << MSG \
+ << ((float)(tm.stop()) * 1000.0 / n_iteration__) \
+ << " ms." << std::endl; \
+ }
+
+
+void usage(char** argv)
+{
+ std::cout << "Usage: " << argv[0] << " image" << std::endl;
+ abort();
+}
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ typedef value::int_u16 V;
+ typedef image2d<V> I;
+ typedef util::ctree::ctree<I> tree_t;
+ typedef neighb2d N;
+
+ I input;
+ N nbh = c4();
+
+ if (argc < 2)
+ usage(argv);
+
+ const char* finput = argv[1];
+
+ tm.start();
+ io::pgm::load(input, finput);
+
+ trace::quiet = false;
+ tree_t tree =
+ morpho::tree::impl::hqueue_fast(tag::tree::max, input, nbh);
+ trace::quiet = true;
+
+ std::cout << "Number of nodes: " << tree.n_nodes() << std::endl;
+
+ START_BENCH(10);
+ morpho::tree::impl::hqueue_fast(tag::tree::max, input, nbh);
+ END_BENCH("Salembier fast 16 bits: ");
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc
new file mode 100644
index 0000000..4bbcfc5
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/test_salembier_fast_8.cc
@@ -0,0 +1,62 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/morpho/tree/component_tree.hh>
+
+
+static mln::util::timer tm;
+
+#define START_BENCH(N_ITERATION) \
+ { \
+ tm.restart(); \
+ const int n_iteration__ = N_ITERATION; \
+ for (int i__ = 0; i__ < n_iteration__; ++i__) {
+
+
+#define END_BENCH(MSG) \
+ } \
+ std::cout << MSG \
+ << ((float)(tm.stop()) * 1000.0 / n_iteration__) \
+ << " ms." << std::endl; \
+ }
+
+
+void usage(char** argv)
+{
+ std::cout << "Usage: " << argv[0] << " image" << std::endl;
+ abort();
+}
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ typedef value::int_u8 V;
+ typedef image2d<V> I;
+ typedef util::ctree::ctree<I> tree_t;
+ typedef neighb2d N;
+
+ I input;
+ N nbh = c4();
+
+ if (argc < 2)
+ usage(argv);
+
+ const char* finput = argv[1];
+
+ tm.start();
+ io::pgm::load(input, finput);
+
+ trace::quiet = false;
+ tree_t tree =
+ morpho::tree::impl::hqueue_fast(tag::tree::max, input, nbh);
+ trace::quiet = true;
+
+ std::cout << "Number of nodes: " << tree.n_nodes() << std::endl;
+
+ START_BENCH(10);
+ morpho::tree::impl::hqueue_fast(tag::tree::max, input, nbh);
+ END_BENCH("Salembier fast 8bits: ");
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc
new file mode 100644
index 0000000..f084650
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_16.cc
@@ -0,0 +1,62 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/morpho/tree/component_tree.hh>
+
+
+static mln::util::timer tm;
+
+#define START_BENCH(N_ITERATION) \
+ { \
+ tm.restart(); \
+ const int n_iteration__ = N_ITERATION; \
+ for (int i__ = 0; i__ < n_iteration__; ++i__) {
+
+
+#define END_BENCH(MSG) \
+ } \
+ std::cout << MSG \
+ << ((float)(tm.stop()) * 1000.0 / n_iteration__) \
+ << " ms" << std::endl; \
+ }
+
+
+void usage(char** argv)
+{
+ std::cout << "Usage: " << argv[0] << " image" << std::endl;
+ abort();
+}
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ typedef value::int_u16 V;
+ typedef image2d<V> I;
+ typedef util::ctree::ctree<I> tree_t;
+ typedef neighb2d N;
+
+ I input;
+ N nbh = c4();
+
+ if (argc < 2)
+ usage(argv);
+
+ const char* finput = argv[1];
+
+ tm.start();
+ io::pgm::load(input, finput);
+
+ trace::quiet = false;
+ tree_t tree =
+ morpho::tree::impl::generic::union_find_fast(tag::tree::max, input, nbh);
+ trace::quiet = true;
+
+ std::cout << "Number of nodes: " << tree.n_nodes() << std::endl;
+
+ START_BENCH(10);
+ morpho::tree::impl::generic::union_find_fast(tag::tree::max, input, nbh);
+ END_BENCH("Union find fast 16bits: ");
+}
diff --git a/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc b/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc
new file mode 100644
index 0000000..150701f
--- /dev/null
+++ b/milena/sandbox/edwin/TreeAlgorithmsComp/test_union_find_fast_8.cc
@@ -0,0 +1,62 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/util/timer.hh>
+
+#include <mln/morpho/tree/component_tree.hh>
+
+
+static mln::util::timer tm;
+
+#define START_BENCH(N_ITERATION) \
+ { \
+ tm.restart(); \
+ const int n_iteration__ = N_ITERATION; \
+ for (int i__ = 0; i__ < n_iteration__; ++i__) {
+
+
+#define END_BENCH(MSG) \
+ } \
+ std::cout << MSG \
+ << ((float)(tm.stop()) * 1000.0 / n_iteration__) \
+ << " ms" << std::endl; \
+ }
+
+
+void usage(char** argv)
+{
+ std::cout << "Usage: " << argv[0] << " image" << std::endl;
+ abort();
+}
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ typedef value::int_u8 V;
+ typedef image2d<V> I;
+ typedef util::ctree::ctree<I> tree_t;
+ typedef neighb2d N;
+
+ I input;
+ N nbh = c4();
+
+ if (argc < 2)
+ usage(argv);
+
+ const char* finput = argv[1];
+
+ tm.start();
+ io::pgm::load(input, finput);
+
+ trace::quiet = false;
+ tree_t tree =
+ morpho::tree::impl::generic::union_find_fast(tag::tree::max, input, nbh);
+ trace::quiet = true;
+
+ std::cout << "Number of nodes: " << tree.n_nodes() << std::endl;
+
+ START_BENCH(10);
+ morpho::tree::impl::generic::union_find_fast(tag::tree::max, input, nbh);
+ END_BENCH("Union find fast 8 bits: ");
+}
--
1.5.6.5
1
0
04 May '10
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Olena, a generic and efficient image processing platform".
The branch exp/scribo-z has been updated
via 7b922a208b3587cd49009a40570556a7489e6d67 (commit)
via f97f87ab21572b65556b8ce6ad3e85e45bdade54 (commit)
from 3d900b511f6ae7a69e94fca37496b08001a5af26 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
7b922a2 Small fixes for Nuxeo/XWiki.
f97f87a text/merging.hh: Disable some debug.
-----------------------------------------------------------------------
Summary of changes:
scribo/ChangeLog | 30 +++++++++++++++++++++++-------
scribo/core/line_set.hh | 3 +++
scribo/src/text_in_article_preprocess.cc | 2 +-
scribo/text/clean.hh | 2 ++
scribo/text/merging.hh | 17 ++++++++++-------
scribo/text/recognition.hh | 20 ++++++++++++++++++--
6 files changed, 57 insertions(+), 17 deletions(-)
hooks/post-receive
--
Olena, a generic and efficient image processing platform
1
0
04 May '10
* src/text_in_article_preprocess.cc: Fix use of program
arguments.
* core/line_set.hh,
* text/clean.hh,
* text/merging.hh: Fix compilation.
* text/recognition.hh: Update output format.
---
scribo/ChangeLog | 13 +++++++++++++
scribo/core/line_set.hh | 3 +++
scribo/src/text_in_article_preprocess.cc | 2 +-
scribo/text/clean.hh | 2 ++
scribo/text/merging.hh | 15 +++++++++------
scribo/text/recognition.hh | 20 ++++++++++++++++++--
6 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 67159ad..e44137e 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,5 +1,18 @@
2010-05-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Small fixes for Nuxeo/XWiki.
+
+ * src/text_in_article_preprocess.cc: Fix use of program
+ arguments.
+
+ * core/line_set.hh,
+ * text/clean.hh,
+ * text/merging.hh: Fix compilation.
+
+ * text/recognition.hh: Update output format.
+
+2010-05-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* text/merging.hh: Disable some debug.
2010-05-04 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/core/line_set.hh b/scribo/core/line_set.hh
index 80a79b3..5dca629 100644
--- a/scribo/core/line_set.hh
+++ b/scribo/core/line_set.hh
@@ -57,8 +57,11 @@ namespace scribo
// Forward declaration.
template <typename L> struct line_set;
+ template <typename L> struct line_info;
+ typedef mln::util::object_id<scribo::LineId, unsigned> line_id_t;
+
namespace internal
{
/// Data structure for \c scribo::line_set<I>.
diff --git a/scribo/src/text_in_article_preprocess.cc b/scribo/src/text_in_article_preprocess.cc
index 8cfa82f..bf70c7f 100644
--- a/scribo/src/text_in_article_preprocess.cc
+++ b/scribo/src/text_in_article_preprocess.cc
@@ -75,7 +75,7 @@ int main(int argc, char* argv[])
lambda = 1.2 * (input_rgb.nrows() + input_rgb.ncols());
// Extract foreground
- if (argc == 4 && atoi(argv[3]) == 1)
+ if (argc >= 4 && atoi(argv[3]) == 1)
{
std::cout << "Extracting foreground..." << std::endl;
input_rgb = preprocessing::split_bg_fg(input_rgb, lambda, 32).second();
diff --git a/scribo/text/clean.hh b/scribo/text/clean.hh
index f93bc6f..341d64c 100644
--- a/scribo/text/clean.hh
+++ b/scribo/text/clean.hh
@@ -31,6 +31,7 @@
///
/// Improve the quality of a text area.
+# include <mln/core/concept/image.hh>
# include <mln/core/concept/weighted_window.hh>
# include <mln/core/routine/extend.hh>
@@ -65,6 +66,7 @@
#include <mln/value/rgb8.hh>
#include <mln/io/pgm/all.hh>
+#include <scribo/core/line_info.hh>
#include <scribo/upsampling/bs2x.hh>
#include <scribo/subsampling/bilinear.hh>
diff --git a/scribo/text/merging.hh b/scribo/text/merging.hh
index 5309b10..7e943ef 100644
--- a/scribo/text/merging.hh
+++ b/scribo/text/merging.hh
@@ -59,12 +59,15 @@
+
namespace scribo
{
namespace text
{
+ using namespace mln;
+
/// \brief Merge text component in order to reconstruct text lines.
///
@@ -161,7 +164,7 @@ namespace scribo
- unsigned my_find_root(util::array<unsigned>& parent, unsigned x)
+ unsigned my_find_root(mln::util::array<unsigned>& parent, unsigned x)
{
if (parent[x] == x)
return x;
@@ -184,7 +187,7 @@ namespace scribo
unsigned do_union(scribo::line_set<L>& lines,
unsigned l1,
unsigned l2,
- util::array<unsigned>& parent)
+ mln::util::array<unsigned>& parent)
{
l1 = my_find_root(parent, l1);
l2 = my_find_root(parent, l2);
@@ -514,7 +517,7 @@ namespace scribo
const box2d& domain,
std::vector<scribo::line_id_t>& v,
scribo::line_set<L>& lines,
- util::array<unsigned>& parent)
+ mln::util::array<unsigned>& parent)
{
image2d<unsigned> billboard(domain);
data::fill(billboard, 0);
@@ -852,7 +855,7 @@ namespace scribo
v.reserve(n);
// Union-find parent data, used to merge lines.
- util::array<unsigned> parent(n + 1);
+ mln::util::array<unsigned> parent(n + 1);
// Initialize data
parent(0) = 0;
@@ -865,7 +868,7 @@ namespace scribo
// Sort lines by bbox.nelements() and ids.
std::sort(v.begin(), v.end(), func);
- util::timer t;
+ mln::util::timer t;
// Setting lines as text lines according to specific criterions.
@@ -912,7 +915,7 @@ namespace scribo
{
using namespace mln;
- util::timer t;
+ mln::util::timer t;
t.start();
scribo::line_set<L> output
diff --git a/scribo/text/recognition.hh b/scribo/text/recognition.hh
index 6f9dac7..fcc83dd 100644
--- a/scribo/text/recognition.hh
+++ b/scribo/text/recognition.hh
@@ -185,7 +185,15 @@ namespace scribo
{
std::string str(s);
str = str.substr(0, str.length() - 1);
- file << lines(i).bbox() << " " << str;
+ file << lines(i).bbox().pmin().row()
+ << " "
+ << lines(i).bbox().pmin().col()
+ << " "
+ << lines(i).bbox().pmax().row()
+ << " "
+ << lines(i).bbox().pmax().col()
+ << " "
+ << str;
}
}
@@ -248,7 +256,15 @@ namespace scribo
{
std::string str(s);
str = str.substr(0, str.length() - 1);
- file << line.domain() << " " << str;
+ file << line.domain().bbox().pmin().row()
+ << " "
+ << line.domain().bbox().pmin().col()
+ << " "
+ << line.domain().bbox().pmax().row()
+ << " "
+ << line.domain().bbox().pmax().col()
+ << " "
+ << str;
}
}
--
1.5.6.5
1
0
last-svn-commit-2-g70d045f Tree build algorithms and tree management routines
by edwin carlinet 04 May '10
by edwin carlinet 04 May '10
04 May '10
* mln/core/image/all.hh: Update.
* mln/morpho/tree/all.hh: Update.
* mln/tag/skeleton.hh: Update.
* mln/morpho/tree/component_tree.hh:
Routines to build component trees.
* mln/morpho/tree/compute_attribute_image.hh:
Routines to compute attribute images.
* mln/morpho/tree/dual_input_tree.hh:
Routines to build dual-input trees.
* mln/morpho/tree/filter/direct.hh,
* mln/morpho/tree/filter/max.hh,
* mln/morpho/tree/filter/min.hh,
* mln/morpho/tree/filter/subtractive.hh:
Filtering routines.
* mln/morpho/tree/impl/hqueue.hh,
* mln/morpho/tree/impl/hqueue_fast.hh,
* mln/morpho/tree/impl/union_find.hh,
* mln/morpho/tree/impl/union_find_fast.hh:
Tree computation algorithms.
* mln/morpho/tree/leaf_last.hh,
* mln/morpho/tree/propagate_node.hh:
Tree management routines.
---
milena/mln/core/image/all.hh | 1 +
milena/mln/morpho/tree/all.hh | 16 +-
milena/mln/morpho/tree/component_tree.hh | 86 +++-
milena/mln/morpho/tree/compute_attribute_image.hh | 281 ++++------
milena/mln/morpho/tree/dual_input_tree.hh | 79 +---
milena/mln/morpho/tree/filter/direct.hh | 35 +-
milena/mln/morpho/tree/filter/max.hh | 62 ++-
milena/mln/morpho/tree/filter/min.hh | 59 ++-
milena/mln/morpho/tree/filter/subtractive.hh | 52 ++-
milena/mln/morpho/tree/impl/dual_hqueue.hh | 604 ++++++++++++--------
milena/mln/morpho/tree/impl/hqueue.hh | 428 ++++++++++++++
milena/mln/morpho/tree/impl/hqueue_fast.hh | 391 +++++++++++++
.../edwin => }/mln/morpho/tree/impl/union_find.hh | 2 +
milena/mln/morpho/tree/impl/union_find_fast.hh | 396 +++++++++++++
milena/mln/morpho/tree/leaf_last.hh | 111 ++++
milena/mln/morpho/tree/propagate_node.hh | 189 ++-----
milena/mln/tag/skeleton.hh | 1 +
milena/mln/util/hqueues.hh | 32 +-
18 files changed, 2050 insertions(+), 775 deletions(-)
create mode 100644 milena/mln/morpho/tree/impl/hqueue.hh
create mode 100644 milena/mln/morpho/tree/impl/hqueue_fast.hh
copy milena/{sandbox/edwin => }/mln/morpho/tree/impl/union_find.hh (99%)
create mode 100644 milena/mln/morpho/tree/impl/union_find_fast.hh
create mode 100644 milena/mln/morpho/tree/leaf_last.hh
diff --git a/milena/mln/core/image/all.hh b/milena/mln/core/image/all.hh
index ee6a15e..1cd2773 100644
--- a/milena/mln/core/image/all.hh
+++ b/milena/mln/core/image/all.hh
@@ -40,6 +40,7 @@
// Files.
+# include <mln/core/image/attribute_image.hh>
# include <mln/core/image/ch_piter.hh>
# include <mln/core/image/complex_image.hh>
# include <mln/core/image/complex_neighborhood_piter.hh>
diff --git a/milena/mln/morpho/tree/all.hh b/milena/mln/morpho/tree/all.hh
index d088ea0..c6d93ee 100644
--- a/milena/mln/morpho/tree/all.hh
+++ b/milena/mln/morpho/tree/all.hh
@@ -30,7 +30,6 @@
///
/// File that includes all morphological tree-related routines.
-
namespace mln
{
@@ -46,11 +45,14 @@ namespace mln
} // end of namespace mln
-# include <mln/morpho/tree/compute_attribute_image.hh>
-# include <mln/morpho/tree/compute_parent.hh>
# include <mln/morpho/tree/dual_input_tree.hh>
-# include <mln/morpho/tree/data.hh>
-# include <mln/morpho/tree/max.hh>
-# include <mln/morpho/tree/utils.hh>
+# include <mln/morpho/tree/component_tree.hh>
+# include <mln/morpho/tree/compute_parent.hh
+# include <mln/morpho/tree/compute_attribute_image.hh>
+# include <mln/morpho/tree/leaf_last.hh>
+# include <mln/morpho/tree/propagate_node.hh>
+
+# include <mln/morpho/tree/filter/all.hh>
+
-#endif // ! MLN_MORPHO_TREE_ALL_HH
+#endif // !MLN_MORPHO_TREE_ALL_HH
diff --git a/milena/mln/morpho/tree/component_tree.hh b/milena/mln/morpho/tree/component_tree.hh
index f45986d..dc9063d 100644
--- a/milena/mln/morpho/tree/component_tree.hh
+++ b/milena/mln/morpho/tree/component_tree.hh
@@ -32,8 +32,10 @@
#ifndef MLN_MORPHO_TREE_COMPONENT_TREE_HH
# define MLN_MORPHO_TREE_COMPONENT_TREE_HH
-# include <mln/data/sort_psites.hh>
-# include <mln/morpho/tree/data.hh>
+# include <mln/tag/tree.hh>
+# include <mln/util/ctree/ctree.hh>
+# include <mln/morpho/tree/impl/union_find_fast.hh>
+# include <mln/morpho/tree/impl/hqueue_fast.hh>
namespace mln
{
@@ -53,7 +55,7 @@ namespace mln
///
template <typename I, typename N>
inline
- data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
min_tree(const Image<I>& f, const Neighborhood<N>& nbh);
/// Compute a canonized max-tree.
@@ -65,15 +67,73 @@ namespace mln
///
template <typename I, typename N>
inline
- data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
max_tree(const Image<I>& f, const Neighborhood<N>& nbh);
# ifndef MLN_INCLUDE_ONLY
+ namespace internal
+ {
+
+ template <typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ max_tree_dispatch(trait::image::quant::any,
+ const I& f,
+ const N& nbh)
+ {
+ util::ctree::ctree<I> tree =
+ morpho::tree::impl::generic::union_find_fast(tag::tree::max, f, nbh);
+
+ return tree;
+ }
+
+ template <typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ min_tree_dispatch(trait::image::quant::any,
+ const I& f,
+ const N& nbh)
+ {
+ util::ctree::ctree<I> tree =
+ morpho::tree::impl::generic::union_find_fast(tag::tree::min, f, nbh);
+
+ return tree;
+ }
+
+
+ template <typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ max_tree_dispatch(trait::image::quant::low,
+ const I& f,
+ const N& nbh)
+ {
+ util::ctree::ctree<I> tree =
+ morpho::tree::impl::hqueue_fast(tag::tree::max, f, nbh);
+
+ return tree;
+ }
+
+ template <typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ min_tree_dispatch(trait::image::quant::low,
+ const I& f,
+ const N& nbh)
+ {
+ util::ctree::ctree<I> tree =
+ morpho::tree::impl::hqueue_fast(tag::tree::min, f, nbh);
+
+ return tree;
+ }
+
+ }
+
template <typename I, typename N>
inline
- data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
min_tree(const Image<I>& f_, const Neighborhood<N>& nbh_)
{
trace::entering("morpho::tree::min_tree");
@@ -84,11 +144,8 @@ namespace mln
mln_precondition(f.is_valid());
mln_precondition(nbh.is_valid());
- typedef p_array<mln_psite(I)> S;
- typedef data<I,S> tree_t;
-
- S s = mln::data::sort_psites_decreasing(f);
- tree_t tree(f, s, nbh);
+ util::ctree::ctree<I> tree =
+ internal::min_tree_dispatch(mln_trait_image_quant(I)(), f, nbh);
trace::exiting("morpho::tree::min_tree");
return tree;
@@ -96,7 +153,7 @@ namespace mln
template <typename I, typename N>
inline
- data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
max_tree(const Image<I>& f_, const Neighborhood<N>& nbh_)
{
trace::entering("morpho::tree::max_tree");
@@ -107,11 +164,8 @@ namespace mln
mln_precondition(f.is_valid());
mln_precondition(nbh.is_valid());
- typedef p_array<mln_psite(I)> S;
- typedef data<I,S> tree_t;
-
- S s = mln::data::sort_psites_increasing(f);
- tree_t tree(f, s, nbh);
+ util::ctree::ctree<I> tree =
+ internal::max_tree_dispatch(mln_trait_image_quant(I)(), f, nbh);
trace::exiting("morpho::tree::max_tree");
return tree;
diff --git a/milena/mln/morpho/tree/compute_attribute_image.hh b/milena/mln/morpho/tree/compute_attribute_image.hh
index 9126bf1..6e5e891 100644
--- a/milena/mln/morpho/tree/compute_attribute_image.hh
+++ b/milena/mln/morpho/tree/compute_attribute_image.hh
@@ -23,22 +23,20 @@
// 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_ATTRIBUTE_IMAGE_HH
-# define MLN_MORPHO_TREE_COMPUTE_ATTRIBUTE_IMAGE_HH
-
-/// \file
+#ifndef COMPUTE_ATTRIBUTE_IMAGE_HH
+# define COMPUTE_ATTRIBUTE_IMAGE_HH
+///
+///
+/// \brief Compute an attribute on a morphological tree.
///
-/// Compute a canonized tree from an image.
+/// \todo Specialize for fast image.
///
-/// \todo Specialize for low quant (and try fastest).
-# include <mln/core/routine/duplicate.hh>
-# include <mln/core/concept/image.hh>
-# include <mln/morpho/tree/data.hh>
-# include <mln/trait/accumulators.hh>
-# include <mln/util/pix.hh>
-# include <mln/data/fill.hh>
+# include <mln/core/concept/tree.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <mln/data/fill.hh>
namespace mln
{
@@ -49,213 +47,132 @@ namespace mln
namespace tree
{
- /**
- ** Compute an attribute image using tree with a parent
- ** relationship between sites. In the attribute image, the
- ** resulting value at a node is the 'sum' of its sub-components
- ** value + the attribute value at this node.
- **
- ** Warning: \p s translates the ordering related to the
- ** "natural" childhood relationship. The parenthood is thus
- ** inverted w.r.t. to \p s.
- **
- ** It is very convenient since all processing upon the parent
- ** tree are performed following \p s (in the default "forward"
- ** way).
- **
- ** FIXME: Put it more clearly...
- **
- ** The parent result image verifies: \n
- ** - p is root iff parent(p) == p \n
- ** - p is a node iff either p is root or f(parent(p)) != f(p).
- **
- ** \param[in] a Attribute.
- ** \param[in] t Component tree.
- ** \param[out] accu_image Optional argument used to store image
- ** of attribute accumulator.
- **
- ** \return The attribute image.
- */
- template <typename A, typename T>
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_image(const Accumulator<A>& a,
- const T& t,
- mln_ch_value(typename T::function, A)* accu_image = 0);
-
-
-
- /** The same as compute_attribute_image but uses the values
- ** stored by \p values image instead.
- **
- ** \param[in] a Attribute.
- ** \param[in] t Component tree.
- ** \param[in] values Value image.
- ** \param[out] accu_image Optional argument used to store image.
- **
- ** \return
- */
- template <typename A, typename T, typename V>
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_image_from(const Accumulator<A>& a,
- const T& t,
- const Image<V>& values,
- mln_ch_value(typename T::function, A)* accu_image = 0);
-
+ template <typename T, typename A>
+ attribute_image<T, mln_result(A)>
+ compute_attribute_image(const Tree<T>& tree,
+ const Accumulator<A>& accu);
# ifndef MLN_INCLUDE_ONLY
- // Take_as_init specialization
namespace internal
{
- template <typename A, typename I, typename P>
- void take_as_init (trait::accumulator::when_pix::use_none, A& accu,
- const I& input, const P& p)
- {
- (void)input;
- (void)p;
- accu.take_as_init();
- }
- template <typename A, typename I, typename P>
- void take_as_init (trait::accumulator::when_pix::use_pix, A& accu,
- const I& input, const P& p)
+ template <typename T, typename A>
+ inline
+ void
+ take_as_init(trait::accumulator::when_pix::use_none,
+ const T&, A& accu,
+ const mln_psite(T)&)
{
- accu.take_as_init(make::pix(input, p));
+ accu.take();
}
- template <typename A, typename I, typename P>
- void take_as_init (trait::accumulator::when_pix::use_v, A& accu,
- const I& input, const P& p)
+ template <typename T, typename A>
+ inline
+ void
+ take_as_init(trait::accumulator::when_pix::use_pix,
+ const T& tree, A& accu,
+ const mln_psite(T)& p)
{
- accu.take_as_init(input(p));
+ accu.take(make::pix(p, tree.f(p)));
}
- template <typename A, typename I, typename P>
- void take_as_init (trait::accumulator::when_pix::use_p, A& accu,
- const I& input, const P& p)
+
+ template <typename T, typename A>
+ inline
+ void
+ take_as_init(trait::accumulator::when_pix::use_v,
+ const T& tree, A& accu,
+ const mln_psite(T)& p)
{
- (void) input;
- accu.take_as_init(p);
+ accu.take(tree.f(p));
}
-
- template <typename A, typename I, typename P>
- void take_as_init (A& accu, const I& input, const P& p)
+ template <typename T, typename A>
+ inline
+ void
+ take_as_init(trait::accumulator::when_pix::use_p,
+ const T&, A& accu,
+ const mln_psite(T)& p)
{
- take_as_init (mln_trait_accumulator_when_pix(A)(), accu, input, p);
+ accu.take(p);
}
-
- template <typename A, typename T, typename V>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_image(const A& a,
- const T& t,
- const V& values,
- mln_ch_value(typename T::function, A)* accu_image = 0)
+ template <typename T, typename A>
+ void
+ take_as_init(const T& tree, A& a, const mln_psite(T)& p)
{
+ take_as_init(mln_trait_accumulator_when_pix(A)(), tree, a, p);
+ }
- typedef typename T::function I;
- mln_ch_value(I, A) acc;
- initialize(acc, t.f());
+ } // end of namespace namespace mln::morpho::tree::internal
- {
- // Transmit "dynamic data" (state) of 'a' to every values of
- // 'acc'. It is usually a no-op (so useless) except for a
- // few accumulators, e.g., for accu::stat::rank which has the 'k'
- // attribute.
- mln::data::fill(acc, a);
- }
+ namespace impl
+ {
- {
- // Initialize every attribute with the corresponding pixel.
- mln_site_piter(T) p(t);
- for_all(p)
- take_as_init(acc(p), values, p);
- }
+ namespace generic
+ {
+ template <typename T, typename A>
+ attribute_image<T, mln_result(A)>
+ compute_attribute_image(const T& tree, const A& accu, attribute_image<T, A>* accu_img = 0)
{
- mln_up_site_piter(T) p(t);
- // Propagate attribute from a site to its parent.
- for_all(p)
- if (! t.is_root(p))
- acc(t.parent(p)).take(acc(p));
-
- // Back-propagate attribute from a node to sites of its
- // component. Below, p is a non-node component site and
- // parent(p) is a node, that is, the site representative of
- // the component p belongs to.
- for_all(p)
- if (! t.is_a_node(p))
- {
- mln_assertion(t.is_a_node(t.parent(p)));
- acc(p) = acc(t.parent(p));
- }
+ typedef attribute_image<T, A> I;
+ attribute_image<T, A> a(tree);
+ (void) accu_img;
+
+ // Transmit dynamic data of accumulator (ex: rank filter).
+ data::fill(a, accu);
+
+ // Initialize. Each node takes its content.
+ {
+ mln_fwd_piter(T::domain_t) p(tree.domain());
+ for_all(p)
+ internal::take_as_init(tree, a.element(tree.node_at_(p)), p);
+ }
+
+ // Transmit to parent.
+ for (unsigned i = tree.n_nodes() - 1; i > 0; --i)
+ {
+ unsigned q = tree.parent_at_(i);
+ if (q != i) // The current node is not a root.
+ a.element(q).take(a.element(i));
+ }
+
+ attribute_image<T, mln_result(A)> out(tree);
+ for (int i = 0; i < tree.n_nodes(); i++)
+ out.element(i) = a.element(i).to_result();
+
+ return out;
}
+ } // end of namespace mln::morpho::tree::impl::generic
- // Store accumulator image.
- if (accu_image)
- *accu_image = duplicate(acc);
-
- typedef typename T::function I;
- mln_ch_value(I, mln_result(A)) output;
- initialize(output, acc);
- mln::data::fill(output, acc);
-
- return output;
- }
- }
-
- // Facade.
-
- template <typename A, typename T>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_image(const Accumulator<A>& a_,
- const T& t,
- mln_ch_value(typename T::function, A)* accu_image = 0)
- {
- trace::entering("morpho::tree::compute_attribute_image");
+ } // end of namespace mln::morpho::tree::impl
- mln_ch_value(typename T::function, mln_result(A)) output;
- output = internal::compute_attribute_image(exact(a_), t, t.f(),
- accu_image);
- trace::exiting("morpho::tree::compute_attribute_image");
- return (output);
- }
-
- template <typename A, typename T, typename V>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_image_from(const Accumulator<A>& a_,
- const T& t,
- const Image<V>& values,
- mln_ch_value(typename T::function, A)* accu_image = 0)
+ // Facades
+ template <typename T, typename A>
+ attribute_image<T, mln_result(A)>
+ compute_attribute_image(const Tree<T>& tree_, const Accumulator<A>& acc)
{
- trace::entering("morpho::tree::compute_attribute_image_from");
-
+ trace::entering("mln::morpho::tree::compute_attribute_image");
+ const T& tree = exact(tree_);
+ const A& accu = exact(acc);
- mln_ch_value(typename T::function, mln_result(A)) output;
- output = internal::compute_attribute_image(exact(a_), t, exact(values),
- accu_image);
+ mln_precondition(tree.is_valid());
- trace::exiting("morpho::tree::compute_attribute_image_from");
- return output;
+ return impl::generic::compute_attribute_image(tree, accu);
+ trace::exiting("mln::morpho::tree::compute_attribute_image");
}
-
-
-
# endif // ! MLN_INCLUDE_ONLY
- } // end of namespace mln::morpho::tree
-
- } // end of namespace mln::morpho
+ } // end of namespace mln::morpho::tree
-} // end of namespace mln
+ } // end of namespace mln::morpho
+} // end of namespace mln
-#endif // ! MLN_MORPHO_TREE_COMPUTE_ATTRIBUTE_IMAGE_HH
+#endif // !COMPUTE_ATTRIBUTE_IMAGE_HH
diff --git a/milena/mln/morpho/tree/dual_input_tree.hh b/milena/mln/morpho/tree/dual_input_tree.hh
index 08e6553..b4d4839 100644
--- a/milena/mln/morpho/tree/dual_input_tree.hh
+++ b/milena/mln/morpho/tree/dual_input_tree.hh
@@ -23,17 +23,12 @@
// exception does not however invalidate any other reasons why the
// executable file might be covered by the GNU General Public License.
-/// \file
-///
-/// Compute a canonized component tree from a dual input.
-
#ifndef MLN_MORPHO_TREE_DUAL_INPUT_TREE_HH
# define MLN_MORPHO_TREE_DUAL_INPUT_TREE_HH
-# include <mln/data/sort_psites.hh>
-
-# include <mln/morpho/tree/data.hh>
-# include <mln/morpho/tree/impl/dual_union_find.hh>
+# include <mln/tag/tree.hh>
+# include <mln/util/ctree/ctree.hh>
+# include <mln/morpho/tree/impl/union_find_fast.hh>
# include <mln/morpho/tree/impl/dual_hqueue.hh>
namespace mln
@@ -45,67 +40,25 @@ namespace mln
namespace tree
{
- /// Compute the dual input max tree using mask-based connectivity.
+ /// Compute a canonized max-tree.
///
- /// \param[in] f The original image.
- /// \param[in] m The connectivity mask.
- /// \param[in] nbh The neighborhood of the mask.
+ /// \param[in] f The input image.
+ /// \param[in] nbh The neighborhood.
///
- /// \return The computed tree.
+ /// \return The corresponding max-tree structure.
///
template <typename I, typename N>
inline
- data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
dual_input_max_tree(const Image<I>& f,
const Image<I>& m,
const Neighborhood<N>& nbh);
-
# ifndef MLN_INCLUDE_ONLY
- namespace internal
- {
-
- template <typename I, typename N>
- inline
- data< I, p_array<mln_psite(I)> >
- dual_input_max_tree_dispatch(trait::image::quant::any,
- const I& f,
- const I& m,
- const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- typedef data<I,S> tree_t;
-
- S s_f = mln::data::sort_psites_increasing(f);
- S s_m = mln::data::sort_psites_increasing(m);
-
- tree_t tree = impl::generic::dual_union_find(f, m, s_f, s_m, nbh);
- return tree;
- }
-
- template <typename I, typename N>
- inline
- data< I, p_array<mln_psite(I)> >
- dual_input_max_tree_dispatch(trait::image::quant::low,
- const I& f,
- const I& m,
- const N& nbh)
- {
- typedef p_array<mln_psite(I)> S;
- typedef data<I,S> tree_t;
-
- tree_t tree = impl::dual_hqueue(f, m, nbh);
- return tree;
- }
-
- } // end of namespace mln::morpho::tree::internal
-
-
- // Facades.
template <typename I, typename N>
inline
- morpho::tree::data< I, p_array<mln_psite(I)> >
+ util::ctree::ctree<I>
dual_input_max_tree(const Image<I>& f_,
const Image<I>& m_,
const Neighborhood<N>& nbh_)
@@ -117,23 +70,16 @@ namespace mln
const N& nbh = exact(nbh_);
mln_precondition(f.is_valid());
- mln_precondition(m.is_valid());
mln_precondition(nbh.is_valid());
- mln_precondition(f.domain() == m.domain());
- typedef p_array<mln_psite(I)> S;
- typedef data<I,S> tree_t;
+ util::ctree::ctree<I> tree =
+ morpho::tree::impl::dual_hqueue(tag::tree::max, f, m, nbh);
- tree_t tree = internal::dual_input_max_tree_dispatch(mln_trait_image_quant(I)(), f, m, nbh);
-
- trace::exiting("morpho::tree::dual_input_max_tree");
+ trace::exiting("morpho::tree::max_tree");
return tree;
}
-
-
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho::tree
@@ -142,5 +88,4 @@ namespace mln
} // end of namespace mln
-
#endif // !MLN_MORPHO_TREE_DUAL_INPUT_TREE_HH
diff --git a/milena/mln/morpho/tree/filter/direct.hh b/milena/mln/morpho/tree/filter/direct.hh
index 1835e07..0fdb01c 100644
--- a/milena/mln/morpho/tree/filter/direct.hh
+++ b/milena/mln/morpho/tree/filter/direct.hh
@@ -27,7 +27,9 @@
# define MLN_MORPHO_TREE_FILTER_DIRECT_HH
# include <mln/core/concept/function.hh>
-# include <mln/morpho/tree/data.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <mln/morpho/tree/propagate_node.hh>
+
/**
** \file mln/morpho/tree/filter/direct.hh
@@ -51,36 +53,39 @@ namespace mln
/**
** Direct non-pruning strategy. A node is removed if it does
- ** not verify the predicate. The sub-components remain intact.
+ ** not verify the predicate. Its pixels are lowered in gray
+ ** level to the highest ancestor which meets the criterion,
+ ** and while its descendants are unaffected.
**
- ** \param[in] tree Component tree.
- ** \param[out] f_ Image to filter.
+ ** \param[in,out] attr The attribute image.
** \param[in] pred_ Filtering criterion.
*/
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename P>
inline
void
- direct(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_);
+ direct(attribute_image<T,V>& attr, const Function_v2b<P>& pred_);
# ifndef MLN_INCLUDE_ONLY
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename F>
inline
void
- direct(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_)
+ direct(attribute_image<T,V>& attr, const Function_v2b<F>& pred_)
{
- F& f = exact(f_);
- const P& pred = exact(pred_);
-
trace::entering("mln::morpho::tree::filter::direct");
- mln_dn_node_piter(T) n(tree);
- for_all(n)
- if (!pred(n))
- f(n) = f(tree.parent(n));
+ typedef attribute_image<T,V> A;
+
+ const F& pred = exact(pred_);
+ const T& tree = attr.tree();
+
+ mln_fwd_piter(A) node(attr.domain());
+ for_all(node)
+ if (!pred(node))
+ attr(node) = attr(tree.parent(node));
trace::exiting("mln::morpho::tree::filter::direct");
}
diff --git a/milena/mln/morpho/tree/filter/max.hh b/milena/mln/morpho/tree/filter/max.hh
index fb0c580..96c2928 100644
--- a/milena/mln/morpho/tree/filter/max.hh
+++ b/milena/mln/morpho/tree/filter/max.hh
@@ -27,14 +27,16 @@
# define MLN_MORPHO_TREE_FILTER_MAX_HH
# include <mln/core/concept/function.hh>
-# include <mln/morpho/tree/data.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <mln/morpho/tree/propagate_node.hh>
/**
** \file mln/morpho/tree/filter/max.hh
**
** \brief Filtering with max strategy.
**
-**
+** See comments in min filter documentation.
+** FIXME: it is possible to make it in one pass !
*/
namespace mln
@@ -54,51 +56,59 @@ namespace mln
** children are removed or if it does not verify the predicate
** \p pred_.
**
- ** \param[in] tree Component tree.
- ** \param[out] f_ Image to filter.
+ ** \param[in,out] attr The attribute image.
** \param[in] pred_ Filtering criterion.
*/
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename P>
inline
void
- max(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_);
-
+ max(attribute_image<T,V>& attr, const Function_v2b<P>& pred_);
# ifndef MLN_INCLUDE_ONLY
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename P>
inline
void
- max(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_)
+ max(attribute_image<T,V>& attr, const Function_v2b<P>& pred_)
{
- F& f = exact(f_);
- const P& pred = exact(pred_);
-
trace::entering("mln::morpho::tree::filter::max");
- mln_ch_value(F, bool) mark;
- initialize(mark, f);
- mln::data::fill(mark, true);
+ typedef attribute_image<T,V> A;
+ const P& pred = exact(pred_);
+ const T& tree = attr.tree();
+
+ typedef mln_ch_value(A, char) M;
+ M marker;
+ initialize(marker, attr);
+ mln::data::fill(marker, true);
+ // 1st pass up.
{
- mln_up_node_piter(T) n(tree);
- for_all(n)
- if (!mark(n))
- mark(tree.parent(n)) = false;
- else if (pred(n))
+ mln_bkd_piter(M) node(marker.domain());
+ for_all(node)
+ if (!marker(node))
+ marker(tree.parent(node)) = false;
+ else if (pred(node))
{
- mark(tree.parent(n)) = false;
- mark(n) = false;
+ marker(tree.parent(node)) = false;
+ marker(node) = false;
}
}
+ // 2nd pass down: propagation.
{
- mln_dn_node_piter(T) n(tree);
- for_all(n)
- if (mark(n))
- f(n) = f(tree.parent(n));
+ for (int i = 0; i < tree.n_nodes(); ++i)
+ {
+ mln_invariant(tree.has_index(i));
+ mln_psite(A) n(tree, i);
+ if (marker(n))
+ {
+ attr(n) = attr(tree.parent(n));
+ i += propagate_node_to_descendants(attr, n, attr(n));
+ }
+ }
}
trace::exiting("mln::morpho::tree::filter::max");
diff --git a/milena/mln/morpho/tree/filter/min.hh b/milena/mln/morpho/tree/filter/min.hh
index db46243..16d2224 100644
--- a/milena/mln/morpho/tree/filter/min.hh
+++ b/milena/mln/morpho/tree/filter/min.hh
@@ -27,7 +27,8 @@
# define MLN_MORPHO_TREE_FILTER_MIN_HH
# include <mln/core/concept/function.hh>
-# include <mln/morpho/tree/data.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <mln/morpho/tree/propagate_node.hh>
/**
@@ -52,45 +53,57 @@ namespace mln
/**
- ** Min pruning strategy. A node is removed iif its parent is
+ ** Min pruning strategy. A node is removed iff its parent is
** removed or if it does not verify the predicate \p pred_.
**
- ** \param[in] tree Component tree.
- ** \param[out] f_ Image to filter.
+ ** \param[in,out] attr The attribute image.
** \param[in] pred_ Filtering criterion.
*/
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename F>
inline
void
- min(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_);
+ min(attribute_image<T,V>& attr, const Function_v2b<F>& pred);
# ifndef MLN_INCLUDE_ONLY
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename F>
inline
void
- min(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_)
+ min(attribute_image<T,V>& attr, const Function_v2b<F>& pred_)
{
- F& f = exact(f_);
- const P& pred = exact(pred_);
-
trace::entering("mln::morpho::tree::filter::min");
- mln_ch_value(F, bool) mark;
- initialize(mark, f);
- mln::data::fill(mark, false);
-
- mln_dn_node_piter(T) n(tree);
- for_all(n)
- if (mark(tree.parent(n)) || !pred(n))
- {
- f(n) = f(tree.parent(n));
- mark(n) = true;
- }
-
+ typedef attribute_image<T,V> A;
+
+ //mlc_is(mln_psite(A), mln_argument(F))::check();
+
+ const F& pred = exact(pred_);
+ const T& tree = attr.tree();
+
+ // Ce qui devrait être !
+ // mln_fwd_piter(A) n(attr);
+ // for_all(n)
+ // if (!pred(n))
+ // {
+ // data::fill_with_value(attr | tree.desc(n), attr(n));
+ // n.go_to_brother();
+ // }
+
+ // En attendant que le morpher subimage soit spécialisé,
+ // on joue avec les indexes.
+ for (int i = 0; i < tree.n_nodes(); ++i)
+ {
+ mln_invariant(tree.has_index(i));
+ mln_psite(A) n(tree, i);
+ if (!pred(n))
+ {
+ attr(n) = attr(tree.parent(n));
+ i += propagate_node_to_descendants(attr, n, attr(n));
+ }
+ }
trace::exiting("mln::morpho::tree::filter::min");
}
diff --git a/milena/mln/morpho/tree/filter/subtractive.hh b/milena/mln/morpho/tree/filter/subtractive.hh
index 10d3043..b905f15 100644
--- a/milena/mln/morpho/tree/filter/subtractive.hh
+++ b/milena/mln/morpho/tree/filter/subtractive.hh
@@ -27,10 +27,8 @@
# define MLN_MORPHO_TREE_FILTER_SUBTRACTIVE_HH
# include <mln/core/concept/function.hh>
-# include <mln/fun/ops.hh>
-
-# include <mln/morpho/tree/data.hh>
-# include <mln/morpho/tree/propagate_if.hh>
+# include <mln/core/image/attribute_image.hh>
+# include <mln/morpho/tree/propagate_node.hh>
/**
** \file mln/morpho/tree/filter/subtractive.hh
@@ -57,45 +55,61 @@ namespace mln
** does not verify the predicate. The sub-components values
** are set to the value of the removed component.
**
- ** \param[in] tree Component tree.
- ** \param[out] f_ Image to filter.
+ ** \param[in] ori The values as an attribute image.
** \param[in] pred_ Filtering criterion.
+ ** \return A copy of \p ori filtered with the subtractive strategy.
*/
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename P>
inline
- void
- subtractive(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_);
-
-
+ attribute_image<T, V>
+ subtractive(const attribute_image<T,V>& ori, const Function_v2b<P>& pred_);
# ifndef MLN_INCLUDE_ONLY
- template <typename T, typename F, typename P>
+ template <typename T, typename V, typename F>
inline
- void
- subtractive(const T& tree, Image<F>& f_, const Function_v2b<P>& pred_)
+ attribute_image<T, V>
+ subtractive(const attribute_image<T,V>& ori, const Function_v2b<F>& pred_)
{
- F& f = exact(f_);
- const P& pred = exact(pred_);
-
trace::entering("mln::morpho::tree::filter::subtractive");
- morpho::tree::propagate_if(tree, f, morpho::tree::desc_propagation (), !pred);
+ typedef attribute_image<T,V> A;
+
+ const F& pred = exact(pred_);
+ const T& tree = ori.tree();
+
+ mln_precondition(ori.is_valid());
- mln_up_node_piter(T) n(tree);
+ A f;
+ initialize(f, ori);
+
+ // Fixme: introduce mln_root_piter...
+ // and traverse all roots, not just the first one.
+ mln_psite(A) root = util::ctree::node<T>(tree, 0);
+ f(root) = ori(root);
+ std::cout << "Root value: " << ori(root) << std::endl;
+
+ mln_piter(A) n(ori.domain());
for_all(n)
if (!pred(n))
f(n) = f(tree.parent(n));
+ else
+ f(n) = f(tree.parent(n)) + ori(n) - ori(tree.parent(n));
trace::exiting("mln::morpho::tree::filter::subtractive");
+
+ return f;
}
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho::tree::filter
+
} // end of namespace mln::morpho::tree
+
} // end of namespace mln::morpho
+
} // end of namespace mln
#endif // ! MLN_MORPHO_TREE_FILTER_SUBTRACTIVE_HH
diff --git a/milena/mln/morpho/tree/impl/dual_hqueue.hh b/milena/mln/morpho/tree/impl/dual_hqueue.hh
index 41334f0..f00642f 100644
--- a/milena/mln/morpho/tree/impl/dual_hqueue.hh
+++ b/milena/mln/morpho/tree/impl/dual_hqueue.hh
@@ -32,31 +32,19 @@
/// This implementation is based on P. Salembier algorithm using
/// hierachical queues. This implies a low-quantized input image so
/// that the number of queues is limited.
-///
-/// TODO: Think about how to extend f domain in a more
-/// generic way. The actual implementation doubles the size of the
-/// first dimension. It implies a boxed domain.
-///
-/// TODO: Use the less functor. The actual implementation is for max-tree.
-///
-/// TODO: During the canonization pass, we build the tree site set
-/// from the sorted site set of f, so that we compute twice f
-/// histogram (can be avoided).
-# include <mln/data/sort_psites.hh>
+# include <mln/util/ctree/ctree.hh>
# include <mln/data/fill.hh>
+# include <mln/extension/fill.hh>
+# include <mln/extension/adjust.hh>
# include <mln/geom/nsites.hh>
-# include <mln/geom/translate.hh>
-# include <mln/morpho/tree/data.hh>
# include <mln/util/hqueues.hh>
-# include <mln/util/ord.hh>
# include <mln/value/value_array.hh>
# include <mln/value/set.hh>
-
# include <mln/util/timer.hh>
namespace mln
@@ -79,320 +67,430 @@ namespace mln
///
/// \return The tree structure.
///
- template <typename I, typename N>
- inline
- data<I, p_array<mln_psite(I)> >
- dual_hqueue(const Image<I>& f,
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ dual_hqueue(const tag::tree::tree_t<T>&,
+ const Image<I>& f,
const Image<I>& m,
const Neighborhood<N>& nbh);
+
} // end of namespace mln::morpho::tree::impl
# ifndef MLN_INCLUDE_ONLY
- namespace internal
+ namespace impl
{
- template <typename I, typename N, class E>
- struct shared_flood_args
+
+ template <typename I, typename N, typename E>
+ struct flooder_base_ : Object<E>
{
- typedef mln_psite(I) P;
+ typedef unsigned P;
typedef mln_value(I) V;
- typedef p_array<P> S;
+ // Constructor.
+ flooder_base_(const I& f_, const I& m_, const N& nbh_);
+
+ // Returned values.
+ mln_ch_value(I, unsigned) map;
+ std::vector<P> location;
+ std::vector<V> values;
+ std::vector<P> parent;
+ std::vector<unsigned> area;
+ unsigned nnode;
+
+
+ protected:
+ enum {
+ nvalues = mln_card(mln_value(I))
+ };
+
+
+ // Recursive function that floods. Canevas function.
+ int flood(int h_idx);
+
+ // HLevel comparaison. To be specialized for min/max tree.
+ bool hlevel_less(int h_idx1, int h_idx2);
+
+ // Parent attachment function. To be specialized for min/max tree.
+ int attach_parent(int h_idx);
+
+ // Data.
+ // \{
const I& f;
const I& m;
const N& nbh;
- mln_ch_value(I, P)& parent;
- // Aux data
- util::hqueues<P, V>& hqueues;
- const E& extend; // site -> site functor.
+ // Auxiliary data.
+ util::hqueues<unsigned, V> hqueues;
+ value::set<V> vset;
+ util::array<int> dp;
+ unsigned n_nbhs;
+
+ mln_ch_value(I, bool) deja_vu;
value::value_array<V, bool> is_node_at_level;
value::value_array<V, P> node_at_level;
- mln_ch_value(I, bool) deja_vu;
- const value::set<V>& vset;
-
- shared_flood_args(const I& f_,
- const I& m_,
- const N& neigb_,
- mln_ch_value(I, P)& parent_,
- util::hqueues<mln_psite(I), V>& hqueues_,
- const E& extend_)
- : f (f_),
- m (m_),
- nbh (neigb_),
- parent (parent_),
- hqueues (hqueues_),
- extend (extend_),
- is_node_at_level (false),
- vset (hqueues.vset())
- {
- initialize(deja_vu, f);
- mln::data::fill(deja_vu, false);
- }
+ unsigned loc;
+ // \}
};
- template <typename I>
- inline
- histo::array<mln_value(I)>
- compute_histo(const I& f, const I& m, mln_value(I)& hmin, mln_psite(I)& pmin)
+ template <typename T, typename I, typename N>
+ struct flooder;
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::max_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::max_t, I, N> >
{
- histo::array<mln_value(I)> hm = histo::compute(m);
- const histo::array<mln_value(I)> hf = histo::compute(f);
-
- { // Retrieve hmin.
- unsigned i = 0;
- while (hm[i] == 0)
- ++i;
- hmin = hm.vset()[i];
- }
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::max_t, I, N> > super_;
- // Merge histograms.
- for (unsigned i = 0; i < hm.nvalues(); ++i)
- hm[i] += hf[i];
+ // Constructor.
+ flooder(const I& f, const I& m, const N& nbh);
- // Retrieve pmin.
- mln_piter(I) p(m.domain());
- for (p.start(); m(p) != hmin; p.next())
- ;
- mln_assertion(p.is_valid());
- pmin = p;
+ // HLevel comparaison.
+ bool hlevel_less_(int h_idx1, int h_idx2);
- return hm;
- }
+ // Parent attachment function.
+ int attach_parent_(int h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
- // Site -> site functor: give for all p in Domain(f), its
- // equivalence in the extended domain.
- // TODO: make it generic. It works only on boxed domain.
- template <typename I>
- struct extend
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ using super_::hqueues;
+ };
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::min_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::min_t, I, N> >
{
- extend(const mln_psite(I)::delta& dp)
- : dp_ (dp)
- {
- }
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::min_t, I, N> > super_;
- mln_psite(I) operator() (const mln_psite(I)& p) const
- {
- return p + dp_;
- }
+ // Constructor.
+ flooder(const I& f, const I& m, const N& nbh);
- private:
- const mln_psite(I)::delta dp_;
+ // HLevel comparaison.
+ bool hlevel_less_(int h_idx1, int h_idx2);
+
+ // Parent attachment function.
+ unsigned attach_parent_(int h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
+
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ using super_::hqueues;
};
- } // end of namespace mln::morpho::tree::internal
- namespace impl
- {
+ template <typename I, typename N, typename E>
+ inline
+ bool
+ flooder_base_<I, N, E>::hlevel_less(int h_idx1, int h_idx2)
+ {
+ E& obj = exact(*this);
+ return obj.hlevel_less_(h_idx1, h_idx2);
+ }
template <typename I, typename N, typename E>
- unsigned
- flood(internal::shared_flood_args<I, N, E>& args, const unsigned h_idx)
+ inline
+ int
+ flooder_base_<I, N, E>::attach_parent(int h_idx)
{
- mln_assertion(args.is_node_at_level[h_idx]);
+ E& obj = exact(*this);
+ return obj.attach_parent_(h_idx);
+ }
- while (!args.hqueues[h_idx].empty())
- {
- mln_psite(I) p = args.hqueues[h_idx].pop_front();
- unsigned p_idx = args.vset.index_of(args.f(p));
-
- if (p_idx != h_idx)
- { // Intensity mismatch: irregular case.
- mln_psite(I) pext = args.extend(p);
- args.parent(pext) = args.node_at_level[h_idx];
-
- if (p_idx > h_idx) // Singleton with parent at h.
- args.parent(p) = args.node_at_level[h_idx];
- else
- {
- if (!args.is_node_at_level[p_idx])
- {
- args.is_node_at_level[p_idx] = true;
- args.node_at_level[p_idx] = p;
- }
- }
- }
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::max_t, I, N>::flooder(const I& f_, const I& m_, const N& nbh_)
+ : flooder_base_<I, N, flooder<tag::tree::max_t, I, N> >(f_, m_, nbh_)
+ {
+ }
- if (p_idx <= h_idx)
- {
- if (!args.f.domain().has(args.node_at_level[p_idx]) ||
- util::ord_strict(p, args.node_at_level[p_idx]))
- { // Regular case but a representative provided by the extension.
- args.parent(args.node_at_level[p_idx]) = p;
- args.node_at_level[p_idx] = p;
- //args.parent(p) = p;
- }
- args.parent(p) = args.node_at_level[p_idx];
- }
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::min_t, I, N>::flooder(const I& f_, const I& m_, const N& nbh_)
+ : flooder_base_<I, N, flooder<tag::tree::min_t, I, N> >(f_, m_, nbh_)
+ {
+ }
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::max_t, I, N>::hlevel_less_(int h_idx1, int h_idx2)
+ {
+ return h_idx1 < h_idx2;
+ }
- // Process the neighbors
- mln_niter(N) n(args.nbh, p);
- for_all(n)
- if (args.f.domain().has(n) && !args.deja_vu(n))
- {
- unsigned mn = args.vset.index_of(args.m(n));
- unsigned fn = args.vset.index_of(args.f(n));
- args.hqueues[mn].push(n);
- args.deja_vu(n) = true;
-
- mln_psite(I) ext = args.extend(n);
- // Create a node at c.
- {
- mln_psite(I) node = (fn == mn) ? n : ext;
- if (!args.is_node_at_level[mn])
- {
- args.is_node_at_level[mn] = true;
- args.node_at_level[mn] = node;
- }
- }
-
- while (mn > h_idx)
- mn = flood(args, mn);
- }
- }
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::min_t, I, N>::hlevel_less_(int h_idx1, int h_idx2)
+ {
+ return h_idx2 < h_idx1;
+ }
- // Retrieve dad.
- args.is_node_at_level[h_idx] = false;
- unsigned c = h_idx;
- while (c > 0 && !args.is_node_at_level[c])
+ template <typename I, typename N>
+ inline
+ int
+ flooder<tag::tree::max_t, I, N>::attach_parent_(int h_idx)
+ {
+ mln_assertion(h_idx >= 0);
+ mln_assertion(is_node_at_level[h_idx]);
+
+
+ unsigned x = node_at_level[h_idx];
+ int c = h_idx - 1;
+
+ is_node_at_level[h_idx] = false;
+ while (c >= 0 && !is_node_at_level[c])
--c;
- mln_psite(I) x = args.node_at_level[h_idx];
- if (c > 0)
- args.parent(x) = args.node_at_level[c];
- else
- args.parent(x) = x;
+ if (c >= 0)
+ {
+ unsigned p = node_at_level[c];
+ parent[x] = p;
+ area[p] += area[x] + 1;
+ }
+ else // root case.
+ parent[x] = x;
+ location[x] = loc++;
return c;
}
- template <typename I, typename N>
- inline
- data< I, p_array<mln_psite(I)> >
- dual_hqueue(const Image<I>& f_,
- const Image<I>& m_,
- const Neighborhood<N>& neibh_)
- {
- trace::entering("mln::morpho::tree::impl::dual_hqueue");
+ // template <typename I, typename N>
+ // inline
+ // unsigned
+ // flooder<tag::tree::min_t, I, N>::attach_parent_(unsigned h_idx)
+ // {
+ // unsigned nv = vset.nvalues() - 1;
+ // unsigned c = h_idx;
- const I& f = exact(f_);
- const I& m = exact(m_);
- const N& nbh = exact(neibh_);
+ // while (c < nv && !is_node_at_level[c])
+ // ++c;
- typedef mln_psite(I) P;
- typedef p_array<mln_psite(I)> S;
+ // unsigned x = node_at_level[h_idx];
+ // if (is_node_at_level[c])
+ // {
+ // unsigned p = node_at_level[c];
+ // parent[x] = p;
+ // area[p] += area[x] + 1;
+ // }
+ // else
+ // parent[x] = x;
- util::timer tm;
- tm.start();
+ // location[x] = loc++;
+ // return c;
+ // }
- // Histo.
- mln_psite(I) pmin;
- mln_value(I) hmin;
- const histo::array<mln_value(I)> histo = internal::compute_histo(f, m, hmin, pmin);
- util::hqueues<P, mln_value(I)> hqueues(histo);
- mln_psite(I)::delta dp(literal::zero);
- mln_domain(I) d_ext = f.domain();
- mln_domain(I) d = f.domain();
+ template <typename I, typename N, typename E>
+ flooder_base_<I, N, E>::flooder_base_(const I& f_, const I& m_, const N& nbh_)
+ : f (f_), m(m_), nbh (nbh_), is_node_at_level (false)
+ {
+ typedef mln_value(I) V;
- // Extend the domain.
- dp[0] = d.pmax()[0] - d.pmin()[0] + 1;
- d.pmax() += dp;
- d_ext.pmin() += dp;
- d_ext.pmax() += dp;
+ unsigned pmin_offset;
+ V vmin;
- // Data.
- mln_concrete(I) fext;
- mln_ch_value(I, P) parent;
- p_array<mln_psite(I)> s;
-
- // Initialization.
- fext = geom::translate(m, dp.to_vec(), f, d);
- initialize(parent, fext);
- s.reserve(geom::nsites(fext));
-
- // Process.
- internal::extend<I> extend(dp);
- internal::shared_flood_args< I, N, internal::extend<I> >
- args(f, m, nbh, parent, hqueues, extend);
-
- unsigned r = args.vset.index_of(hmin);
- args.deja_vu(pmin) = true;
- args.hqueues[r].push(pmin);
- args.node_at_level[r] = (f(pmin) == hmin) ? pmin : extend(pmin);
- args.is_node_at_level[r] = true;
- flood(args, r);
-
- // Attach the nodes under hmin.
- unsigned i = r;
- do
+ // Allocate hierarchical queues and retrieve the starting point
{
- if (args.is_node_at_level[i])
- {
- parent(args.node_at_level[r]) = args.node_at_level[i];
- r = i;
- }
+ util::array< unsigned > h(nvalues, 0);
+
+ pmin_offset = m.index_of_point(m.domain().pmin());
+ vmin = m.element(pmin_offset);
+
+ mln_fwd_pixter(const I) pxl(m);
+ for_all(pxl)
+ {
+ ++h[pxl.val()];
+ if (hlevel_less(pxl.val(), vmin))
+ {
+ vmin = pxl.val();
+ pmin_offset = pxl.offset();
+ }
+ }
+
+ for (unsigned i = 0; i < nvalues; ++i)
+ hqueues[i].reserve(h[i]);
}
- while (i-- > 0);
- parent(args.node_at_level[r]) = args.node_at_level[r]; //root
- // Canonization and make tree site set.
- {
- mln_ch_value(I, bool) deja_vu(d_ext);
- mln::data::fill(deja_vu, false);
+ // Initialize aux data
+ {
+ dp = offsets_wrt(f, nbh);
+ n_nbhs = dp.nelements();
+ vset = value::set<V>::the();
+
+ extension::adjust(f, nbh);
+ extension::adjust(m, nbh);
+
+ initialize(deja_vu, f);
+ initialize(map, f);
+ data::fill(deja_vu, false);
+ extension::fill(deja_vu, true);
+
+ unsigned nsites = geom::nsites(f);
+ parent.resize(2 * nsites);
+ location.resize(2 * nsites);
+ area.resize(2 * nsites, 0);
+ values.resize(2 * nsites);
+
+ nnode = 0;
+ loc = 0;
+ }
+
+ // Start flooding
+ unsigned hmin = vset.index_of(vmin);
+ unsigned fmin = vset.index_of(f.element(pmin_offset));
+ std::cout << vmin << std::endl;
+ hqueues[hmin].push(pmin_offset);
+ deja_vu.element(pmin_offset) = true;
+ values[nnode] = vmin;
+ node_at_level[fmin] = nnode++;
+ is_node_at_level[fmin] = true;
+ if (hmin != fmin)
+ {
+ values[nnode] = f.element(pmin_offset);
+ node_at_level[hmin] = nnode++;
+ is_node_at_level[hmin] = true;
+ }
+ int c = flood(hmin);
+ while (c != -1) // There still are nodes under minimal mask level.
+ c = attach_parent(c);
+ mln_assertion(c == -1);
+ }
- p_array<mln_psite(I)> s_f = mln::data::sort_psites_increasing(f);
- mln_fwd_piter(S) p(s_f); // Forward.
- for_all(p)
+ template <typename I, typename N, typename E>
+ int
+ flooder_base_<I, N, E>::flood(int h_idx)
+ {
+ mln_assertion(h_idx >= 0);
+ mln_assertion(is_node_at_level[h_idx]);
+
+ while (!hqueues[h_idx].empty())
{
- P x = p;
- P q = parent(p);
+ unsigned p = hqueues[h_idx].pop_front();
+ int p_idx = vset.index_of(f.element(p));
+ mln_assertion(vset.index_of(m.element(p)) == (unsigned)h_idx);
+ //mln_assertion(is_node_at_level[p_idx]);
- // Case: l: m <---- m <---- f
- // Or
- // Case l1: m <----- f impossible.
- // |
- // l2: m
- mln_assertion(!(d_ext.has(q) && fext(p) == fext(q) && d_ext.has(parent(q)) && q != parent(q)));
- while (d_ext.has(q) && !deja_vu(q) && (fext(q) != fext(parent(q)) || q == parent(q)))
+ if (h_idx < p_idx) // FIXME: max tree only
{
- s.append(q);
- deja_vu(q) = true;
- x = q;
- q = parent(q);
+ // Singleton
+ int par_i = node_at_level[h_idx];
+ int self_i = nnode++; // Create the node.
+ map.element(p) = self_i;
+ values[self_i] = m.element(p);
+ area[self_i] = 1;
+ parent[self_i] = par_i;
+ location[self_i] = loc++;
+ area[par_i]++;
}
+ else
+ map.element(p) = node_at_level[p_idx];
- if (d_ext.has(q) && fext(q) == fext(parent(q)) && q != parent(q))
+ // Process the neighbors
+ for (unsigned j = 0; j < n_nbhs; ++j)
{
- q = (parent(x) = parent(q));
- mln_assertion(f.domain().has(q));
+ unsigned n = p + dp[j];
+
+ if (!deja_vu.element(n))
+ {
+ unsigned n_hidx = vset.index_of(m.element(n));
+ unsigned n_fidx = vset.index_of(f.element(n));
+ hqueues[n_hidx].push(n);
+ deja_vu.element(n) = true;
+
+ if (!is_node_at_level[n_hidx])
+ {
+ values[nnode] = (m.element(n));
+ node_at_level[n_hidx] = nnode++;
+ is_node_at_level[n_hidx] = true;
+ }
+ if (!is_node_at_level[n_fidx] && n_fidx < n_hidx)
+ {
+ values[nnode] = (f.element(n));
+ node_at_level[n_fidx] = nnode++;
+ is_node_at_level[n_fidx] = true;
+ }
+
+ while (hlevel_less(h_idx, n_hidx))
+ n_hidx = flood(n_hidx);
+ }
}
+ }
- if (fext(q) == fext(parent(q)))
- parent(x) = parent(q);
+ return attach_parent(h_idx);
+ }
+
+ template <typename T, typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ dual_hqueue(const tag::tree::tree_t<T>&,
+ const Image<I>& f_,
+ const Image<I>& m_,
+ const Neighborhood<N>& nbh_)
+ {
+ trace::entering("mln::morpho::tree::impl::hqueue");
+ const I& f = exact(f_);
+ const I& m = exact(m_);
+ const N& nbh = exact(nbh_);
- s.append(p);
+ mln_precondition(f.is_valid());
+ mln_precondition(m.is_valid());
+ mln_precondition(nbh.is_valid());
- mln_assertion((q = parent(p)) == parent(q) || fext(q) != fext(parent(q)));
- }
+ // Process
+ impl::flooder<T, I, N> args(f, m, nbh);
- }
+ // Reserve
+ util::ctree::ctree<I> tree;
+ tree.reserve(f, args.nnode);
- std::cout << "Construction de l'arbre en " << tm << " s." << std::endl;
+ // Set values
+ {
+ mln_piter(I) p(f.domain());
+ for_all(p)
+ {
+ unsigned idx = args.map(p);
+ unsigned loc = args.nnode - args.location[idx] - 1;
+ tree.node_at_(p) = loc;
+ }
- data<I, S> tree(fext, parent, s);
+ for (int idx = 0; idx < args.nnode; ++idx)
+ {
+ unsigned loc = args.nnode - args.location[idx] - 1;
- trace::exiting("mln::morpho::tree::impl::dual_hqueue");
+ tree.parent_at_(loc) = args.nnode - args.location[args.parent[idx]] - 1;
+ tree.f_at_(loc) = args.values[idx];
+ tree.length_at_(loc) = args.area[idx];
+ }
+ }
+ trace::exiting("mln::morpho::tree::impl::hqueue");
return tree;
}
- } // end of namespace mln::morpho::tree::impl
+ } // end of namespace mln::morpho::tree::impl
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/milena/mln/morpho/tree/impl/hqueue.hh b/milena/mln/morpho/tree/impl/hqueue.hh
new file mode 100644
index 0000000..cfe0f4b
--- /dev/null
+++ b/milena/mln/morpho/tree/impl/hqueue.hh
@@ -0,0 +1,428 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_IMPL_HQUEUE_HH
+# define MLN_MORPHO_TREE_IMPL_HQUEUE_HH
+
+# include <mln/util/ctree/ctree.hh>
+# include <mln/util/hqueues.hh>
+# include <mln/value/value_array.hh>
+# include <mln/geom/nsites.hh>
+
+# include <mln/histo/array.hh>
+# include <mln/histo/compute.hh>
+# include <mln/data/fill.hh>
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ namespace tree
+ {
+
+ namespace impl
+ {
+
+ template <typename T, typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ hqueue(const tag::tree::tree_t<T>&, const Image<I>& f, const Neighborhood<N>& nbh);
+
+ } // end of namespace mln::morpho::tree::impl
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename T, typename I>
+ struct op_psite_less;
+
+ template <typename I>
+ struct op_psite_less< tag::tree::max_t, I>
+ {
+ op_psite_less(const I& f) : f_(f) {}
+
+ bool operator() (const mln_psite(I)& lhs, const mln_psite(I)& rhs) const
+ {
+ return util::ord_strict(f_(lhs), f_(rhs));
+ }
+
+ private:
+ const I& f_;
+ };
+
+ template <typename I>
+ struct op_psite_less< tag::tree::min_t, I>
+ {
+ op_psite_less(const I& f) : f_(f) {}
+
+ bool operator() (const mln_psite(I)& lhs, const mln_psite(I)& rhs) const
+ {
+ return util::ord_strict(f_(rhs), f_(lhs));
+ }
+
+ private:
+ const I& f_;
+ };
+
+ }
+
+
+ namespace impl
+ {
+
+
+ template <typename I, typename N, typename E>
+ struct flooder_base_ : Object<E>
+ {
+ typedef unsigned P;
+ typedef mln_value(I) V;
+
+ // Constructor.
+ flooder_base_(const I& f_, const N& nbh_);
+
+ // Returned values.
+ mln_ch_value(I, unsigned) map;
+ std::vector<P> location;
+ std::vector<P> parent;
+ std::vector<unsigned> area;
+ unsigned n_node;
+
+
+ protected:
+ // Recursive function that floods. Canevas function.
+ unsigned flood(const unsigned h_idx);
+
+ // HLevel comparaison. To be specialized for min/max tree.
+ bool hlevel_less(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function. To be specialized for min/max tree.
+ unsigned attach_parent(unsigned h_idx);
+
+ // Data.
+ // \{
+ const I& f;
+ const N& nbh;
+
+ // Auxiliary data.
+ util::hqueues<mln_psite(I), V> hqueues;
+ value::set<V> vset;
+
+ mln_ch_value(I, bool) deja_vu;
+ value::value_array<V, bool> is_node_at_level;
+ value::value_array<V, P> node_at_level;
+ unsigned loc;
+ // \}
+ };
+
+ template <typename T, typename I, typename N>
+ struct flooder;
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::max_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::max_t, I, N> >
+ {
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::max_t, I, N> > super_;
+
+ // Constructor.
+ flooder(const I& f_, const N& nbh_);
+
+ // HLevel comparaison.
+ bool hlevel_less_(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function.
+ unsigned attach_parent_(unsigned h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
+
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ };
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::min_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::min_t, I, N> >
+ {
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::min_t, I, N> > super_;
+
+ // Constructor.
+ flooder(const I& f_, const N& nbh_);
+
+ // HLevel comparaison.
+ bool hlevel_less_(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function.
+ unsigned attach_parent_(unsigned h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
+
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ };
+
+
+ template <typename I, typename N, typename E>
+ inline
+ bool
+ flooder_base_<I, N, E>::hlevel_less(unsigned h_idx1, unsigned h_idx2)
+ {
+ E& obj = exact(*this);
+ return obj.hlevel_less_(h_idx1, h_idx2);
+ }
+
+ template <typename I, typename N, typename E>
+ inline
+ unsigned
+ flooder_base_<I, N, E>::attach_parent(unsigned h_idx)
+ {
+ E& obj = exact(*this);
+ return obj.attach_parent_(h_idx);
+ }
+
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::max_t, I, N>::flooder(const I& f_, const N& nbh_,
+ const histo::array< mln_value(I) >& histo_)
+ : flooder_base_<I, N, flooder<tag::tree::max_t, I, N> >(f_, nbh_, histo_)
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::min_t, I, N>::flooder(const I& f_, const N& nbh_,
+ const histo::array<mln_value(I)>& histo_)
+ : flooder_base_<I, N, flooder<tag::tree::min_t, I, N> >(f_, nbh_, histo_)
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::max_t, I, N>::hlevel_less_(unsigned h_idx1, unsigned h_idx2)
+ {
+ return h_idx1 < h_idx2;
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::min_t, I, N>::hlevel_less_(unsigned h_idx1, unsigned h_idx2)
+ {
+ return h_idx2 < h_idx1;
+ }
+
+ template <typename I, typename N>
+ inline
+ unsigned
+ flooder<tag::tree::max_t, I, N>::attach_parent_(unsigned h_idx)
+ {
+ unsigned c = h_idx;
+ while (c > 0 && !is_node_at_level[c])
+ --c;
+
+ unsigned x = node_at_level[h_idx];
+ if (is_node_at_level[c]) // || c > 0
+ {
+ unsigned p = node_at_level[c];
+ parent[x] = p;
+ area[p] += area[x] + 1;
+ }
+ else
+ parent[x] = x;
+
+ location[x] = loc++;
+ return c;
+ }
+
+ template <typename I, typename N>
+ inline
+ unsigned
+ flooder<tag::tree::min_t, I, N>::attach_parent_(unsigned h_idx)
+ {
+ unsigned nv = vset.nvalues() - 1;
+ unsigned c = h_idx;
+
+ while (c < nv && !is_node_at_level[c])
+ ++c;
+
+ unsigned x = node_at_level[h_idx];
+ if (is_node_at_level[c]) // || c < nv
+ {
+ unsigned p = node_at_level[c];
+ parent[x] = p;
+ area[p] += area[x] + 1;
+ }
+ else
+ parent[x] = x;
+
+ location[x] = loc++;
+ return c;
+ }
+
+
+ template <typename I, typename N, typename E>
+ flooder_base_<I, N, E>::flooder_base_(const I& f_, const N& nbh_,
+ const histo::array< mln_value(I) >& histo_)
+ : f (f_), nbh (nbh_), is_node_at_level (false)
+ {
+ // Initialization
+ {
+ unsigned nsites = geom::nsites(f);
+ initialize(map, f);
+ initialize(deja_vu, f);
+
+ parent.resize(nsites);
+ location.resize(nsites);
+ area.resize(nsites, 0);
+ data::fill(deja_vu, false);
+
+ vset = value::set< mln_value(I) >::the();
+
+ n_node = 0;
+ loc = 0;
+ }
+
+ // Get start value
+ mln_psite(I) pstart = f.domain().pmin();
+ mln_value(I) hstart = f(pstart);
+ {
+ mln_piter(I) p(f.domain());
+ for_all(p)
+ {
+ mln_value(I) v = f(p);
+ ++h[v];
+ if (hlevel_less(v, hstart))
+ {
+ hstart = v;
+ pstart = p;
+ }
+ }
+
+ for (unsigned i = 0; i < nvalues; ++i)
+ hqueues[i].reserve(h[i]);
+ }
+
+ // Start flooding
+ unsigned r = vset.index_of(hstart);
+ deja_vu(pstart) = true;
+ hqueues[r].push(pstart);
+ node_at_level[r] = n_node++;
+ is_node_at_level[r] = true;
+
+ flood(r);
+ }
+
+ template <typename I, typename N, typename E>
+ unsigned
+ flooder_base_<I, N, E>::flood(const unsigned h_idx)
+ {
+ mln_assertion(is_node_at_level[h_idx]);
+
+ while (!hqueues[h_idx].empty())
+ {
+ mln_psite(I) p = hqueues[h_idx].pop_front();
+ mln_assertion(vset.index_of(f(p)) == h_idx);
+
+ map(p) = node_at_level[h_idx];
+
+ // Process the neighbors
+ mln_niter(N) n(nbh, p);
+ for_all(n)
+ if (f.domain().has(n) && !deja_vu(n))
+ {
+ unsigned n_idx = vset.index_of(f(n));
+ hqueues[n_idx].push(n);
+ deja_vu(n) = true;
+
+ if (!is_node_at_level[n_idx])
+ {
+ node_at_level[n_idx] = n_node++;
+ is_node_at_level[n_idx] = true;
+ }
+
+ while (hlevel_less(h_idx, n_idx))
+ n_idx = flood(n_idx);
+ }
+ }
+
+ is_node_at_level[h_idx] = false;
+ return attach_parent(h_idx);
+ }
+
+ template <typename T, typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ hqueue(const tag::tree::tree_t<T>&, const Image<I>& f_, const Neighborhood<N>& nbh_)
+ {
+ trace::entering("mln::morpho::tree::impl::hqueue");
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(f.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ // Process
+ impl::flooder<T, I, N> args(f, nbh);
+ // \todo handles here discontinous domains: so multi-roots trees.
+
+ args.parent.resize(args.n_node);
+ args.area.resize(args.n_node);
+ args.location.resize(args.n_node);
+
+ util::ctree::ctree<I> tree(f, args.map, args.location, args.parent,
+ args.area);
+
+ trace::exiting("mln::morpho::tree::impl::hqueue");
+ return tree;
+ }
+
+ } // end of namespace mln::morpho::tree::impl
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::tree
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif // !MLN_MORPHO_TREE_IMPL_HQUEUE_HH
diff --git a/milena/mln/morpho/tree/impl/hqueue_fast.hh b/milena/mln/morpho/tree/impl/hqueue_fast.hh
new file mode 100644
index 0000000..645bbc4
--- /dev/null
+++ b/milena/mln/morpho/tree/impl/hqueue_fast.hh
@@ -0,0 +1,391 @@
+#ifndef MLN_MORPHO_TREE_IMPL_HQUEUE_FASTHH
+# define MLN_MORPHO_TREE_IMPL_HQUEUE_FASTHH
+
+# include <mln/extension/adjust.hh>
+# include <mln/extension/fill.hh>
+# include <mln/util/ctree/ctree.hh>
+# include <mln/util/hqueues.hh>
+# include <mln/value/value_array.hh>
+# include <mln/geom/nsites.hh>
+# include <mln/data/fill.hh>
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ namespace tree
+ {
+
+ namespace impl
+ {
+
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ hqueue_fast(const tag::tree::tree_t<T>&, const Image<I>& f, const Neighborhood<N>& nbh);
+
+ } // end of namespace mln::morpho::tree::impl
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I, typename N, typename E>
+ struct flooder_base_ : Object<E>
+ {
+ typedef unsigned P;
+ typedef mln_value(I) V;
+
+ // Constructor.
+ flooder_base_(const I& f_, const N& nbh_);
+
+ mln_ch_value(I, unsigned) map;
+ std::vector<P> location;
+ std::vector<P> parent;
+ std::vector<unsigned> area;
+ unsigned n_node;
+
+ protected:
+ enum {
+ nvalues = mln_card(mln_value(I))
+ };
+
+ // Recursive function that floods. Canevas function.
+ unsigned flood(const unsigned h_idx);
+
+ // HLevel comparaison. To be specialized for min/max tree.
+ bool hlevel_less(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function. To be specialized for min/max tree.
+ unsigned attach_parent(unsigned h_idx);
+
+
+ // Data.
+ // \{
+ const I& f;
+ const N& nbh;
+
+ // Auxiliary data.
+ util::hqueues<unsigned, V> hqueues;
+ value::set<V> vset;
+ util::array<int> dp;
+ unsigned n_nbhs;
+
+ mln_ch_value(I, bool) deja_vu;
+ value::value_array<V, bool> is_node_at_level;
+ value::value_array<V, P> node_at_level;
+ unsigned loc;
+ // \}
+ };
+
+ template <typename T, typename I, typename N>
+ struct flooder;
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::max_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::max_t, I, N> >
+ {
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::max_t, I, N> > super_;
+
+ // Constructor.
+ flooder(const I& f_, const N& nbh_);
+
+ // HLevel comparaison.
+ bool hlevel_less_(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function.
+ unsigned attach_parent_(unsigned h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
+
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ };
+
+ template <typename I, typename N>
+ struct flooder<tag::tree::min_t, I, N> :
+ flooder_base_< I, N, flooder<tag::tree::min_t, I, N> >
+ {
+ typedef mln_value(I) V;
+ typedef flooder_base_< I, N, flooder<tag::tree::min_t, I, N> > super_;
+
+ // Constructor.
+ flooder(const I& f_, const N& nbh_);
+
+ // HLevel comparaison.
+ bool hlevel_less_(unsigned h_idx1, unsigned h_idx2);
+
+ // Parent attachment function.
+ unsigned attach_parent_(unsigned h_idx);
+
+ public:
+ using super_::parent;
+ using super_::area;
+ using super_::location;
+
+ protected:
+ using super_::is_node_at_level;
+ using super_::node_at_level;
+ using super_::vset;
+ using super_::loc;
+ };
+
+ template <typename I, typename N, typename E>
+ inline
+ bool
+ flooder_base_<I, N, E>::hlevel_less(unsigned h_idx1, unsigned h_idx2)
+ {
+ E& obj = exact(*this);
+ return obj.hlevel_less_(h_idx1, h_idx2);
+ }
+
+ template <typename I, typename N, typename E>
+ inline
+ unsigned
+ flooder_base_<I, N, E>::attach_parent(unsigned h_idx)
+ {
+ E& obj = exact(*this);
+ return obj.attach_parent_(h_idx);
+ }
+
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::max_t, I, N>::flooder(const I& f_, const N& nbh_)
+ : flooder_base_<I, N, flooder<tag::tree::max_t, I, N> >(f_, nbh_)
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ flooder<tag::tree::min_t, I, N>::flooder(const I& f_, const N& nbh_)
+ : flooder_base_<I, N, flooder<tag::tree::min_t, I, N> >(f_, nbh_)
+ {
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::max_t, I, N>::hlevel_less_(unsigned h_idx1, unsigned h_idx2)
+ {
+ return h_idx1 < h_idx2;
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ flooder<tag::tree::min_t, I, N>::hlevel_less_(unsigned h_idx1, unsigned h_idx2)
+ {
+ return h_idx2 < h_idx1;
+ }
+
+ template <typename I, typename N>
+ inline
+ unsigned
+ flooder<tag::tree::max_t, I, N>::attach_parent_(unsigned h_idx)
+ {
+ unsigned c = h_idx;
+ while (c > 0 && !is_node_at_level[c])
+ --c;
+
+ unsigned x = node_at_level[h_idx];
+ if (is_node_at_level[c]) // || c > 0
+ {
+ unsigned p = node_at_level[c];
+ parent[x] = p;
+ area[p] += area[x] + 1;
+ }
+ else
+ parent[x] = x;
+
+ location[x] = loc++;
+ return c;
+ }
+
+ template <typename I, typename N>
+ inline
+ unsigned
+ flooder<tag::tree::min_t, I, N>::attach_parent_(unsigned h_idx)
+ {
+ unsigned nv = vset.nvalues() - 1;
+ unsigned c = h_idx;
+
+ while (c < nv && !is_node_at_level[c])
+ ++c;
+
+ unsigned x = node_at_level[h_idx];
+ if (is_node_at_level[c]) // || c < nv
+ {
+ unsigned p = node_at_level[c];
+ parent[x] = p;
+ area[p] += area[x] + 1;
+ }
+ else
+ parent[x] = x;
+
+ location[x] = loc++;
+ return c;
+ }
+
+
+ template <typename I, typename N, typename E>
+ flooder_base_<I, N, E>::flooder_base_(const I& f_, const N& nbh_)
+ : f (f_), nbh (nbh_), is_node_at_level(false)
+ {
+ // Prepare hierarchical queues and retrieve start point.
+ unsigned pmin;
+ mln_value(I) vmin;
+ {
+ util::array< unsigned > h(nvalues, 0);
+
+ pmin = f.index_of_point(f.domain().pmin());
+ vmin = f.element(pmin);
+
+ mln_fwd_pixter(const I) pxl(f);
+ for_all(pxl)
+ {
+ ++h[pxl.val()];
+ if (hlevel_less(pxl.val(), vmin))
+ {
+ vmin = pxl.val();
+ pmin = pxl.offset();
+ }
+ }
+
+ for (unsigned i = 0; i < nvalues; ++i)
+ hqueues[i].reserve(h[i]);
+ }
+
+ // Initialize aux data
+ {
+ dp = offsets_wrt(f, nbh);
+ n_nbhs = dp.nelements();
+ vset = value::set< mln_value(I) >::the();
+
+ extension::adjust(f, nbh);
+
+ initialize(deja_vu, f);
+ initialize(map, f);
+ data::fill(deja_vu, false);
+ extension::fill(deja_vu, true);
+
+ unsigned nsites = geom::nsites(f);
+ parent.resize(nsites);
+ location.resize(nsites);
+ area.resize(nsites, 0);
+
+ n_node = 0;
+ loc = 0;
+ }
+
+ // Start flooding
+ unsigned hmin = vset.index_of(vmin);
+ deja_vu.element(pmin) = true;
+ hqueues[hmin].push(pmin);
+ node_at_level[hmin] = n_node++;
+ is_node_at_level[hmin] = true;
+
+ flood(hmin);
+ }
+
+ template <typename I, typename N, typename E>
+ unsigned
+ flooder_base_<I, N, E>::flood(const unsigned h_idx)
+ {
+ mln_assertion(is_node_at_level[h_idx]);
+
+ while (!hqueues[h_idx].empty())
+ {
+ unsigned p = hqueues[h_idx].pop_front();
+ mln_assertion(vset.index_of(f.element(p)) == h_idx);
+
+ map.element(p) = node_at_level[h_idx];
+
+ // Process the neighbors
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+
+ if (!deja_vu.element(n))
+ {
+ unsigned n_idx = vset.index_of(f.element(n));
+ hqueues[n_idx].push(n);
+ deja_vu.element(n) = true;
+
+ if (!is_node_at_level[n_idx])
+ {
+ node_at_level[n_idx] = n_node++;
+ is_node_at_level[n_idx] = true;
+ }
+
+ while (hlevel_less(h_idx, n_idx))
+ n_idx = flood(n_idx);
+ }
+ }
+ }
+
+ is_node_at_level[h_idx] = false;
+ return attach_parent(h_idx);
+ }
+
+ template <typename T, typename I, typename N>
+ inline
+ util::ctree::ctree<I>
+ hqueue_fast(const tag::tree::tree_t<T>&, const Image<I>& f_, const Neighborhood<N>& nbh_)
+ {
+ trace::entering("mln::morpho::tree::impl::hqueue_fast");
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(f.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ // Process
+ impl::flooder<T, I, N> args(f, nbh);
+ // \todo handles here discontinous domains: so multi-roots trees.
+
+ // Create tree and fill it.
+ util::ctree::ctree<I> tree;
+ {
+ tree.reserve(f, args.n_node);
+
+ mln_pixter(const I) pix(f);
+ for_all(pix)
+ {
+ int idx = args.map.element(pix.offset());
+ int loc = args.n_node - args.location[idx] - 1;
+ tree.data_->map_.element(pix.offset()) = loc;
+ tree.data_->values_[loc] = pix.val();
+ }
+
+ for (unsigned idx = 0; idx < args.n_node; ++idx)
+ {
+ int loc = args.n_node - args.location[idx] - 1;
+ tree.data_->parent_[loc] = args.n_node - args.location[args.parent[idx]] - 1;
+ tree.data_->length_[loc] = args.area[idx];
+ }
+ }
+
+ trace::exiting("mln::morpho::tree::impl::hqueue_fast");
+ return tree;
+ }
+
+ } // end of namespace mln::morpho::tree::impl
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::tree
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif // !MLN_MORPHO_TREE_IMPL_HQUEUE_FAST_HH
diff --git a/milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh b/milena/mln/morpho/tree/impl/union_find.hh
similarity index 99%
copy from milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh
copy to milena/mln/morpho/tree/impl/union_find.hh
index f2aee82..8485727 100644
--- a/milena/sandbox/edwin/mln/morpho/tree/impl/union_find.hh
+++ b/milena/mln/morpho/tree/impl/union_find.hh
@@ -163,7 +163,9 @@ namespace mln
}
}
+
# endif // ! MLN_INCLUDE_ONLY
+
}
}
diff --git a/milena/mln/morpho/tree/impl/union_find_fast.hh b/milena/mln/morpho/tree/impl/union_find_fast.hh
new file mode 100644
index 0000000..80a521d
--- /dev/null
+++ b/milena/mln/morpho/tree/impl/union_find_fast.hh
@@ -0,0 +1,396 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_IMPL_UNION_FIND_FAST_HH
+# define MLN_MORPHO_TREE_IMPL_UNION_FIND_FAST_HH
+
+///
+///
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ namespace tree
+ {
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ /// The fast version of union-find algorithm.
+ /// \pre The image \p f must be fastest
+ ///
+ /// \param tree_tag The type of tree to build (min or max-tree).
+ /// \param f Source image used to build the component tree.
+ /// \param nbh Neighborhood used to build the component tree.
+ ///
+ /// \return A component tree object.
+ ///
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ union_find_fast(const tag::tree::tree_t<T>& tree_tag,
+ const Image<I>& f,
+ const Neighborhood<N>& nbh);
+ }
+
+ }
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ void
+ sort_sites_set_radix(const tag::tree::max_t&, const I& f, util::array<unsigned>& s, util::array<unsigned>& levels)
+ {
+ typedef mln_value(I) V;
+ static const value::set<V>& vset = value::set<V>::the();
+ static const int n = mln_card(V);
+
+ util::array<unsigned> h(n, 0);
+ s.resize(f.domain().nsites());
+ levels.resize(n + 1);
+
+ mln_fwd_pixter(const I) pxl(f);
+ for_all(pxl)
+ ++h[vset.index_of(pxl.val())];
+
+ for (int i = 1; i <= n; ++i)
+ {
+ levels[i] = levels[i - 1] + h[i - 1];
+ h[i - 1] = levels[i - 1];
+ }
+
+ // computing output data
+ for_all(pxl)
+ {
+ int i = vset.index_of(pxl.val());
+ s[h[i]++] = pxl.offset();
+ }
+ }
+
+ template <typename I>
+ static inline
+ void
+ sort_sites_set_radix(const tag::tree::min_t&, const I& f, util::array<unsigned>& s, util::array<unsigned>& levels)
+ {
+ typedef mln_value(I) V;
+ static const value::set<V>& vset = value::set<V>::the();
+ static const int n = mln_card(V);
+
+ util::array<unsigned> h(n, 0);
+ s.resize(f.domain().nsites());
+ levels.resize(n + 1);
+
+ mln_fwd_pixter(const I) pxl(f);
+ for_all(pxl)
+ ++h[n - 1 - vset.index_of(pxl.val())];
+
+ for (int i = 1; i <= n; ++i)
+ {
+ levels[i] = levels[i - 1] + h[i - 1];
+ h[i - 1] = levels[i - 1];
+ }
+
+ // computing output data
+ for_all(pxl)
+ {
+ int i = vset.index_of(pxl.val());
+ s[h[n - 1 - i]++] = pxl.offset();
+ }
+ }
+
+ template <typename T, typename I>
+ struct sort_op_less_;
+
+ template <typename I>
+ struct sort_op_less_<tag::tree::max_t, I>
+ {
+ sort_op_less_ (const I& f_) : f(f_) {}
+
+ bool operator() (unsigned e1, unsigned e2)
+ {
+ return f.element(e1) < f.element(e2) || (f.element(e1) == f.element(e2) && e1 < e2);
+ }
+
+ private:
+ const I& f;
+ };
+
+ template <typename I>
+ struct sort_op_less_<tag::tree::min_t, I>
+ {
+ sort_op_less_ (const I& f_) : f(f_) {}
+
+ bool operator() (unsigned e1, unsigned e2)
+ {
+ return f.element(e2) < f.element(e1) || (f.element(e1) == f.element(e2) && e2 < e1);
+ }
+
+ private:
+ const I& f;
+ };
+
+ template <typename T, typename I>
+ inline
+ void
+ sort_sites_set_std(const T&, const I& f, util::array<unsigned>& s)
+ {
+ s.reserve(f.domain().nsites());
+
+ mln_pixter(const I) pix(f);
+ for_all(pix)
+ s.append(pix.offset());
+
+ std::vector<unsigned>& v = s.hook_std_vector_();
+ std::sort(v.begin(), v.end(), sort_op_less_<T, I>(f));
+ }
+
+ template <typename T, typename I>
+ static inline
+ void
+ sort_sites_set_dispatch(const mln::trait::value::quant::low&, const T& tree_, const I& f, util::array<unsigned>& s, util::array<unsigned>& levels)
+ {
+ trace::entering("morpho::tree::internal::sort_sites_set_radix");
+ sort_sites_set_radix(tree_, f, s, levels);
+ trace::exiting("morpho::tree::internal::sort_sites_set_radix");
+ }
+
+ template <typename T, typename I>
+ static inline
+ void
+ sort_sites_set_dispatch(const mln::trait::value::quant::any&, const T& tree_, const I& f, util::array<unsigned>& s, util::array<unsigned>& levels)
+ {
+ (void) levels;
+ trace::entering("morpho::tree::internal::sort_sites_set_std");
+ sort_sites_set_std(tree_, f, s);
+ trace::exiting("morpho::tree::internal::sort_sites_set_std");
+ }
+
+
+ template <typename T, typename I>
+ static inline
+ void
+ sort_sites_set(const T& tree_, const I& f, util::array<unsigned>& s, util::array<unsigned>& levels)
+ {
+ sort_sites_set_dispatch(mln_trait_value_quant(mln_value(I)) (), tree_, f, s, levels);
+ }
+
+ template <typename T>
+ static inline
+ unsigned
+ zfind_root(T& zpar, unsigned x)
+ {
+ mlc_equal(mln_value(T), unsigned)::check();
+ if (zpar.element(x) == x)
+ return x;
+ else
+ return zpar.element(x) = zfind_root(zpar, zpar.element(x));
+ }
+
+
+ } // end of namespace mln::morpho::tree::internal
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I, typename F>
+ static inline
+ void
+ union_find_fast_process2_(const I& f, const util::array<int>& dp,
+ F& parent, F& area, F& zpar,
+ unsigned& nnodes, unsigned p)
+ {
+ // Make set.
+ const unsigned n_nbhs = dp.nelements();
+
+ parent.element(p) = p;
+ zpar.element(p) = p;
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+
+ if (zpar.element(n) == 0) // not deja-vu
+ continue;
+
+ unsigned r = internal::zfind_root(zpar, n);
+ if (r != p)
+ {
+ parent.element(r) = p;
+ zpar.element(r) = p;
+ area.element(p) += area.element(r);
+ if (f.element(r) != f.element(p))
+ ++area.element(p);
+ else
+ --nnodes;
+ }
+ }
+ }
+
+
+ template <typename I, typename F>
+ static inline
+ unsigned
+ union_find_fast_process(const mln::trait::value::quant::low&, const I& f, const util::array<int>& dp,
+ F& parent, F& area, F& zpar,
+ const util::array<unsigned>& s, const util::array<unsigned>& levels)
+ {
+ trace::entering("morpho::tree::impl::union_find_fast_process_low");
+ static const unsigned nvalues = mln_card(mln_value(I));
+
+ unsigned nnodes = f.domain().nsites();
+
+ for (int v = nvalues - 1; v >= 0; --v) // Reverse
+ {
+ for (int i = levels[v + 1] - 1; i >= (int)levels[v]; --i) // Reverse
+ union_find_fast_process2_(f, dp, parent, area, zpar, nnodes, s[i]);
+
+ // Fast root compression
+ for (unsigned i = levels[v]; i < levels[v + 1]; ++i) // Direct
+ {
+ unsigned p = s[i];
+ zpar.element(p) = zpar.element(zpar.element(p));
+ }
+ }
+
+ trace::exiting("morpho::tree::impl::union_find_fast_process_low");
+ return nnodes;
+ }
+
+ template <typename I, typename F>
+ static inline
+ unsigned
+ union_find_fast_process(const trait::value::quant::any&, const I& f, const util::array<int>& dp,
+ F& parent, F& area, F& zpar,
+ const util::array<unsigned>& s, const util::array<unsigned>&)
+ {
+ trace::entering("morpho::tree::impl::union_find_fast_process_any");
+
+ unsigned nnodes = f.domain().nsites();
+ for (int i = s.size() - 1; i >= 0; --i) // Reverse
+ union_find_fast_process2_(f, dp, parent, area, zpar, nnodes, s[i]);
+
+ trace::exiting("morpho::tree::impl::union_find_fast_process_any");
+ return nnodes;
+ }
+
+
+ template <typename T, typename I, typename N>
+ util::ctree::ctree<I>
+ union_find_fast(const tag::tree::tree_t<T>&,
+ const Image<I>& f_,
+ const Neighborhood<N>& nbh_)
+ {
+ trace::entering("morpho::tree::impl::generic::union_find_fast");
+
+ typedef p_array<mln_psite(I)> S;
+ typedef mln_value(I) V;
+
+ const I& f = exact(f_);
+ const N& nbh = exact(nbh_);
+ util::array< unsigned > s;
+ util::array< unsigned > levels;
+ internal::sort_sites_set(T (), f, s, levels);
+
+ util::array<int> dp = offsets_wrt(f, nbh);
+
+ // Auxiliary data.
+ mln_ch_value(I, unsigned) parent;
+ mln_ch_value(I, unsigned) area;
+ mln_ch_value(I, unsigned) zpar;
+
+ initialize(parent, f);
+ initialize(area, f);
+ initialize(zpar, f);
+
+ // Initialization.
+ data::fill(zpar, 0);
+ data::fill(area, 0);
+
+ unsigned nnodes =
+ union_find_fast_process(mln_trait_value_quant(V) (), f, dp, parent, area, zpar, s, levels);
+
+ util::ctree::ctree<I> tree;
+ tree.reserve(f, nnodes);
+
+ unsigned root_offset = 0;
+ for (unsigned i = 0; i < s.size(); ++i) // Forward
+ {
+ unsigned p = s[i];
+ unsigned q = parent.element(p);
+
+ if (f.element(parent.element(q)) == f.element(q)) // Canonization
+ q = (parent.element(p) = parent.element(q));
+
+ if (f.element(p) == f.element(q) && p != q) // Not a node.
+ {
+ mln_assertion(q == parent.element(p));
+ tree.data_->map_.element(p) =
+ tree.data_->map_.element(q);
+ }
+ else
+ {
+ unsigned& offset = (p == q) ? root_offset : area.element(q);
+
+ // Insert Node.
+ mln_assertion(offset < nnodes);
+ tree.data_->map_.element(p) = offset;
+ tree.data_->parent_[offset] = tree.data_->map_.element(q);
+ tree.data_->values_[offset] = f.element(p);
+ tree.data_->length_[offset] = area.element(p);
+ area.element(p) = offset + 1;
+ offset += tree.data_->length_[offset] + 1;
+ }
+ }
+
+ trace::exiting("morpho::tree::impl::generic::union_find_fast");
+ return tree;
+ }
+
+ } // end of namespace mln::morpho::tree::impl::generic
+
+ } // end of namespace mln::morpho::tree::impl
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::tree
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif // !MLN_MORPHO_TREE_IMPL_UNION_FIND_FAST_HH
diff --git a/milena/mln/morpho/tree/leaf_last.hh b/milena/mln/morpho/tree/leaf_last.hh
new file mode 100644
index 0000000..2f283d5
--- /dev/null
+++ b/milena/mln/morpho/tree/leaf_last.hh
@@ -0,0 +1,111 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena 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 Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project 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_LEAF_LAST_HH
+# define MLN_MORPHO_TREE_LEAF_LAST_HH
+
+# include <mln/accu/stat/max.hh>
+# include <mln/util/ctree/ctree.hh>
+# include <mln/morpho/tree/propagate_node.hh>
+# include <mln/convert/to_p_array.hh>
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ namespace tree
+ {
+
+ template <typename T, typename V>
+ util::array<typename T::node_t>
+ leaf_last(const attribute_image<T, V>& ima);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename T, typename V>
+ struct less_
+ {
+ typedef typename T::node_t node_t;
+
+ less_(const attribute_image<T, V>& img) :
+ f_ (img)
+ {
+ }
+
+ bool operator() (const node_t& lhs, const node_t& rhs)
+ {
+ return f_(lhs) > f_(rhs);
+ }
+
+ private:
+ const attribute_image<T, V>& f_;
+ };
+ }
+
+ template <typename T, typename V>
+ util::array<typename T::node_t>
+ leaf_last(const attribute_image<T, V>& ima)
+ {
+ typedef attribute_image<T, V> A;
+ typedef typename T::node_t node_t;
+
+ p_array<node_t> sorted_sites = convert::to_p_array(ima);
+ std::vector<node_t>& hook = sorted_sites.hook_std_vector_();
+ std::sort(hook.begin(), hook.end(), internal::less_<T, V> (ima));
+
+ mln_ch_value(A, char) deja_vu;
+ initialize(deja_vu, ima);
+ data::fill(deja_vu, 0);
+
+ util::array<node_t> result;
+
+ mln_piter(p_array<node_t>) n(sorted_sites);
+ for_all(n)
+ {
+ if (deja_vu(n))
+ continue;
+ result.append(n);
+ deja_vu(n) = true; // useless
+ propagate_node_to_descendants<T, char>(deja_vu, n, 1);
+ propagate_node_to_ancestors<T, char>(deja_vu, n, 1);
+ }
+
+ return result;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho::tree
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+#endif // !MLN_MORPHO_TREE_LEAF_LAST_HH
diff --git a/milena/mln/morpho/tree/propagate_node.hh b/milena/mln/morpho/tree/propagate_node.hh
index 7778905..76f2410 100644
--- a/milena/mln/morpho/tree/propagate_node.hh
+++ b/milena/mln/morpho/tree/propagate_node.hh
@@ -26,14 +26,27 @@
#ifndef MLN_MORPHO_TREE_PROPAGATE_NODE_HH
# define MLN_MORPHO_TREE_PROPAGATE_NODE_HH
-# include <mln/core/concept/image.hh>
-# include <mln/core/macros.hh>
-# include <mln/morpho/tree/data.hh>
-
/// \file
///
/// Functions to propagate node in the tree.
+///
+/// \todo: The new implementation permits: + to propagate toward
+/// subcomponents very fast (data::fill)\ + to propagate toward
+/// supernodes as fast as the previous component\ + the attribute
+/// image is still valid without the use of propagate_representative
+/// that does not make sense any more.
+///
+/// We are able in both cases to do something like:
+/// + data::fill(attr_img | asc(n), v)
+/// + data::fill(attr_img | desc(n), v)
+///
+/// However the subimage morpher is not specialized for fast image and
+/// does not take benefits in the fact that:
+/// + desc(n) is a p_run (so can be memseté)
+/// + attr_img can accessed by indexed (element() method for fast-image)
+# include <mln/core/image/attribute_image.hh>
+# include <algorithm>
namespace mln
{
@@ -44,166 +57,52 @@ namespace mln
namespace tree
{
- /*!
- ** Propagate a value \p v from a node \p n to its descendants.
- **
- ** \param[in] n Node to propagate.
- ** \param[in] t Component tree used for propagation.
- ** \param[in] a_ Attribute image where values are propagated.
- ** \param[in] v Value to propagate.
- ** \param[out] nb_leaves Optional. Store the number of leaves in
- ** the component.
- */
- template <typename T, typename A>
- void
- propagate_node_to_descendants(mln_psite(A) n,
- const T& t,
- Image<A>& a_,
- const mln_value(A)& v,
- unsigned* nb_leaves = 0);
-
- /*!
- ** Propagate the node's value to its descendants.
- **
- ** \param[in] n Node to propagate.
- ** \param[in] t Component tree used for propagation.
- ** \param[in] a_ Attribute image where values are propagated.
- ** \param[out] nb_leaves Optional. Store the number of leaves in
- ** the component.
- */
- template <typename T, typename A>
- inline
- void
- propagate_node_to_descendants(mln_psite(A)& n,
- const T& t,
- Image<A>& a_,
- unsigned* nb_leaves = 0);
-
-
- /*!
- ** Propagate a value \p v from a node \p n to its ancestors.
- **
- ** \param[in] n Node to propagate.
- ** \param[in] t Component tree used for propagation.
- ** \param[in] a_ Attribute image where values are propagated.
- ** \param[in] v Value to propagate.
- */
- template <typename T, typename A>
- void
- propagate_node_to_ancestors(mln_psite(A) n,
- const T& t,
- Image<A>& a_,
- const mln_value(A)& v);
-
- /*!
- ** Propagate the node's value to its ancestors.
- **
- ** \param[in] n Node to propagate.
- ** \param[in] t Component tree used for propagation.
- ** \param[in,out] a_ Attribute image where values are propagated.
- */
- template <typename T, typename A>
- inline
- void
- propagate_node_to_ancestors(mln_psite(A) n,
- const T& t,
- Image<A>& a_);
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- /* Descendants propagation */
-
- template <typename T, typename A>
+ template <typename T, typename V>
inline
- void
- propagate_node_to_descendants(mln_psite(A) n,
- const T& t,
- Image<A>& a_,
- const mln_value(A)& v,
- unsigned* nb_leaves = 0)
+ unsigned
+ propagate_node_to_descendants(attribute_image<T, V>& a,
+ const typename T::node_t& n,
+ const V& value)
{
- A& a = exact(a_);
+ typedef typename T::nodes_t desc_t;
mln_precondition(a.is_valid());
- mln_precondition(a.domain() == t.f().domain());
- mln_precondition(a.domain().has(n));
-
-
- if (!t.is_a_node(n)) // Get the representant.
- n = t.parent(n);
- mln_assertion(t.is_a_node(n));
-
- typename T::depth1st_piter pp(t, n);
-
- pp.start(); // We don't set n to v.
+ mln_precondition(a.has(n));
- if (nb_leaves)
- *nb_leaves += t.is_a_leaf(pp);
+ // (n € desc(n)) but we don't set its value.
+ unsigned i = a.tree().desc(n).nsites();
- for (pp.next(); pp.is_valid(); pp.next())
+ if (i > 1)
{
- a(pp) = v;
- if (nb_leaves && t.is_a_leaf(pp))
- ++(*nb_leaves);
+ mln_assertion(a.tree().has_index(n.index() + i));
+ V* v = a.buffer() + n.index();
+ std::fill(v + 1, v + i, value);
}
+ return i - 1;
}
-
- template <typename T, typename A>
+ template <typename T, typename V>
inline
- void
- propagate_node_to_descendants(mln_psite(A) n,
- const T& t,
- Image<A>& a_,
- unsigned* nb_leaves = 0)
-
- {
- A& a = exact(a_);
- propagate_node_to_descendants(n, t, a, a(n), nb_leaves);
- }
-
-
- /* Ancestors propagation */
-
- template <typename T, typename A>
- void
- propagate_node_to_ancestors(mln_psite(A) n,
- const T& t,
- Image<A>& a_,
- const mln_value(A)& v)
+ unsigned
+ propagate_node_to_ancestors(attribute_image<T, V>& a,
+ typename T::node_t n,
+ const V& v)
{
- A& a = exact(a_);
mln_precondition(a.is_valid());
- mln_precondition(a.domain() == t.f().domain());
- mln_precondition(a.domain().has(n));
+ mln_precondition(a.has(n));
- if (!t.is_a_node(n)) // Get the representant.
- n = t.parent(n);
- mln_assertion(t.is_a_node(n));
-
- if (t.is_root(n))
- return;
+ if (a.tree().is_a_root(n))
+ return 0;
+ unsigned i = 0;
do {
- n = t.parent(n);
+ n = a.tree().parent(n);
a(n) = v;
- } while (!t.is_root(n));
-
- }
+ ++i;
+ } while (!a.tree().is_a_root(n));
- template <typename T, typename A>
- inline
- void
- propagate_node_to_ancestors(mln_psite(A) n,
- const T& t,
- Image<A>& a_)
- {
- A& a = exact(a_);
- propagate_node_to_ancestors(n, t, a, a(n));
+ return i;
}
-# endif // ! MLN_INCLUDE_ONLY
-
} // end of namespace mln::morpho::tree
} // end of namespace mln::morpho
diff --git a/milena/mln/tag/skeleton.hh b/milena/mln/tag/skeleton.hh
index f446317..bca9b4f 100644
--- a/milena/mln/tag/skeleton.hh
+++ b/milena/mln/tag/skeleton.hh
@@ -44,6 +44,7 @@ namespace mln
template <typename F> struct function_ { typedef F param; };
template <typename G> struct graph_ { typedef G param; };
template <typename I> struct image_ { typedef I param; };
+ template <typename T> struct tree_ { typedef T param; };
template <typename N> struct neighb_ { typedef N param; };
template <typename P> struct psite_ { typedef P param; };
template <typename S> struct domain_ { typedef S param; };
diff --git a/milena/mln/util/hqueues.hh b/milena/mln/util/hqueues.hh
index 151c71c..35c7a50 100644
--- a/milena/mln/util/hqueues.hh
+++ b/milena/mln/util/hqueues.hh
@@ -55,6 +55,7 @@ namespace mln
nvalues = mln_card(T)
};
+ hqueues();
hqueues(const histo::array<T>& h);
const p_queue_fast<P>& operator[](unsigned i) const;
@@ -66,38 +67,29 @@ namespace mln
const mln::value::set<T>& vset() const;
protected:
- void pre_allocate_(unsigned i);
-
- const histo::array<T>& h_;
const mln::value::set<T>& s_;
- std::vector<bool> allocated_;
std::vector< p_queue_fast<P> >queues_;
};
# ifndef MLN_INCLUDE_ONLY
-
template <typename P, typename T>
inline
- hqueues<P,T>::hqueues(const histo::array<T>& h)
- : h_ (h),
- s_ (mln::value::set<T>::the()),
- allocated_ (nvalues, false),
- queues_ (nvalues)
+ hqueues<P,T>::hqueues()
+ : s_ (mln::value::set<T>::the())
{
+ queues_.resize(nvalues);
}
+
template <typename P, typename T>
inline
- void
- hqueues<P,T>::pre_allocate_(unsigned i)
+ hqueues<P,T>::hqueues(const histo::array<T>& h)
+ : s_ (mln::value::set<T>::the())
{
- mln_precondition(i < nvalues);
- if (!allocated_[i])
- {
- queues_[i].reserve(h_[i]);
- allocated_[i] = true;
- }
+ queues_.resize(nvalues);
+ for (unsigned i = 0; i < nvalues; ++i)
+ queues_[i].reserve(h[i]);
}
@@ -107,7 +99,6 @@ namespace mln
hqueues<P,T>::operator[](unsigned i) const
{
mln_precondition(i < nvalues);
- pre_allocate_(i);
return queues_[i];
}
@@ -117,7 +108,6 @@ namespace mln
hqueues<P,T>::operator[](unsigned i)
{
mln_precondition(i < nvalues);
- pre_allocate_(i);
return queues_[i];
}
@@ -127,7 +117,6 @@ namespace mln
hqueues<P,T>::operator()(const T& v) const
{
unsigned i = s_.index_of(v);
- pre_allocate_(i);
return queues_[i];
}
@@ -137,7 +126,6 @@ namespace mln
hqueues<P,T>::operator()(const T& v)
{
unsigned i = s_.index_of(v);
- pre_allocate_(i);
return queues_[i];
}
--
1.5.6.5
1
0
04 May '10
---
scribo/ChangeLog | 17 ++++++++++-------
scribo/text/merging.hh | 2 +-
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/scribo/ChangeLog b/scribo/ChangeLog
index 59f9e67..67159ad 100644
--- a/scribo/ChangeLog
+++ b/scribo/ChangeLog
@@ -1,18 +1,21 @@
2010-05-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+ * text/merging.hh: Disable some debug.
+
+2010-05-04 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Prepare DIA tools for Nuxeo/XWiki.
- * scribo/src/Makefile.am: Add a new target.
+ * src/Makefile.am: Add a new target.
- * scribo/src/text_in_article_preprocess.cc: New.
+ * src/text_in_article_preprocess.cc: New.
- * scribo/src/text_in_article_pbm.cc: Add optional cropping and
- makes the debug optionnal.
+ * src/text_in_article_pbm.cc: Add optional cropping and makes the
+ debug optionnal.
- * scribo/text/clean.hh: Improve cleanup.
+ * text/clean.hh: Improve cleanup.
- * scribo/text/recognition.hh: Remove last '\n' in Tesseract's
- output.
+ * text/recognition.hh: Remove last '\n' in Tesseract's output.
2010-04-30 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/scribo/text/merging.hh b/scribo/text/merging.hh
index b29e63f..5309b10 100644
--- a/scribo/text/merging.hh
+++ b/scribo/text/merging.hh
@@ -606,7 +606,7 @@ namespace scribo
if (lines(mc).type() == line::Text) // included in a text line => weird
{
++count_txtline_IN_txtline;
- std::cout << "weird: inclusion of a txt_line in a txt_line!" << std::endl;
+// std::cout << "weird: inclusion of a txt_line in a txt_line!" << std::endl;
/// Merge is perform if the current line is a
/// petouille considered as a line.
--
1.5.6.5
1
0