r3679: Clean dead code, and optimize components retrieving

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-04-16 Edwin Carlinet <carlinet@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); }
participants (1)
-
Edwin Carlinet