URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-03-19 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Optimize propagations and add component processing functions.
* mln/morpho/tree/data.hh: Add optimization about preorder
iterator.
* tests/morpho/tree/data.cc: Update test file.
* sandbox/edwin/tree/accumulator/arg_max.hh: New accumulator
that returns site having the max value.
* sandbox/edwin/tree/accumulator/max.hh: Remove.
* sandbox/edwin/tree/propagate.hh: Make clean.
* sandbox/edwin/tree/propagate_if.hh: Functions performing
different propagations on nodes matching a predicate.
* sandbox/edwin/tree/propagate_node.hh: Basic ascendant and
descendant propagations computation.
* sandbox/edwin/tree/propagation.cc: Test file for propagations.
* sandbox/edwin/tree/routines.hh: Remove.
* sandbox/edwin/tree/run.hh: Methods to apply accumulator on
tree nodes, and to perform object component research with a
criteria (treshold...).
* sandbox/edwin/tree/test.cc: New.
---
mln/morpho/tree/data.hh | 134 ++++++++++--
sandbox/edwin/tree/Makefile | 6
sandbox/edwin/tree/accumulator/arg_max.hh | 160 +++++++++++++++
sandbox/edwin/tree/propagate.hh | 102 ---------
sandbox/edwin/tree/propagate_if.hh | 320 ++++++++++++++++++++++++++++++
sandbox/edwin/tree/propagate_node.hh | 46 ++--
sandbox/edwin/tree/propagation.cc | 82 ++++---
sandbox/edwin/tree/run.hh | 272 +++++++++++++++++++++++++
sandbox/edwin/tree/test.cc | 98 +++++++++
tests/morpho/tree/data.cc | 14 +
10 files changed, 1052 insertions(+), 182 deletions(-)
Index: trunk/milena/tests/morpho/tree/data.cc
===================================================================
--- trunk/milena/tests/morpho/tree/data.cc (revision 3551)
+++ trunk/milena/tests/morpho/tree/data.cc (revision 3552)
@@ -65,11 +65,18 @@
/* Check site and node up order */
tree_t::up_node_piter n(t);
tree_t::up_site_piter s(t);
+ tree_t::up_leaf_piter l(t);
n.start();
+ l.start();
for_all(s)
if (t.is_a_node(s))
{
mln_assertion(s == n);
+ if (t.is_a_leaf(n))
+ {
+ mln_assertion(l == n);
+ l.next();
+ }
n.next();
}
mln_assertion(!n.is_valid());
@@ -79,11 +86,18 @@
/* Check site and node up order */
tree_t::dn_node_piter n(t);
tree_t::dn_site_piter s(t);
+ tree_t::dn_leaf_piter l(t);
n.start();
+ l.start();
for_all(s)
if (t.is_a_node(s))
{
mln_assertion(s == n);
+ if (t.is_a_leaf(n))
+ {
+ mln_assertion(l == n);
+ l.next();
+ }
n.next();
}
mln_assertion(!n.is_valid());
Index: trunk/milena/mln/morpho/tree/data.hh
===================================================================
--- trunk/milena/mln/morpho/tree/data.hh (revision 3551)
+++ trunk/milena/mln/morpho/tree/data.hh (revision 3552)
@@ -47,12 +47,16 @@
# define mln_dn_site_piter(T) typename T::dn_site_piter
# define mln_up_node_piter(T) typename T::up_node_piter
# define mln_dn_node_piter(T) typename T::dn_node_piter
+# define mln_up_leaf_piter(T) typename T::up_leaf_piter
+# define mln_dn_leaf_piter(T) typename T::dn_leaf_piter
# define mln_preorder_piter(T) typename T::preorder_piter
# define mln_up_site_piter_(T) T::up_site_piter
# define mln_dn_site_piter_(T) T::dn_site_piter
# define mln_up_node_piter_(T) T::up_node_piter
# define mln_dn_node_piter_(T) T::dn_node_piter
+# define mln_up_leaf_piter_(T) T::up_leaf_piter
+# define mln_dn_leaf_piter_(T) T::dn_leaf_piter
# define mln_preorder_piter_(T) T::preorder_piter
namespace mln
@@ -78,6 +82,12 @@
/// Iterate on tree's nodes (component representants) from leaves to roots.
template <typename T> struct dn_node_piter;
+ /// Iterate on tree's leaves in the same way of up_node_piter.
+ template <typename T> struct up_leaf_piter;
+
+ /// Iterate on tree's leaves in the same way of dn_node_piter.
+ template <typename T> struct dn_leaf_piter;
+
/// Preorder tree traversal iterator.
template <typename T> struct preorder_piter;
@@ -101,8 +111,10 @@
typedef mln_site(I) site;
/// Site set associated type.
typedef S sites_t;
- /// Node list associated type.
+ /// Node set associated type.
typedef p_array<mln_psite(I)> nodes_t;
+ /// Leaf set associated type.
+ typedef p_array<mln_psite(I)> leaves_t;
/// Parent image associated type.
typedef mln_ch_value(I, mln_psite(I)) parent_t;
@@ -115,6 +127,10 @@
typedef mln::morpho::tree::up_node_piter<self_> up_node_piter;
typedef mln::morpho::tree::dn_node_piter<self_> dn_node_piter;
+ // Iterate on leaves only.
+ typedef mln::morpho::tree::up_leaf_piter<self_> up_leaf_piter;
+ typedef mln::morpho::tree::dn_leaf_piter<self_> dn_leaf_piter;
+
typedef mln::morpho::tree::preorder_piter<self_> preorder_piter;
// typedef mln_bkd_piter(S) piter;
@@ -123,7 +139,7 @@
/// Constructor.
template <typename N>
- explicit data(const Image<I>& f, const Site_Set<S>& s, const
Neighborhood<N>& nbh);
+ data(const Image<I>& f, const Site_Set<S>& s, const
Neighborhood<N>& nbh);
@@ -134,32 +150,46 @@
/// \}
+ /// \{ Child-related materials.
+
const p_array<mln_psite(I)>& children(const mln_psite(I)& p) const;
const mln_ch_value(I, nodes_t)& children_image() const;
- /// \{ Tests.
+ /// \}
- bool is_valid() const;
- bool is_root(const mln_psite(I)& p) const;
- bool is_a_node(const mln_psite(I)& p) const;
- bool is_a_non_root_node(const mln_psite(I)& p) const;
- bool is_a_leaf(const mln_psite(I)& p) const;
+ /// \{ Nodes materials.
- /// \}
+ const p_array<mln_psite(I)>& nodes() const;
+ /// \}
- /// \{ Nodes-related materials.
+ /// \{ Leaves materials.
- const p_array<mln_psite(I)>& nodes() const;
+ const p_array<mln_psite(I)>& leaves() const;
/// \}
- /// \{ Sites-related materials.
+ /// \{ Sites materials.
const S& domain() const;
/// \}
+
+
+ /// \{ Tests.
+
+ bool is_valid() const;
+ bool is_root(const mln_psite(I)& p) const;
+ bool is_a_node(const mln_psite(I)& p) const;
+ bool is_a_non_root_node(const mln_psite(I)& p) const;
+ bool is_a_leaf(const mln_psite(I)& p) const;
+
+ /// \}
+
+
+
+
unsigned nroots() const;
@@ -175,10 +205,13 @@
mln_ch_value(I, mln_psite(I)) parent_; // Parent image.
mln_ch_value(I, nodes_t) children_; // Children image.
nodes_t nodes_;
+ leaves_t leaves_;
unsigned nroots_;
};
+ /* Iterators */
+
template <typename T>
struct up_site_piter
: public mln::internal::piter_identity_< typename T::sites_t::bkd_piter, // Adaptee.
@@ -227,7 +260,7 @@
up_node_piter<T> > // Exact.
{
private:
- typedef typename T::sites_t::fwd_piter Pi_;
+ typedef typename T::nodes_t::fwd_piter Pi_;
typedef mln::internal::piter_identity_< Pi_, up_node_piter<T> > super_;
public:
@@ -248,7 +281,7 @@
dn_node_piter<T> > // Exact.
{
private:
- typedef typename T::sites_t::bkd_piter Pi_;
+ typedef typename T::nodes_t::bkd_piter Pi_;
typedef mln::internal::piter_identity_< Pi_, dn_node_piter<T> > super_;
public:
@@ -264,6 +297,48 @@
};
template <typename T>
+ struct up_leaf_piter
+ : public mln::internal::piter_identity_< typename T::leaves_t::fwd_piter, //
Adaptee.
+ up_leaf_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::leaves_t::fwd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, up_leaf_piter<T> > super_;
+
+ public:
+ up_leaf_piter(const T& t)
+ {
+ this->change_target(t.leaves());
+ }
+
+ up_leaf_piter(const Pi_& pi)
+ : super_(pi)
+ {
+ }
+ };
+
+ template <typename T>
+ struct dn_leaf_piter
+ : public mln::internal::piter_identity_< typename T::leaves_t::bkd_piter, //
Adaptee.
+ dn_leaf_piter<T> > // Exact.
+ {
+ private:
+ typedef typename T::leaves_t::bkd_piter Pi_;
+ typedef mln::internal::piter_identity_< Pi_, dn_leaf_piter<T> > super_;
+
+ public:
+ dn_leaf_piter(const T& t)
+ {
+ this->change_target(t.leaves());
+ }
+
+ dn_leaf_piter(const Pi_& pi)
+ : super_(pi)
+ {
+ }
+ };
+
+ template <typename T>
class preorder_piter
: public mln::internal::site_set_iterator_base< T, preorder_piter<T> >
{
@@ -294,6 +369,9 @@
/// Go to the next point.
void next_();
+ /// Skip current point children. Next call to next() goes to the brother point.
+ void skip_children();
+
protected:
using super_::p_;
using super_::s_;
@@ -328,11 +406,14 @@
{
nodes_.insert(p);
children_(parent_(p)).insert(p);
+ if (is_a_leaf(p))
+ leaves_.insert(p);
}
- else
- if (parent_(p) == p)
+ else if (parent_(p) == p) //it's a root.
{
nodes_.insert(p);
+ if (is_a_leaf(p)) // One pixel image...
+ leaves_.insert(p);
++nroots_;
}
}
@@ -418,6 +499,15 @@
template <typename I, typename S>
inline
+ const p_array<mln_psite(I)>&
+ data<I,S>::leaves() const
+ {
+ mln_precondition(is_valid());
+ return leaves_;
+ }
+
+ template <typename I, typename S>
+ inline
const S&
data<I,S>::domain() const
{
@@ -490,6 +580,7 @@
const mln_psite(T::function)& p)
: root_ (&p)
{
+ mln_assertion(t.is_a_node(p));
this->change_target(t);
}
@@ -522,7 +613,7 @@
else
{
mln_dn_node_piter(T) n(*s_);
- int roots = 0;
+ unsigned roots = 0;
for (n.start(); n.is_valid() && roots < s_->nroots(); n.next())
if (s_->is_root(n))
{
@@ -548,6 +639,15 @@
stack_.push_back(child);
}
+ template <typename T>
+ inline
+ void
+ preorder_piter<T>::skip_children()
+ {
+ while (stack_.size() != 1 && s_->parent(stack_.back()) == p_)
+ stack_.pop_back();
+ }
+
# endif // ! MLN_INCLUDE_ONLY
Index: trunk/milena/sandbox/edwin/tree/routines.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/accumulator/max.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/accumulator/arg_max.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/accumulator/arg_max.hh (revision 0)
+++ trunk/milena/sandbox/edwin/tree/accumulator/arg_max.hh (revision 3552)
@@ -0,0 +1,160 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_TREE_ACCUMULATOR_ARG_MAX_HH_
+# define MLN_MORPHO_TREE_ACCUMULATOR_ARG_MAX_HH_
+
+/// \file mln/morpho/tree/accumulator/arg_max.hh
+///
+/// Define an accumulator that performs arg max.
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/accu/internal/base.hh>
+# include <mln/util/pix.hh>
+
+namespace mln {
+ namespace accumulator {
+
+ template <typename I>
+ class arg_max : public mln::accu::internal::base<const mln_psite(I)&,
arg_max<I> >
+ {
+ typedef mln::accu::internal::base<const mln_psite(I)&, arg_max<I> >
super_;
+
+ public:
+ typedef typename util::pix<I> argument;
+
+ /// Constructor
+ arg_max(const Image<I>& ima);
+ /// Destructor
+ ~arg_max();
+
+ /// Manipulators.
+ /// \{
+ void init();
+
+ void take(const argument& pix);
+ void take(const arg_max<I>& other);
+
+ void take_as_init(const argument& pix);
+ /// \}
+
+ /// Get the value of the accumulator.
+ const mln_psite(I)& to_result() const;
+
+ /// Check whether the accumulator is able to give a result.
+ bool is_valid() const;
+
+ private:
+ const I& ima_;
+ mln_psite(I)* p_;
+ };
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ arg_max<I>::arg_max(const Image<I>& ima) :
+ ima_ (exact(ima)),
+ p_ (0)
+ {
+ }
+
+ template <typename I>
+ inline
+ arg_max<I>::~arg_max()
+ {
+ delete p_;
+ }
+
+
+ template <typename I>
+ inline
+ void
+ arg_max<I>::init()
+ {
+ }
+
+ template <typename I>
+ inline
+ void
+ arg_max<I>::take(const argument& pix)
+ {
+ if (!is_valid())
+ {
+ take_as_init(pix);
+ return;
+ }
+
+ if (pix.v() > ima_(*p_))
+ *p_ = pix.p();
+ }
+
+ template <typename I>
+ inline
+ void
+ arg_max<I>::take(const arg_max<I>& other)
+ {
+ mln_invariant(other.is_valid());
+
+ if (other.ima_(*other.p_) > ima_(*p_))
+ *p_ = *other.p_;
+ }
+
+ template <typename I>
+ inline
+ void
+ arg_max<I>::take_as_init(const argument& pix)
+ {
+ p_ = new mln_psite(I)(pix.p());
+ }
+
+ template <typename I>
+ inline
+ const mln_psite(I)&
+ arg_max<I>::to_result() const
+ {
+ mln_invariant(p_ != 0);
+ return *p_;
+ }
+
+ template <typename I>
+ inline
+ bool
+ arg_max<I>::is_valid() const
+ {
+ return p_ != 0;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accumulator
+ } // end of namespace mln
+
+#endif /* ! MLN_MORPHO_TREE_ACCUMULATOR_ARG_MAX_HH_ */
Index: trunk/milena/sandbox/edwin/tree/propagate.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3551)
+++ trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3552)
@@ -46,7 +46,7 @@
propagate_representant(const T& t, Image<A>& a_)
{
A a = exact(a_);
- mln_fwd_piter(T) p(t.domain());
+ mln_up_site_piter(T) p(t);
for_all(p)
if (! t.is_a_node(p))
{
@@ -55,106 +55,6 @@
}
}
-
-
-
-
- /// Dans le cas des images binaires...
- /// Propagate a tagged node's value to its subbranches.
- template <typename T, typename A>
- void
- propagate_to_childhood(const T& t, A& a)
- {
- mln_bkd_piter(T::nodes_t) n(t.nodes());
- for_all(n)
- {
- if (a(t.parent(n)))
- {
- mln_assertion(t.is_a_node(t.parent(n)));
- a(n) = a(t.parent(n));
- }
- }
- }
-
-
- /// Propagate a tagged node's value to its direct children.
- template <typename T, typename A>
- void
- propagate_to_children(const T& t, A& a)
- {
- mln_fwd_piter(T::nodes_t) n(t.nodes());
- for_all(n)
- {
- if (a(t.parent(n)))
- {
- mln_assertion(t.is_a_node(t.parent(n)));
- a(n) = a(t.parent(n));
- }
- }
- }
-
- /// Propagate a tagged node's value to its ancestors.
- template <typename T, typename A>
- void
- propagate_to_ancestors(const T& t, A& a)
- {
- mln_fwd_piter(T::nodes_t) n(t.nodes());
- for_all(n)
- {
- if (a(n))
- {
- mln_assertion(t.is_a_node(t.parent(n)));
- a(t.parent(n)) = a(n);
- }
- }
- }
-
- /// Propagate a tagged node's value to its direct parents.
- template <typename T, typename A>
- void
- propagate_to_parent(const T& t, A& a)
- {
- mln_bkd_piter(T::nodes_t) n(t.nodes());
- for_all(n)
- {
- mln_assertion(t.is_a_node(n));
- if (a(n))
- {
- mln_assertion(t.is_a_node(t.parent(n)));
- a(t.parent(n)) = a(n);
- }
- }
- }
-
- /// Propagate a tagged leaf's value to its ancestors.
- /// In others words, tag the branch which the tagged leaf belongs to.
- /// At the end, the tree should get this property:
- /// for all n
- /// a(n) is true iff there exits an l in tree's leaves such that
- /// n <== l and a(l) is true.
- /// TODO: post-condition which checks this property.
-
-
- template <typename T, typename A>
- void
- propagate_leaf_to_ancestors(const T& t, A& a)
- {
-
- mln_fwd_piter(T::leaves_t) l(t.leaves());
- for_all(l)
- a(t.parent(l)) = 0;
-
-
- mln_fwd_piter(T::nodes_t) n(t.nodes());
- for_all(n)
- {
- mln_assertion(t.is_a_node(t.parent(n)));
- a(t.parent(n)) = a(t.parent(n)) || a(n);
- }
- }
-
-
-
} // end of namespace mln::morpho::tree
} // end of namespace mln::morpho
} // end of namespace mln
Index: trunk/milena/sandbox/edwin/tree/run.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/run.hh (revision 0)
+++ trunk/milena/sandbox/edwin/tree/run.hh (revision 3552)
@@ -0,0 +1,272 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_TREE_PROPAGATE_RUN_HH_
+# define MLN_MORPHO_TREE_PROPAGATE_RUN_HH_
+
+# include <mln/core/concept/accumulator.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+
+# include <mln/core/site_set/p_array.hh>
+# include <mln/util/pix.hh>
+
+# include "propagate_node.hh"
+
+namespace mln {
+ namespace morpho {
+ namespace tree {
+
+
+ /**
+ ** Traverse component tree \p tree and provide tree nodes values
+ ** to accumulator \p accu_. (Alias to "map")
+ **
+ ** @param tree Component tree used to perform accumulation.
+ ** @param a_ Attributed image.
+ ** @accu_ Accumulator that will be applied on tree nodes.
+ **
+ ** @return The result of accumulation.
+ */
+ template <typename T, typename A, typename I>
+ mln_result(A)
+ run(const T& tree,
+ const Image<I>& a_,
+ Accumulator<A>& accu_);
+
+ /**
+ ** Apply accumulator \accu on tree nodes. If the resulting node of
+ ** accumulation checks predicate \p pred, the node is inserted
+ ** into resulting array, then ascendant and descendant zero-fill
+ ** propagations are performed from the node. These operations
+ ** are repeated until the node won't check predicate.
+ **
+ ** @param tree Component tree used for propagation.
+ ** @param a Attributed image where values are propagated.
+ ** @param accu_ Accumulator to apply on tree.
+ ** @param pred Predicate that must check the result of
+ ** accumulator to propagate the node.
+ **
+ ** @return Array of propagated nodes.
+ */
+ template <typename T, typename A, typename ACC, typename P2B>
+ p_array< mln_psite(A) >
+ run_while(const T& tree,
+ Image<A>& a,
+ Accumulator<ACC>& accu_,
+ Function_p2b<P2B>& pred);
+
+
+ /**
+ ** Apply accumulator \accu on tree nodes values n times.
+ ** Each time, the result of accumulator is inserted
+ ** into the returned array, then ascendant and descendant zero-fill
+ ** propagations are performed from the node.
+ ** (This function is a shorcut of run_while with a cardinality predicate).
+ **
+ ** @param tree Component tree used for propagation.
+ ** @param a Attributed image where values are propagated.
+ ** @param accu_ Accumulator to apply on tree.
+ ** @param n The repetition number.
+ **
+ ** @return Array of propagated nodes.
+ */
+ template <typename T, typename A, typename ACC>
+ inline
+ p_array< mln_psite(A) >
+ run_ntimes(const T& tree,
+ Image<A>& a,
+ Accumulator<ACC>& acc,
+ unsigned n);
+
+ /**
+ ** Apply accumulator \accu on tree nodes value until the value
+ ** accumulated by \p acc get lesser than the treshold \p n.
+ ** Each time, the result of accumulator is inserted
+ ** into the returned array, then ascendant and descendant zero-fill
+ ** propagations are performed from the node.
+ ** (This function is a shorcut of run_while with a treshold predicate).
+ **
+ ** @param tree Component tree used for propagation.
+ ** @param a Attributed image where values are propagated.
+ ** @param accu_ Accumulator to apply on tree.
+ ** @param n Treshold.
+ **
+ ** @return Array of propagated nodes.
+ */
+ template <typename T, typename A, typename ACC>
+ inline
+ p_array< mln_psite(A) >
+ run_while_treshold(const T& tree,
+ Image<A>& a,
+ Accumulator<ACC>& acc,
+ mln_value(A) n);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename T, typename A, typename ACC, typename P2B>
+ p_array< mln_psite(A) >
+ run_while(const T& tree,
+ A& a,
+ ACC& accu,
+ P2B& pred)
+ {
+ mln_psite(A) p;
+ p_array< mln_psite(A) > arr_sites;
+ util::array< mln_value(A) > arr_values;
+
+ do {
+ p = morpho::tree::run(tree, a, accu);
+ if (a(p) == 0) //there's no more objects.
+ break;
+ arr_sites.insert(p);
+ arr_values.append(a(p));
+ morpho::tree::propagate_node_to_descendants(p, tree, a, 0);
+ morpho::tree::propagate_node_to_ancestors(p, tree, a, 0);
+ a(p) = 0;
+ } while (pred(accu.to_result()));
+ for (unsigned i = 0; i < arr_sites.nsites(); i++)
+ a(arr_sites[i]) = arr_values[i];
+ return arr_sites;
+ }
+
+ struct ncard : Function_p2b< ncard >
+ {
+ typedef bool result;
+
+ ncard(unsigned n)
+ : n_ (n)
+ {
+ }
+
+ template <typename P>
+ bool operator()(const P& p)
+ {
+ (void)p;
+ return (n_-- > 0);
+ }
+
+ private:
+ unsigned n_;
+ };
+
+ template <typename I>
+ struct treshold : Function_p2b< treshold<I> >
+ {
+ typedef bool result;
+
+ treshold(const Image<I>& ima,
+ const mln_value(I)& treshold)
+ : ima_ (exact(ima)),
+ treshold_ (treshold)
+ {
+ }
+
+ bool operator()(const mln_psite(I)& p) const
+ {
+ return (ima_(p) > treshold_);
+ }
+
+ private:
+ const I& ima_;
+ const mln_value(I) treshold_;
+ };
+
+
+ } // end of namespace mln::morpho::tree::internal
+
+ template <typename T, typename A, typename ACC, typename P2B>
+ inline
+ p_array< mln_psite(A) >
+ run_while(const T& tree,
+ Image<A>& a_,
+ Accumulator<ACC>& acc,
+ Function_p2b<P2B>& pred)
+ {
+ A& a = exact(a_);
+
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ return internal::run_while(tree, a, exact(acc), exact(pred));
+ }
+
+ template <typename T, typename A, typename ACC>
+ inline
+ p_array< mln_psite(A) >
+ run_ntimes(const T& tree,
+ Image<A>& a,
+ Accumulator<ACC>& acc,
+ unsigned n)
+ {
+ internal::ncard predicate(n - 1);
+ return run_while(tree, a, acc, predicate);
+ }
+
+
+ template <typename T, typename A, typename ACC>
+ inline
+ p_array< mln_psite(A) >
+ run_while_treshold(const T& tree,
+ Image<A>& a,
+ Accumulator<ACC>& acc,
+ mln_value(A) n)
+ {
+ internal::treshold<A> predicate(a, n);
+ return run_while(tree, a, acc, predicate);
+ }
+
+ template <typename T, typename A, typename I>
+ mln_result(A)
+ run(const T& tree,
+ const Image<I>& a_,
+ Accumulator<A>& accu_)
+ {
+ A& accu = exact(accu_);
+ const I& a = exact(a_);
+
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ mln_up_node_piter(T) n(tree);
+ for_all(n)
+ accu.take(make::pix(a, n));
+ return (accu.to_result());
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::morpho::tree
+ } // end of namespace mln::morpho
+} // end of namespace mln
+
+#endif /* !MLN_MORPHO_TREE_PROPAGATE_RUN_HH_ */
Index: trunk/milena/sandbox/edwin/tree/test.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/test.cc (revision 0)
+++ trunk/milena/sandbox/edwin/tree/test.cc (revision 3552)
@@ -0,0 +1,98 @@
+/* mln core */
+#include <mln/core/image/image2d.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/var.hh>
+
+/* Site set */
+#include <mln/core/site_set/p_array.hh>
+#include <mln/level/sort_psites.hh>
+
+/* Component trees */
+#include <mln/morpho/tree/data.hh>
+#include <mln/morpho/tree/compute_attribute_image.hh>
+#include "propagate.hh"
+#include "run.hh"
+#include "accumulator/arg_max.hh"
+
+/* Attributes */
+#include <mln/morpho/attribute/sharpness.hh>
+
+/* io */
+#include <mln/io/pgm/load.hh>
+#include <../../theo/color/change_attributes.hh>
+#include <iostream>
+
+/* std */
+#include <string>
+
+bool mydebug = false;
+
+
+void usage(char** argv)
+{
+ std::cerr << "usage: " << argv[0] << " input
[--debug]" << std::endl;
+ abort();
+}
+
+void dsp(const char* str)
+{
+ std::cout << std::endl
+ << "*********************" << std::endl
+ << "** " << str << std::endl
+ << "*********************" << std::endl;
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+
+ if (argc < 2)
+ usage(argv);
+
+ mydebug = (argc >= 3 && std::string(argv[2]) == "--debug");
+
+
+ /* Image loadin' */
+ typedef image2d<int_u8> I;
+
+ I input;
+ io::pgm::load(input, argv[1]);
+
+ /* Component tree creation */
+ typedef p_array< mln_site_(I) > S;
+ typedef morpho::tree::data<I,S> tree_t;
+
+ S sorted_sites = level::sort_psites_decreasing(input);
+ tree_t tree(input, sorted_sites, c4());
+
+ /* Compute Attribute On Image */
+ typedef morpho::attribute::sharpness<I> accu_t;
+ typedef mln_ch_value_(tree_t::function, mln_result_(accu_t)) A;
+
+ A a = morpho::tree::compute_attribute_image(accu_t (), tree);
+ morpho::tree::propagate_representant(tree, a);
+
+ if (mydebug) {
+ dsp("Image attribute"); display_tree_attributes(tree, a);
+ }
+
+ /* Run max accumulator, looking for 5 objects */
+ accumulator::arg_max<A> argmax(a);
+ p_array< mln_psite_(A) > obj_array; // Array of object components.
+ obj_array = morpho::tree::run_ntimes(tree, a, argmax, 5);
+
+ if (mydebug) {
+ dsp("Run max accumulator, lk 4 5 objs"); display_tree_attributes(tree, a);
+ }
+
+ /* Print them */
+ if (mydebug) {
+ dsp("Image Filtered Components");
+ mln_fwd_piter_(p_array< mln_psite_(I) >) c(obj_array);
+ for_all(c)
+ std::cout << c;
+ }
+
+
+}
Index: trunk/milena/sandbox/edwin/tree/propagate_node.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3551)
+++ trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3552)
@@ -41,41 +41,42 @@
namespace morpho {
namespace tree {
-
/**
- ** Propagate a value to a node and its descendants.
+ ** Propagate a value \v from a node \n to its descendants.
**
- ** @param n The root of subtree which value propagates in.
- ** @param t The reference to components tree.
- ** @param a_ The reference to image.
- ** @param v The value to propagate. Default is a_(n).
+ ** @param n Node to propagate.
+ ** @param t Component tree used for propagation.
+ ** @param a_ Attributed image where values are propagated.
+ ** @param v Value to propagate.
*/
template <typename T, typename A>
void
propagate_node_to_descendants(mln_psite(A) n,
const T& t,
Image<A>& a_,
- mln_value(A) v);
+ const mln_value(A)& v);
/**
** Propagate the node's value to its descendants.
**
- ** @param n The root of subtree which value propagates in.
- ** @param t The reference to components tree.
- ** @param a_ The reference to image.
+ ** @param n Node to propagate.
+ ** @param t Component tree used for propagation.
+ ** @param a_ Attributed image where values are propagated.
*/
template <typename T, typename A>
+ inline
void
propagate_node_to_descendants(mln_psite(A)& n,
const T& t,
Image<A>& a_);
+
/**
- ** Propagate a value from a node to its ancestors.
+ ** Propagate a value \v from a node \n to its ancestors.
**
- ** @param n Forward iterator related to the node.
- ** @param t Reference to components tree.
- ** @param a_ Reference to image.
+ ** @param n Node to propagate.
+ ** @param t Component tree used for propagation.
+ ** @param a_ Attributed image where values are propagated.
** @param v Value to propagate.
*/
template <typename T, typename A>
@@ -83,23 +84,24 @@
propagate_node_to_ancestors(mln_psite(A) n,
const T& t,
Image<A>& a_,
- mln_value(A) v);
+ const mln_value(A)& v);
/**
** Propagate the node's value to its ancestors.
**
- ** @param n Forward iterator related to the node.
- ** @param t Reference to components tree.
- ** @param a_ Reference to image.
+ ** @param n Node to propagate.
+ ** @param t Component tree used for propagation.
+ ** @param a_ Attributed 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
+ //# ifndef MLN_INCLUDE_ONLY
/* Descendants propagation */
@@ -109,7 +111,7 @@
propagate_node_to_descendants(mln_psite(A) n,
const T& t,
Image<A>& a_,
- mln_value(A) v)
+ const mln_value(A)& v)
{
A& a = exact(a_);
mln_precondition(a.is_valid());
@@ -148,7 +150,7 @@
propagate_node_to_ancestors(mln_psite(A) n,
const T& t,
Image<A>& a_,
- mln_value(A) v)
+ const mln_value(A)& v)
{
A& a = exact(a_);
mln_precondition(a.is_valid());
@@ -180,7 +182,7 @@
propagate_node_to_ancestors(n, t, a, a(n));
}
-# endif // ! MLN_INCLUDE_ONLY
+ //# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho::tree
} // end of namespace mln::morpho
Index: trunk/milena/sandbox/edwin/tree/propagation.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3551)
+++ trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3552)
@@ -1,9 +1,15 @@
#include <iostream>
+
+#include <mln/accu/max.hh>
+#include <mln/util/pix.hh>
+
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/core/alias/point2d.hh>
#include <mln/core/routine/duplicate.hh>
+#include <mln/core/concept/function.hh>
+
#include <mln/value/int_u8.hh>
#include <mln/io/pgm/load.hh>
@@ -12,12 +18,14 @@
#include <mln/level/sort_psites.hh>
#include <mln/morpho/tree/data.hh>
-
#include <../../theo/color/change_attributes.hh>
+
+
+
#include "propagate_node.hh"
-#include "propagate_value.hh"
+#include "propagate_if.hh"
+#include "accumulator/arg_max.hh"
#include "run.hh"
-#include "accumulator/max.hh"
void usage(char** argv)
{
@@ -46,6 +54,9 @@
print(img, it);
}
+using namespace mln;
+
+
int main(int argc, char* argv[])
{
using namespace mln;
@@ -90,53 +101,46 @@
dsp("Propagate node to descendants : (point2d(0, 2), tree, dup)");
display_tree_attributes(tree, dup);
- // dup = duplicate(input);
-// morpho::tree::propagate_value_to_ancestors(117, tree, dup, 0);
-// dsp("Propagate value to ancestors : (117, tree, dup, 0)");
-// display_tree_attributes(tree, dup);
-// dup = duplicate(input);
-// morpho::tree::propagate_value_to_ancestors(117, tree, dup);
-// dsp("Propagate value to ancestors : (117, tree, dup)");
-// display_tree_attributes(tree, dup);
-
-// dup = duplicate(input);
-// morpho::tree::propagate_value_to_descendants(117, tree, dup, 0);
-// dsp("Propagate value to descendants : (117, tree, dup, 0)");
-// display_tree_attributes(tree, dup);
-
-// dup = duplicate(input);
-// morpho::tree::propagate_value_to_descendants(117, tree, dup);
-// dsp("Propagate value to descendants : (117, tree, dup)");
-// display_tree_attributes(tree, dup);
+ dup = duplicate(input);
+ morpho::tree::propagate_if_value(tree, dup, morpho::tree::asc_propagation (), 117, 0);
+ dsp("Propagate value to ancestors : (117, tree, dup, 0)");
+ display_tree_attributes(tree, dup);
+ dup = duplicate(input);
+ morpho::tree::propagate_if_value(tree, dup, morpho::tree::asc_propagation (), 117);
+ dsp("Propagate value to ancestors : (117, tree, dup)");
+ display_tree_attributes(tree, dup);
+ dup = duplicate(input);
+ morpho::tree::propagate_if_value(tree, dup, morpho::tree::desc_propagation (), 117,
0);
+ dsp("Propagate value to descendants : (117, tree, dup, 0)");
+ display_tree_attributes(tree, dup);
dup = duplicate(input);
+ morpho::tree::propagate_if_value(tree, dup, morpho::tree::desc_propagation (), 117);
+ dsp("Propagate value to descendants : (117, tree, dup)");
+ display_tree_attributes(tree, dup);
+
- typedef morpho::tree::accumulator::max<tree_t, I> A;
- A accu(dup);
- morpho::tree::run_bkd(tree, accu);
+ accumulator::arg_max<I> mmax;
+ p_array< mln_psite_(I) > tabmax;
+ mln_fwd_piter_(p_array< mln_psite_(I) >) pit(tabmax);
- mln_bkd_piter_(tree_t::nodes_t) it_max = accu.to_result();
- morpho::tree::propagate_node_to_descendants(it_max, tree, dup, 69);
- dsp("Propagate value to descendants : (it_max, tree, dup, 69)");
+ dup = duplicate(input);
+ tabmax = morpho::tree::run_ntimes(tree, dup, mmax, 5);
+ for_all(pit)
+ std::cout << pit << std::endl;
+ dsp("Run ntimes : (tree, dup, max, 5)");
display_tree_attributes(tree, dup);
-// mln_dn_node_piter_(tree_t) n(tree);
-// n.start();
-// print(tree.children_image(), n);
- std::cout << "\n";
- mln_preorder_piter_(tree_t) pit(tree);
- mln_psite_(I) parent;
+ dup = duplicate(input);
+ tabmax = morpho::tree::run_while_treshold(tree, dup, mmax, 20);
for_all(pit)
- {
- if (parent != tree.parent(pit))
- std::cout << std::endl;
- std::cout << pit << " -> ";
- parent = pit;
- }
+ std::cout << pit << std::endl;
+ dsp("Run with treshold : (tree, dup, max, 20)");
+ display_tree_attributes(tree, dup);
}
Index: trunk/milena/sandbox/edwin/tree/Makefile
===================================================================
--- trunk/milena/sandbox/edwin/tree/Makefile (revision 3551)
+++ trunk/milena/sandbox/edwin/tree/Makefile (revision 3552)
@@ -1,11 +1,11 @@
-TARGET=propagation
-SRC=propagation.cc
+TARGET=test
+SRC=test.cc
OBJS=${SRC:.cc=.o}
OLENADIR=$(MLN_DIR)/..
MILENADIR=$(OLENADIR)/milena
-CXXFLAGS=-I$(MILENADIR) -I./
+CXXFLAGS=-I$(MILENADIR) -I./ -W -Wall
CXXFLAGS += -g -ggdb
#CXXFLAGS += -DNDEBUG -O1
Index: trunk/milena/sandbox/edwin/tree/propagate_if.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_if.hh (revision 0)
+++ trunk/milena/sandbox/edwin/tree/propagate_if.hh (revision 3552)
@@ -0,0 +1,320 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_TREE_PROPAGATE_IF_HH_
+# define MLN_MORPHO_TREE_PROPAGATE_IF_HH_
+
+/**
+** @file mln/morpho/tree/propagate_if.hh
+**
+** @brief Methods to handle propagation startegies
+** in component trees.
+**
+*/
+
+# include <mln/morpho/tree/data.hh>
+# include "propagate_node.hh"
+
+namespace mln {
+ namespace morpho {
+ namespace tree {
+
+ template <typename WP>
+ struct way_of_propagation : Object< WP > { protected: way_of_propagation()
{}; };
+ struct desc_propagation : way_of_propagation <desc_propagation> {};
+ struct asc_propagation : way_of_propagation <asc_propagation> {};
+
+ /**
+ ** Propagate nodes checking the predicate \p pred in the way
+ ** defined by \p way_of_propagation.
+ **
+ ** @param tree Component tree used for propagation.
+ ** @param a_ Attributed image where values are propagated.
+ ** @param way_of_propagation Propagate node in acsendant or
+ ** descendant way.
+ ** @param pred Predicate that node must check to be propagated.
+ ** @param v Value to be propagated. (By default \v is the value
+ ** at the node being propagated).
+ */
+ template <typename T, typename A, class P, typename WP>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>&,
+ const P& pred,
+ const mln_value(A)& v);
+
+ template <typename T, typename A, class P, typename WP>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>&,
+ const P& pred);
+
+ /**
+ ** Propagate nodes having the value v in the way
+ ** defined by \p way_of_propagation.
+ **
+ ** @param tree Component tree used for propagation.
+ ** @param a_ Attributed image where values are propagated.
+ ** @param way_of_propagation Propagate node in acsendant or
+ ** descendant way.
+ ** @param v Value that node must have to be propagated.
+ ** @param v_prop Value to propagate (By default it is the value
+ ** at the node being propagated).
+ */
+ template <typename T, typename A, class P, typename WP>
+ inline
+ void
+ propagate_if_value(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>&,
+ const mln_value(A)& v,
+ const mln_value(A)& v_prop);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+ template <typename I>
+ struct pred_value_eq : public mln::Function_p2b< pred_value_eq<I> >
+ {
+ typedef bool result;
+
+ pred_value_eq(const I& a, const mln_value(I)& v)
+ : a_ (a),
+ v_ (v)
+ {
+ mln_invariant(a_.is_valid());
+ }
+
+ bool operator() (const mln_psite(I)& p) const
+ {
+ mln_invariant(a_.domain().has(p));
+ return (v_ == a_(p));
+ }
+
+ private:
+ const I& a_;
+ const mln_value(I) v_;
+ };
+
+
+ template <typename T, typename A>
+ bool check_propagate_value(const T& t,
+ const A& a,
+ const asc_propagation& prop,
+ const mln_value(A)& v)
+ {
+ (void) prop;
+ mln_up_node_piter(T) n(t);
+ for_all(n)
+ if (a(n) == v && a(t.parent(n)) != v)
+ return false;
+ return true;
+ }
+
+ template <typename T, typename A>
+ bool check_propagate_value(const T& t,
+ const A& a,
+ const desc_propagation& prop,
+ const mln_value(A)& v)
+ {
+ (void) prop;
+ mln_up_node_piter(T) n(t);
+ for_all(n)
+ if (a(n) != v && a(t.parent(n)) == v)
+ return false;
+ return true;
+ }
+
+
+ template <typename T, typename A, class P>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const desc_propagation& prop,
+ const P& pred,
+ const mln_value(A)& v)
+ {
+ const A& a = exact(a_);
+ (void) prop;
+
+ mln_precondition(a.is_valid());
+ mln_precondition(tree.f().domain() == a.domain());
+
+ mln_preorder_piter(T) n(tree);
+ for_all(n)
+ if (pred(n))
+ {
+ propagate_node_to_descendants(n, tree, a_, v);
+ n.skip_children();
+ }
+ }
+
+ template <typename T, typename A, class P>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const desc_propagation& prop,
+ const P& pred)
+ {
+ const A& a = exact(a_);
+ (void) prop;
+
+ mln_precondition(a.is_valid());
+ mln_precondition(tree.f().domain() == a.domain());
+
+ mln_preorder_piter(T) n(tree);
+ for_all(n)
+ if (pred(n))
+ {
+ propagate_node_to_descendants(n, tree, a_);
+ n.skip_children();
+ }
+ }
+
+ template <typename T, typename A, class P>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const asc_propagation& prop,
+ const P& pred,
+ const mln_value(A)& v)
+ {
+ const A& a = exact(a_);
+ (void) prop;
+
+ mln_precondition(a.is_valid());
+ mln_precondition(tree.f().domain() == a.domain());
+
+ mln_up_node_piter(T) n(tree);
+ for_all(n)
+ if (pred(n))
+ propagate_node_to_ancestors(n, tree, a_, v);
+ }
+
+ template <typename T, typename A, class P>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const asc_propagation& prop,
+ const P& pred)
+ {
+ const A& a = exact(a_);
+ (void) prop;
+
+ mln_precondition(a.is_valid());
+ mln_precondition(tree.f().domain() == a.domain());
+
+ mln_up_node_piter(T) n(tree);
+ for_all(n)
+ if (pred(n))
+ propagate_node_to_ancestors(n, tree, a_, a(n));
+ }
+
+ } // end of namespace mln::morpho::tree::internal
+
+
+ /* Facades */
+
+ template <typename T, typename A, typename WP>
+ inline
+ void
+ propagate_if_value(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>& prop_,
+ const mln_value(A)& v,
+ const mln_value(A)& v_prop)
+ {
+ A& a = exact(a_);
+ const WP& prop = exact(prop_);
+ internal::pred_value_eq<A> pred(a, v);
+
+ internal::propagate_if(tree, a_, prop, pred, v_prop);
+ }
+
+
+ template <typename T, typename A, typename WP>
+ inline
+ void
+ propagate_if_value(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>& prop_,
+ const mln_value(A)& v)
+ {
+ const A& a = exact(a_);
+ const WP& prop = exact(prop_);
+ internal::pred_value_eq<A> pred(a, v);
+
+ internal::propagate_if(tree, a_, prop, pred);
+ mln_postcondition(internal::check_propagate_value(tree, a, prop, v));
+ }
+
+ template <typename T, typename A, class P, typename WP>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>& prop_,
+ const P& pred,
+ const mln_value(A)& v)
+ {
+ const WP& prop = exact(prop_);
+ internal::propagate_if(tree, a_, prop, pred, v);
+ }
+
+ template <typename T, typename A, class P, typename WP>
+ inline
+ void
+ propagate_if(const T& tree,
+ Image<A>& a_,
+ const way_of_propagation<WP>& prop_,
+ const P& pred)
+ {
+ const WP& prop = exact(prop_);
+ internal::propagate_if(tree, a_, prop, pred);
+ }
+
+#endif /* !MLN_INCLUDE_ONLY */
+
+
+ } // end of namespace mln::morpho::tree
+ } // end of namespace mln::morpho
+} // end of namespace mln
+
+#endif /* !MLN_MORPHO_TREE_PROPAGATE_IF_HH_ */