URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-04-16 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Clean dead code, and optimize components retrieving.
* edwin/tree/propagate_value.hh: Remove.
* edwin/tree/propagate_leaf.hh: Remove.
* edwin/tree/propagate_node.hh,
* edwin/tree/propagation.cc,
* edwin/tree/run.hh,
* edwin/tree/sharp.cc,
* edwin/tree/components.hh: Some minor fixes + component retrieving
optimisation.
---
components.hh | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
propagate_node.hh | 2
propagation.cc | 38 -------
run.hh | 1
sharp.cc | 155 ++++++++++++++++++++++--------
5 files changed, 396 insertions(+), 78 deletions(-)
Index: trunk/milena/sandbox/edwin/tree/propagate_leaf.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/propagate_value.hh (deleted)
===================================================================
Index: trunk/milena/sandbox/edwin/tree/sharp.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3679)
@@ -12,20 +12,15 @@
/* Component trees */
#include <mln/morpho/tree/data.hh>
#include <mln/morpho/tree/compute_attribute_image.hh>
-#include "run.hh"
+#include "components.hh"
#include "propagate.hh"
-#include "accumulator/arg_max.hh"
/* Attributes */
#include <mln/morpho/attribute/sharpness.hh>
-#include <mln/morpho/attribute/card.hh>
-
/* io */
-#include <mln/io/ppm/load.hh>
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
-#include <mln/io/pbm/save.hh>
/* data & pw */
#include <mln/core/concept/function.hh>
@@ -99,8 +94,69 @@
}
return output;
}
+
+ template <typename P2V>
+ struct height_wrapper_ : Function_p2v< height_wrapper_<P2V> >
+ {
+ typedef unsigned result;
+
+ height_wrapper_(const Function_p2v<P2V>& f) :
+ f_ (exact(f))
+ {
+ mlc_is_a(mln_result(P2V), Accumulator)::check();
}
+ template <typename P>
+ unsigned operator() (const P& p) const
+ {
+ return f_(p).height();
+ }
+
+ private:
+ const P2V& f_;
+ };
+
+ template <typename P2V>
+ inline
+ height_wrapper_<P2V>
+ height_wrapper(const Function_p2v<P2V>& f)
+ {
+ return height_wrapper_<P2V>(f);
+ }
+
+ template <typename P2V>
+ struct card_wrapper_ : Function_p2v< card_wrapper_<P2V> >
+ {
+ typedef unsigned result;
+
+ card_wrapper_(const Function_p2v<P2V>& f) :
+ f_ (exact(f))
+ {
+ mlc_is_a(mln_result(P2V), Accumulator)::check();
+ }
+
+ template <typename P>
+ unsigned operator() (const P& p) const
+ {
+ return f_(p).area();
+ }
+
+ private:
+ const P2V& f_;
+ };
+
+ template <typename P2V>
+ inline
+ card_wrapper_<P2V>
+ card_wrapper(const Function_p2v<P2V>& f)
+ {
+ return card_wrapper_<P2V>(f);
+ }
+
+}
+
+
+
@@ -112,6 +168,7 @@
std::string arg;
unsigned nb_components = 0;
unsigned card = 0;
+ unsigned height = 0;
double sharpness = 0;
if (argc < 2)
@@ -130,46 +187,60 @@
card = atoi(argv[++i]);
else if (arg == "--trace")
trace::quiet = false;
+ else if (arg == "-h")
+ height = atoi(argv[++i]);
else
usage (argv);
}
+ /********************/
+ /* Load & Pre-treat */
+ /********************/
-
- /* Image loadin' */
- image2d<rgb8> input_;
- io::ppm::load(input_, argv[1]);
+ if (mydebug)
+ dsp("Load & Pre-treat");
typedef image2d<int_u8> I;
- I input = dist_on_pixels(input_, c4());
+ I input;
+ io::pgm::load(input, argv[1]);
- if (mydebug)
- io::pgm::save(input, "input.pgm");
+ /***************************/
+ /* Component tree creation */
+ /***************************/
+ if (mydebug)
+ dsp("Component tree creation");
- /* 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 */
+ /******************************/
+ if (mydebug)
+ dsp("Image sharp attribute");
// TODO: l'attribut devrait favoriser les composantes plus larges
// dans son calcul. Ainsi au lieu de faire un sharpness, on aurait
- // un ratio sharpness / largeur de composante (reprendre l'idee du
+ // un ratio sharpness / hauteur de composante (reprendre l'idee du
// log utilise pour INIM).
typedef morpho::attribute::sharpness<I> sharp_t;
typedef mln_ch_value_(I, double) A;
+ typedef mln_ch_value_(I, sharp_t) B;
- if (mydebug)
- dsp("Image sharp attribute");
+ B a_img;
+ A a = morpho::tree::compute_attribute_image(sharp_t (), tree, &a_img);
+ // Note: then we work on nodes (component representant so we don't
+ // need to propagate the representant value to the component sites.
- A a = morpho::tree::compute_attribute_image(sharp_t (), tree);
- morpho::tree::propagate_representant(tree, a);
- /* We don't want little components */
+ /***********************************/
+ /* Components Filtering */
+ /***********************************/
// So we compute card attribute and we filter big components
// FIXME: some attributes are compositions of attributes, here
@@ -179,27 +250,33 @@
if (card)
{
- typedef morpho::attribute::card<I> card_t;
- typedef mln_ch_value_(tree_t::function, mln_result_(card_t)) B;
-
if (mydebug)
dsp("Image card attribute");
- B b = morpho::tree::compute_attribute_image(card_t (), tree);
- morpho::tree::propagate_representant(tree, b);
-
- a = duplicate((fun::p2v::ternary(pw::value(b) > pw::cst(card), pw::value(a),
pw::cst(0.0))) | a.domain());
+ a = duplicate((fun::p2v::ternary(card_wrapper(pw::value(a_img)) >
pw::cst(card),
+ pw::value(a),
+ pw::cst(0.0))) | a.domain());
}
+ if (height)
+ {
if (mydebug)
- io::pgm::save(level::stretch(int_u8(), a), "attr_image.pgm");
+ dsp("Image height attribute");
+ a = duplicate((fun::p2v::ternary(height_wrapper(pw::value(a_img)) >
pw::cst(height),
+ pw::value(a),
+ pw::cst(0.0))) | a.domain());
+ }
+
+ /************************************************/
+ /* Retrieve Components (Maximising the criteria) */
+ /************************************************/
- /* Run max accumulator */
accumulator::arg_max<A> argmax(a);
p_array< mln_psite_(A) > obj_array; // Array of object components.
if (mydebug) {
- std::stringstream s("Run max accumulator, look for ",
std::stringstream::out|std::stringstream::in|std::stringstream::ate);
+ std::stringstream s("Run max accumulator, look for ",
std::stringstream::out|std::stringstream::in|
+ std::stringstream::ate);
if (nb_components)
s << nb_components << " components.";
else if (sharpness)
@@ -210,12 +287,12 @@
}
if (nb_components) {
- obj_array = morpho::tree::run_ntimes(tree, a, argmax, nb_components);
+ obj_array = morpho::tree::get_components(tree, a, nb_components);
} else if (sharpness > 0) {
mln_VAR(predicate, pw::value(a) > pw::cst(sharpness));
- obj_array = morpho::tree::run_while(tree, a, argmax, predicate);
+ obj_array = morpho::tree::get_components(tree, a, predicate);
} else {
- obj_array = morpho::tree::run_until_glutted_leaves(tree, a, argmax);
+ obj_array = morpho::tree::get_components(tree, a);
}
@@ -227,16 +304,21 @@
std::cout << c;
}
- /* Now Back Propagate to component */
+ /***********************************/
+ /* Use components in output image */
+ /***********************************/
if (mydebug) {
dsp("Create mask and propagate");
}
+ // Note: now we must propagate the representant value to the other components sites.
A pre_output = morpho::tree::set_value_to_components(a, tree, obj_array, 0);
- I output = level::stretch(int_u8(), pre_output);
+ I output = level::stretch(int_u8(), pre_output); //adapt to 0-255
io::pgm::save(output, "components.pgm");
+ /* EXTRA */
+
// typedef mln_ch_value_(I, bool) M;
// M mask;
// initialize(mask, a);
@@ -252,9 +334,6 @@
// mask now contains all nodes related to objects
-
- /* EXTRA */
-
// /* Labeling */
// typedef mln_ch_value_(I, value::label<8>) L;
// value::label<8> nlabel;
Index: trunk/milena/sandbox/edwin/tree/run.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/run.hh (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/run.hh (revision 3679)
@@ -120,7 +120,6 @@
namespace internal
{
-
template <typename T, typename A, typename ACC, typename P2B>
p_array< mln_psite(A) >
run_while(const T& tree,
Index: trunk/milena/sandbox/edwin/tree/components.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/components.hh (revision 0)
+++ trunk/milena/sandbox/edwin/tree/components.hh (revision 3679)
@@ -0,0 +1,278 @@
+// 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 COMPONENTS_HH_
+# define COMPONENTS_HH_
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/data/fill.hh>
+
+# include <mln/morpho/tree/data.hh>
+# include "propagate_node.hh"
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+
+
+namespace mln {
+ namespace morpho {
+ namespace tree {
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image);
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, unsigned
n);
+
+ template <typename T, typename A, typename P2B>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, const
Function_p2b<P2B>& pred);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+ template <typename P, typename I>
+ struct desc_sort
+ {
+ bool operator()(const P& p1, const P& p2) const
+ {
+ return ima(p1) > ima(p2);
+ }
+ const I& ima;
+
+ desc_sort(const I& ima) : ima(ima) {}
+ };
+
+ template <typename P, typename I>
+ inline
+ void
+ sort(p_array<P>& arr, const I& ima_)
+ {
+ mlc_converts_to(P, mln_psite(I))::check();
+
+ const I& ima = exact(ima_);
+ std::vector<P>& v = arr.hook_std_vector_();
+ std::sort(v.begin(), v.end(), desc_sort<P,I>(ima));
+ }
+
+ template <typename A>
+ inline
+ bool
+ get_max(const p_array< mln_psite(A) >& arr, const A& activity,
unsigned& pos)
+ {
+ while (pos < arr.nsites() && !activity(arr[pos]))
+ ++pos;
+ return (pos < arr.nsites());
+ }
+
+
+ //////////////////////////
+ // Predifined predicate //
+ //////////////////////////
+
+ /// Predicate used to gets components until tree leaves last.
+ template <typename T>
+ class pred_tree_leaves_last
+ {
+ public:
+ pred_tree_leaves_last(const T& tree) :
+ n_ (tree.leaves().nsites())
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)p;
+ (void)n;
+ mln_assertion(nb_leaves != 0);
+
+ return (*nb_leaves < n_);
+ }
+
+
+ private:
+ unsigned n_;
+ };
+
+ /// Predicate used to get n components.
+ class pred_n_components
+ {
+ public:
+ pred_n_components(unsigned n) :
+ n_(n)
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)p;
+ (void)nb_leaves;
+
+ return (n < n_);
+ }
+
+
+ private:
+ unsigned n_;
+ };
+
+ /// Predicate used to get components that check a p2b function predicate.
+ template <typename P2B>
+ class pred_p2b
+ {
+ public:
+ pred_p2b(const P2B& f) :
+ f_ (f)
+ {
+ }
+
+ template <typename P>
+ bool operator() (const P& p, unsigned n, unsigned* nb_leaves) const
+ {
+ (void)n;
+ (void)nb_leaves;
+
+ return (f_(p));
+ }
+
+
+ private:
+ const P2B& f_;
+ };
+
+
+
+
+ template <typename T, typename A, class P>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const A& a, const P& pred, bool uses_leaves =
0)
+ {
+
+ mln_psite(A) p;
+ p_array< mln_psite(A) > components;
+ mln_ch_value(A, bool) activity;
+ p_array< mln_psite(A) > max_arr = tree.nodes();
+ unsigned arr_pos = 0; //position in max_array
+ unsigned n = 0;
+ unsigned* nb_leaves = uses_leaves ? new unsigned(0) : 0;
+
+ initialize(activity, a);
+ data::fill(activity, true);
+ internal::sort(max_arr, a);
+
+ do
+ {
+ if (!internal::get_max(max_arr, activity, arr_pos))
+ break;
+ p = max_arr[arr_pos];
+ if (a(p) == 0)
+ break;
+ components.insert(p);
+ morpho::tree::propagate_node_to_descendants(p, tree, activity, false, nb_leaves);
+ morpho::tree::propagate_node_to_ancestors(p, tree, activity, false);
+ activity(p) = false;
+ mln_assertion(nb_leaves == 0 || *nb_leaves <= n);
+ }
+ while (pred(p, n, nb_leaves));
+
+ if (uses_leaves)
+ delete nb_leaves;
+ return components;
+ }
+
+ } // end of namespace mln::morpho::tree::internal
+
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components<T, A>(tree, a,
internal::pred_tree_leaves_last<T>(tree), true);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+
+ template <typename T, typename A>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, unsigned
n)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components(tree, a, internal::pred_n_components(n), false);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+ template <typename T, typename A, typename P2B>
+ p_array< mln_psite(A) >
+ get_components(const T& tree, const Image<A>& attr_image, const
Function_p2b<P2B>& pred)
+ {
+ trace::entering("mln::morpho::tree::get_components");
+
+ const A& a = exact(attr_image);
+ const P2B& predicate = exact(pred);
+ mln_precondition(tree.f().domain() == a.domain());
+ mln_precondition(a.is_valid());
+
+ p_array< mln_psite(A) > components =
+ internal::get_components(tree, a, internal::pred_p2b<P2B>(predicate), false);
+
+ trace::exiting("mln::morpho::tree::get_components");
+ return components;
+ }
+
+ } // end of namespace mln::morpho::tree
+ } // end of namespace mln::morpho
+} // end of namespace mln
+
+# endif /* !MLN_INCLUDE_ONLY */
+
+#endif /* !COMPONENTS_HH_ */
Index: trunk/milena/sandbox/edwin/tree/propagate_node.hh
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/propagate_node.hh (revision 3679)
@@ -136,7 +136,7 @@
pp.start(); // We don't set n to v.
if (nb_leaves)
- *nb_leaves = t.is_a_leaf(pp);
+ *nb_leaves += t.is_a_leaf(pp);
for (pp.next(); pp.is_valid(); pp.next())
{
Index: trunk/milena/sandbox/edwin/tree/propagation.cc
===================================================================
--- trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3678)
+++ trunk/milena/sandbox/edwin/tree/propagation.cc (revision 3679)
@@ -40,23 +40,6 @@
<< "*********************" << std::endl;
}
-template <typename I>
-void print(I& img, mln_psite(I) p)
-{
- using namespace mln;
-
- std::cout << p << " -> ";
- mln_fwd_piter(p_array<mln_psite(I)>) it(img(p));
-// for_all(it)
-// std::cout << it << " ";
-// std::cout << std::endl;
- for_all(it)
- print(img, it);
-}
-
-using namespace mln;
-
-
int main(int argc, char* argv[])
{
using namespace mln;
@@ -101,7 +84,6 @@
dsp("Propagate node to descendants : (point2d(0, 2), 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)");
@@ -121,26 +103,6 @@
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);
-
-
- accumulator::arg_max<I> mmax;
- p_array< mln_psite_(I) > tabmax;
- mln_fwd_piter_(p_array< mln_psite_(I) >) pit(tabmax);
-
- 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);
-
-
- dup = duplicate(input);
- tabmax = morpho::tree::run_while_treshold(tree, dup, mmax, 20);
- for_all(pit)
- std::cout << pit << std::endl;
- dsp("Run with treshold : (tree, dup, max, 20)");
- display_tree_attributes(tree, dup);
}