milena r1753: Split fllt.hh in my sanbox

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2008-02-26 Matthieu Garrigues <garrigues@lrde.epita.fr> Split fllt.hh in my sanbox. * sandbox/garrigues/fllt/compute_level_set.hh: New, compute the level sets. * sandbox/garrigues/fllt/debug.hh: New, debug routines for FLLT. * sandbox/garrigues/fllt/doc.hh: New, some comments from the monasse's paper. * sandbox/garrigues/fllt/lower.hh: New, the struct used to compute the lower level set. * sandbox/garrigues/fllt/upper.hh: New, the struct used to compute the upper level set. * sandbox/garrigues/fllt/types.hh: New, type defined for FLLT. * sandbox/garrigues/fllt/merge.hh: New, routines to merge the lower level set and the upper level set. * sandbox/garrigues/fllt/fllt.hh: Split this file. * sandbox/garrigues/fllt/test_fllt10.cc: Update includes. --- compute_level_set.hh | 410 ++++++++++++++++++++++++++++ debug.hh | 122 ++++++++ doc.hh | 90 ++++++ fllt.hh | 724 --------------------------------------------------- lower.hh | 86 ++++++ merge.hh | 216 +++++++++++++++ test_fllt10.cc | 2 types.hh | 71 +++++ upper.hh | 85 +++++ 9 files changed, 1090 insertions(+), 716 deletions(-) Index: trunk/milena/sandbox/garrigues/fllt/test_fllt10.cc =================================================================== --- trunk/milena/sandbox/garrigues/fllt/test_fllt10.cc (revision 1752) +++ trunk/milena/sandbox/garrigues/fllt/test_fllt10.cc (revision 1753) @@ -1,4 +1,4 @@ -# include "fllt2.hh" +# include "fllt.hh" # include <mln/core/image2d.hh> # include <mln/core/clone.hh> # include <mln/value/int_u8.hh> Index: trunk/milena/sandbox/garrigues/fllt/lower.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/lower.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/lower.hh (revision 1753) @@ -0,0 +1,86 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_LOWER_HH +# define MLN_FIXME_FLLT_LOWER_HH + +/*! \file lower.hh + * + * \brief Lower level set for Fast level line transform. + * + */ + +# include <mln/core/neighb2d.hh> +# include <mln/labeling/regional_minima.hh> +# include <mln/accu/min.hh> + +# include "upper.hh" + +namespace mln +{ + namespace fllt + { + + //Fwd declarations. + template <typename V> struct lower; + template <typename V> struct upper; + + // LOWER LEVEL SET : region = c4, border = c8 + template <typename V> + struct lower + { + typedef upper<V> opposite; + static bool + compare(const V& u, const V& v) + { + return u < v; + } + + template <typename I, typename N, typename L> + static mln_ch_value(I, L) + regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels) + { + return labeling::regional_minima(input, nbh, nlabels); + } + + static const int inc = 1; + static const bool parent_is_brighter = true; + typedef accu::min accu_for_gn; + + static const neighb2d& bdr_nbh() { return c8(); } + static const neighb2d& reg_nbh() { return c4(); } + + }; + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_LOWER_HH Index: trunk/milena/sandbox/garrigues/fllt/upper.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/upper.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/upper.hh (revision 1753) @@ -0,0 +1,85 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_UPPER_HH +# define MLN_FIXME_FLLT_UPPER_HH + +/*! \file upper.hh + * + * \brief Upper level set for Fast level line transform. + * + */ + +# include <mln/core/neighb2d.hh> +# include <mln/labeling/regional_maxima.hh> +# include <mln/accu/max.hh> + +# include "lower.hh" + +namespace mln +{ + namespace fllt + { + + //Fwd declarations. + template <typename V> struct lower; + + // UPPER LEVEL SET : region = c8, border = c4 + template <typename V> + struct upper + { + typedef lower<V> opposite; + + static bool + compare(const V& u, const V& v) + { + return u > v; + } + + template <typename I, typename N, typename L> + static mln_ch_value(I, L) + regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels) + { + return labeling::regional_maxima(input, nbh, nlabels); + } + + static const int inc = -1; + static const bool parent_is_brighter = false; + typedef accu::max accu_for_gn; + + static const neighb2d& bdr_nbh() { return c4(); } + static const neighb2d& reg_nbh() { return c8(); } + }; + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_UPPER_HH Index: trunk/milena/sandbox/garrigues/fllt/merge.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/merge.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/merge.hh (revision 1753) @@ -0,0 +1,216 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_MERGE_HH +# define MLN_FIXME_FLLT_MERGE_HH + +/*! \file merge.hh + * + * \brief Merge for Fast level line transform. + * + */ + +namespace mln +{ + namespace fllt + { + + + // Fwd declarations. + template <typename P, typename V, typename F> + void + fill_a_shape(fllt_node(P, V)& node, + fllt_tree(P, V)& tree, + const image2d<fllt_node(P, V)*>& node_reg, + const image2d<fllt_node(P, V)*>& hole_reg); + + template <typename P, typename V, typename F> + void + move_shape(fllt_node(P, V)& node, + fllt_node(P, V)& hole, + fllt_tree(P, V)& tree, + const image2d<fllt_node(P, V)*>& hole_reg, + const image2d<fllt_node(P, V)*>& other_reg) + { + // FIXME : debug to remove. + // std::cout << " [move_shape] "<< &hole << " as son of "<< &node << std::endl; + //node.elt().points = set::uni(hole.elt().points, node.elt().points); + node.add_child(&hole); + fill_a_shape<P,V,typename F::opposite>(hole, tree, hole_reg, other_reg); + } + + template <typename P, typename V, typename F> + fllt_node(P, V)* + find_the_hole(fllt_node(P, V)& node, + const P p, + const image2d<fllt_node(P, V)*>& other_reg) + { + fllt_node(P, V)* s = other_reg(p); + mln_assertion(s); + while (s->parent() && F::opposite::compare(s->parent()->elt().value, node.elt().value)) + //FIXME : Was while (s->parent() && (s->parent()->elt().value < node.elt().value)) + { + mln_assertion(s); + s = s->parent(); + mln_assertion(s); + } +// std::cout << " [Find the hole] of " << p +// << " from " << &node +// << " return " << s +// << std::endl; + return s; + } + + template <typename P, typename V, typename F> + void + fill_a_shape(fllt_node(P, V)& node, + fllt_tree(P, V)& tree, + const image2d<fllt_node(P, V)*>& node_reg, + const image2d<fllt_node(P, V)*>& hole_reg) + { +// std::cout << "[Start fill_a_shape] " << &node << " " +// << node.elt().holes.npoints() +// << " holes." << std::endl; + + if (node.elt().holes.npoints() == 0) + { + // std::cout << "[End fill_a_shape]" << std::endl; + return; + } + mln_piter(p_set<P>) p(node.elt().holes); + for_all(p) + { + bool h = true; + + fllt_node(P, V)* hole; + if (node.elt().brighter == F::parent_is_brighter) + hole = find_the_hole<P,V,F>(node, point2d(p), hole_reg); + else + hole = find_the_hole<P,V,typename F::opposite>(node, point2d(p), node_reg); + + mln_assertion(hole); + + typename fllt_node(P, V)::children_t::iterator it; + for (it = node.children().begin(); + it != node.children().end(); + it++) + { + // Browse the hole of each child. + mln_piter(p_set<P>) q((*it)->elt().holes); + for_all(q) + { + fllt_node(P, V)* child_hole = find_the_hole<P,V,F>((**it), point2d(q), hole_reg); + if (set::is_subset_of(hole->elt().points, + child_hole->elt().points)) + +// if (hole->elt().points < child_hole->elt().points) + { + h = false; + break; + } + + } + if (!h) + break; + } + if (h) + move_shape<P,V,F>(node, *hole, tree, hole_reg, node_reg); + } + + node.elt().holes.clear(); + // std::cout << "[end fill_a_shape]" << std::endl; + } + + template <typename P, typename V> + fllt_tree(P, V) + merge_trees(fllt_tree(P, V)& lower_tree, + fllt_tree(P, V)& upper_tree, + const image2d<fllt_node(P, V)*>& low_reg, + const image2d<fllt_node(P, V)*>& upp_reg, + const image2d<V>& ima) + { + + // In order to merge the trees, we only have to find for each shape S + // with a hole H in it whether one of its children has a hole HŽ + // containing H. If it is the case, we do nothing. Otherwise, we + // put the shape of the hole H (and all its descendants) as child of + // the shape . + { + std::cout << "[Merge first tree]------------" << std::endl; + + fllt_branch_iter_ind(P, V) p(lower_tree.main_branch()); + for_all(p) + { + fllt_node(P, V)& n(p); + fill_a_shape< P, V, lower<V> >(n, lower_tree, low_reg, upp_reg); + mln_assertion(lower_tree.check_consistency()); + mln_assertion(upper_tree.check_consistency()); + } + + } + + { + std::cout << "[Merge second tree]------------" << std::endl; + + fllt_branch_iter_ind(P, V) p(upper_tree.main_branch()); + for_all(p) + { + fllt_node(P, V)& n(p); + fill_a_shape< P, V, upper<V> >(n, upper_tree, upp_reg, low_reg); + mln_assertion(lower_tree.check_consistency()); + mln_assertion(upper_tree.check_consistency()); + } + } + + fllt_tree(P, V)* main_tree = &lower_tree; + fllt_tree(P, V)* other_tree = &upper_tree; + + if (lower_tree.root()->elt().points.npoints() >= ima.domain().npoints()) + { + main_tree = &upper_tree; + other_tree = &lower_tree; + } + + typename fllt_node(P, V)::children_t::iterator it; + for (it = other_tree->root()->children().begin(); + it != other_tree->root()->children().end(); ) + { + main_tree->root()->add_child(*it); + } + mln_assertion(main_tree->check_consistency()); + return *main_tree; + } + + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_MERGE_HH Index: trunk/milena/sandbox/garrigues/fllt/types.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/types.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/types.hh (revision 1753) @@ -0,0 +1,71 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_TYPES_HH +# define MLN_FIXME_FLLT_TYPES_HH + +/*! \file types.hh + * + * \brief Types for Fast level line transform. + * + */ + +# include <mln/core/p_set.hh> +# include <mln/util/tree.hh> +# include <mln/util/branch_iter_ind.hh> + +namespace mln +{ + namespace fllt + { + + template <typename P, typename V> + struct fllt_node_elt + { + V value; + p_set<P> points; + p_set<P> holes; + /// Tell if his parent if brighter or not. Nb : if the parent + /// if brighter, the node come from the lower level set + bool brighter; + }; + +# define fllt_tree(P, V) util::tree< fllt_node_elt<P, V> > +# define fllt_node(P, V) util::tree_node< fllt_node_elt<P, V> > +# define fllt_branch(P, V) util::branch< fllt_node_elt<P, V> > +# define fllt_branch_iter_ind(P, V) util::branch_iter_ind< fllt_node_elt<P, V> > + + // # define fllt_node(P, V) typename fllt_tree(P, V)::node_t + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_TYPES_HH Index: trunk/milena/sandbox/garrigues/fllt/doc.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/doc.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/doc.hh (revision 1753) @@ -0,0 +1,90 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_DOC_HH +# define MLN_FIXME_FLLT_DOC_HH + +/*! \file doc.hh + * + * \brief Compute Level Set for Fast level line transform. + * + */ + +namespace mln +{ + namespace fllt + { + + + // LOWER LEVEL SET : region = c4, border = c8 + // UPPER LEVEL SET : region = c8, border = c4 + + // 1) + // x0 <- a not tagged local mininum of ima. + // g <- u(x0) + + // 2) + // A <- {x0} + // R <- {} + // N <- {} + + // 3) + // N <- N union {x neighbor of a pixel in a} + // gn <- min u(x) x belongs to N. + // R <- R union A + // tag the pixels of A. + + // 4) + // IF g < gn + // IF number of conected components of the border > 1 + // follow each border to find which is the exterior border + // and which are the holes. Keep one pixel of each holes. + // + // Remove from N border of holes. + // Recompute gn <- min u(x) x belongs to A + // + // g <- gn + // A <- {x belongs to N / u(x) == g} + // N <- N\{x belongs to N / u(x) == g} + // GO TO 3) + // IF g == gn + // A <- {x belongs to N / u(x) == g} + // N <- N\{x belongs to N / u(x) == g} + // GO TO 3) + // IF g > gn + // set the gray-level of the pixels of R to g. + // GO TO 1) + + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_DOC_HH Index: trunk/milena/sandbox/garrigues/fllt/debug.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/debug.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/debug.hh (revision 1753) @@ -0,0 +1,122 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_DEBUG_HH +# define MLN_FIXME_FLLT_DEBUG_HH + +/*! \file debug.hh + * + * \brief Debug for Fast level line transform. + * + */ + +# include "types.hh" + +namespace mln +{ + namespace fllt + { + + + template <typename P, typename V> + void + visualize_deepness(image2d<value::int_u8>& output, + fllt_tree(P, V)& tree) + { + fllt_branch_iter_ind(P, V) p(tree.main_branch()); + level::fill(output, 0); + for_all(p) + { + //std::cout << (&*p) << ":" << p.deepness() << std::endl; + mln_piter(p_set<point2d>) q((*p).elt().points); + for_all(q) + { + if (output(q) < p.deepness()) + output(q) = p.deepness(); + } + } + } + + + template <typename P, typename V> + void + visualize_bounds(image2d<value::int_u8>& output, + fllt_tree(P, V)& tree, + unsigned limit) + { + fllt_branch_iter_ind(P, V) p(tree.main_branch()); + level::fill(output, 255); + for_all(p) + { + if ((*p).elt().points.npoints() > limit) + { + mln_piter(p_set<point2d>) q((*p).elt().points); + for_all(q) + { + mln_niter(neighb2d) n(c4(), q); + bool is_border = false; + for_all (n) + if (!((*p).elt().points).has (n)) + is_border = true; + if (is_border) + output(q) = 0; + } + } + } + } + + template <typename P, typename V> + void + draw_tree(const image2d<V>& ima, + fllt_tree(P, V)& tree) + { + fllt_branch_iter_ind(P, V) p(tree.main_branch()); + for_all(p) + { + std::cout << "region mere : " << (*p).parent() << std::endl; + std::cout << " ^" << std::endl; + std::cout << " |" << std::endl; + std::cout << "region : " << &*p + << " value = " << (*p).elt().value << std::endl + << " holes : " + << (*p).elt().holes.npoints() + << (*p).elt().holes + << std::endl; + + debug::println(ima | (*p).elt().points); + std::cout << std::endl; + } + } + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_DEBUG_HH Index: trunk/milena/sandbox/garrigues/fllt/fllt.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/fllt.hh (revision 1752) +++ trunk/milena/sandbox/garrigues/fllt/fllt.hh (revision 1753) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -78,725 +78,19 @@ # include <mln/level/compare.hh> # include <mln/io/pgm/save.hh> -namespace mln -{ - namespace fllt - { - - template <typename P, typename V> - struct fllt_node_elt - { - V value; - p_set<P> points; - p_set<P> holes; - /// Tell if his parent if brighter or not. Nb : if the parent - /// if brighter, the node come from the lower level set - bool brighter; - }; - -# define fllt_tree(P, V) util::tree< fllt_node_elt<P, V> > -# define fllt_node(P, V) util::tree_node< fllt_node_elt<P, V> > -# define fllt_branch(P, V) util::branch< fllt_node_elt<P, V> > -# define fllt_branch_iter_ind(P, V) util::branch_iter_ind< fllt_node_elt<P, V> > - - // # define fllt_node(P, V) typename fllt_tree(P, V)::node_t - - - - // LOWER LEVEL SET : region = c4, border = c8 - // UPPER LEVEL SET : region = c8, border = c4 - - // 1) - // x0 <- a not tagged local mininum of ima. - // g <- u(x0) - - // 2) - // A <- {x0} - // R <- {} - // N <- {} - - // 3) - // N <- N union {x neighbor of a pixel in a} - // gn <- min u(x) x belongs to N. - // R <- R union A - // tag the pixels of A. - - // 4) - // IF g < gn - // IF number of conected components of the border > 1 - // follow each border to find which is the exterior border - // and which are the holes. Keep one pixel of each holes. - // - // Remove from N border of holes. - // Recompute gn <- min u(x) x belongs to A - // - // g <- gn - // A <- {x belongs to N / u(x) == g} - // N <- N\{x belongs to N / u(x) == g} - // GO TO 3) - // IF g == gn - // A <- {x belongs to N / u(x) == g} - // N <- N\{x belongs to N / u(x) == g} - // GO TO 3) - // IF g > gn - // set the gray-level of the pixels of R to g. - // GO TO 1) - - template <typename V> - void step1 (const image2d<V>& ima, - point2d p, - V& g, - point2d& x0) - { - //std::cout << "entering step 1" << std::endl; - // x0 <- a not tagged local mininum of ima. - //std::cout << std::endl << "x0 = " << p << std::endl; - x0 = p; - // g <- u(x0) - g = ima(x0); - //std::cout << "g = " << g << std::endl; - //std::cout << "exiting step 1" << std::endl; - } - - template <typename P> - void step2 (p_set<P>& A, - p_set<P>& R, - p_set<P>& N, - point2d& x0) - { - //std::cout << "entering step 2" << std::endl; - // A <- {x0} - A.clear(); - A.insert(x0); - // R <- {} - R.clear(); - // N <- {} - N.clear(); - //std::cout << "exiting step 2" << std::endl; - } - - - template <typename V, typename P, typename F> - void step3 (const image2d<V>& u, - image2d<bool>& tagged, - p_set<P>& A, - p_set<P>& R, - p_set<P>& N, - V& gn) - { - static bool finished = false; - //std::cout << "entering step 3" << std::endl; - - // Stop the algorithm. - if (finished) - { finished = false; gn -= 2 * F::inc; return; } - - // N <- N union {x neighbor of a pixel in a\R} - mln_piter(p_set<P>) qa(A); - for_all(qa) - { - mln_niter(neighb2d) n(F::reg_nbh(), qa); - for_all (n) - if (!R.has (n)) - N.insert (n); - } - - // debug::println(u); - - // //std::cout << "A :" << std::endl; - // if (A.npoints()) - // //debug::println(u | A); - // //std::cout << "N :" << std::endl; - // if (N.npoints()) - // //debug::println(u | N); - // //std::cout << "R :" << std::endl; - // if (R.npoints()) - // //debug::println(u | R); - - // gn <- min u(x) x belongs to N. - if ((u | set::inter(N, u.domain())).npoints() > 0) - gn = level::compute< typename F::accu_for_gn >(u | set::inter(N, u.domain())); - else - { - finished = true; - gn += F::inc; - } - //std::cout << std::endl << "gN = " << gn << std::endl; - // R <- R union A - // tag the pixels of A. - - for_all(qa) - { - R.insert(qa); - tagged(qa) = true; - } - //std::cout << "exiting step 3" << std::endl; - } - - - /// IF g < gn. - template <typename V, typename P, typename F> - void step4_1 (image2d<V>& u, - p_set<P>& A, - p_set<P>& R, - p_set<P>& N, - V& g, - V& gn, - fllt_node(P, V)*& current_region, - image2d<fllt_node(P, V)*>& regions - ) - { - //std::cout << "entering step 4_1" << std::endl; - - // If the region is bounded - // Create a new conected component. - // FIXME : we can make it faster. - - if ((R.bbox() < u.domain()) || (R.npoints() == u.domain().npoints())) - { - mln_piter(p_set<P>) p(R); - current_region = new fllt_node(P, V)(); - current_region->elt().brighter = F::parent_is_brighter; - current_region->elt().value = g; - for_all(p) - { - current_region->elt().points.insert(p); - - if (regions(p) == 0) - { - //current_region->elt().points.insert(p); - regions(p) = current_region; - } - else - { - if (regions(p)->parent() == 0) - regions(p)->set_parent(current_region); - } - } - - - // Count the number of conected components of the border of R. - static image2d<unsigned> tmp(u.domain().to_larger(1)); - static image2d<bool> border_ima(tmp.domain()); - level::fill(border_ima, false); - - // level::fill(inplace(border_ima | N), true); - // std::cout << "tmp border = " << tmp.border () << std::endl; - // std::cout << "ima border = " << border_ima.border () << std::endl; - mln_piter(p_set<P>) z(N); - for_all(z) - { - mln_assertion(border_ima.owns_(z)); - border_ima(z) = true; - } - unsigned n; - tmp = labeling::level(border_ima, true, F::bdr_nbh(), n); - - // debug::println(border_ima); - //std::cout << "nb composantes :" << n << std::endl; - // debug::println(tmp); - if (n > 1) - { - - // IF number of conected components of the border > 1 - for (int i = 2; i <= n; i++) - { - // follow each border to find which is the exterior border - // and which are the holes. Keep one pixel of each holes. - - // WARNING : We trust labeling::level to label the exterior border with 1. - current_region->elt().holes.insert(a_point_of(tmp | pw::value(tmp) == pw::cst(i))); - - // FIXME : [optimisation] Remove from N border of holes???. - // Recompute gn <- min u(x) x belongs to A - } - } - - } - g = gn; - // A <- {x belongs to N / u(x) == g} - A.clear(); - A = set::uni(A, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); - // N <- N\{x belongs to N / u(x) == g} - N = set::diff(N, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); - - // std::cout << "A :" << std::endl; - // if (A.npoints()) - // debug::println(u | A); - // std::cout << "N :" << std::endl; - // if (N.npoints()) - // debug::println(u | N); - - //std::cout << "exiting step 4_1" << std::endl; - } - - - /// IF g == gn. - template <typename V, typename P> - void step4_2 (const image2d<V>& u, - p_set<P>& A, - p_set<P>& N, - V& g, - fllt_node(P, V)* current_region, - image2d<fllt_node(P, V)*>& regions - ) - { - //std::cout << "entering step 4_2" << std::endl; - - // A <- {x belongs to N / u(x) == g} - A = set::uni(A, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); - // N <- N\{x belongs to N / u(x) == g} - N = set::diff(N, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); - - // std::cout << "A :" << std::endl; - // if (A.npoints()) - // debug::println(u | A); - // std::cout << "N :" << std::endl; - // if (N.npoints()) - // debug::println(u | N); - - //std::cout << "exiting step 4_2" << std::endl; - } - - /// IF g > gn. - template <typename V, typename P> - void step4_3 (image2d<V>& u, - const image2d<bool>& tagged, - const p_set<P>& R, - const V& g) - { - //std::cout << "entering step 4_3" << std::endl; - - // set the gray-level of the pixels of R to g. - mln_piter(p_set<P>) p(R); - for_all(p) - { - mln_assertion (tagged(p)); - u (p) = g; - } - - //std::cout << "exiting step 4_3" << std::endl; - - } - - - template <typename V, typename F> - fllt_tree(point2d, V)& - compute_level_set(const image2d<V>& ima, - image2d< fllt_node(point2d, V)* >& regions) - { - typedef point2d P; - typedef image2d<V> I; - - // FIXME: not nice. - typedef mln::image_if< - mln::image2d<unsigned>, - mln::fun::greater_p2b_expr_<mln::pw::value_<mln::image2d<unsigned> >, - mln::pw::cst_<int> > - > I_IF; - - // Check - mln_assertion(ima.domain() == regions.domain()); - - // Declarations. - p_set<P> R, N, A; - V g, gn; - point2d x0; - image2d<unsigned> min_locals(ima.domain()); - image2d<V> u = clone(ima); - border::fill(u, 0); - - //std::cout << "image U:" << std::endl; - // debug::println_with_border(u); - image2d<bool> tagged(ima.domain()); - fllt_node(P, V)* current_region; - - // INIT - R.clear(); - N.clear(); - A.clear(); - g= 0; - gn = 0; - current_region = 0; - - level::fill(regions, 0); - level::fill(tagged, false); - - // Get the locals extremums - unsigned nlabels; - min_locals = F::regional_extremum(ima, F::reg_nbh(), nlabels); - - // debug::println(min_locals); - // debug::println(min_locals | (pw::value(min_locals) > pw::cst(0))); - - /// Algorithm. - { - // For all locals extremums - //void* x = min_locals | (pw::value(min_locals) > pw::cst(0)); - I_IF min_locals_list(min_locals | (pw::value(min_locals) > pw::cst(0))); - mln_piter(I_IF) p(min_locals_list.domain()); - for_all(p) - { - if (tagged(p)) - continue; - - step1(ima, p, g, x0); - step2(A, R, N, x0); - while (1) - { - //std::cout << "g = " << g << std::endl; - step3<V, P, F>(u, tagged, A, R, N, gn); - /// step4. - if (F::compare(g, gn)) - { - step4_1<V, P, F>(u, A, R, N, g, gn, current_region, regions); - // GO TO 3) - continue; - } - - - if (g == gn) - { - step4_2(u, A, N, g, current_region, regions); - // GO TO 3) - continue; - } - - - if (!F::compare(g, gn)) - { - step4_3(u, tagged, R, g); - // GO TO 1) - break; - } - } - //std::cout << "current_region = " << current_region << std::endl; - } - } // end of Algorithm - - image2d<value::int_u8> output (ima.domain ()); - fllt_tree(P, V)& tree = *new fllt_tree(P, V)(current_region); - util::tree_to_image (tree, output); - - // util::display_tree(ima, tree); - - // debug::println(output); - // std::cout << std::endl; - // debug::println(ima); - - // if (output != ima) - // { - // std::cerr << "BUG!!!" << std::endl; - // abort(); - // } - - // io::pgm::save(output, "out.pgm"); - // std::cout << "out.pgm generate" - // << std::endl; - - - // debug::println(regions); - //debug::println(ima | regions(make:defined reference to `mln::fllt::lower<mln::value::int_u<8u> >::inc':point2d(-4,-1))->elt().points); - - return (tree); - - } // end of compute_level_set - - //Fwd declarations. - template <typename V> struct lower; - template <typename V> struct upper; - - // LOWER LEVEL SET : region = c4, border = c8 - template <typename V> - struct lower - { - typedef upper<V> opposite; - static bool - compare(const V& u, const V& v) - { - return u < v; - } - - template <typename I, typename N, typename L> - static mln_ch_value(I, L) - regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels) - { - return labeling::regional_minima(input, nbh, nlabels); - } - - static const int inc = 1; - static const bool parent_is_brighter = true; - typedef accu::min accu_for_gn; - - static const neighb2d& bdr_nbh() { return c8(); } - static const neighb2d& reg_nbh() { return c4(); } - - }; - - +# include "types.hh" +# include "debug.hh" - // UPPER LEVEL SET : region = c8, border = c4 - template <typename V> - struct upper - { - typedef lower<V> opposite; +# include "lower.hh" +# include "upper.hh" - static bool - compare(const V& u, const V& v) - { - return u > v; - } - - template <typename I, typename N, typename L> - static mln_ch_value(I, L) - regional_extremum(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels) - { - return labeling::regional_maxima(input, nbh, nlabels); - } +# include "compute_level_set.hh" +# include "merge.hh" - static const int inc = -1; - static const bool parent_is_brighter = false; - typedef accu::max accu_for_gn; - - static const neighb2d& bdr_nbh() { return c4(); } - static const neighb2d& reg_nbh() { return c8(); } - }; - - // Fwd declarations. - template <typename P, typename V, typename F> - void - fill_a_shape(fllt_node(P, V)& node, - fllt_tree(P, V)& tree, - const image2d<fllt_node(P, V)*>& node_reg, - const image2d<fllt_node(P, V)*>& hole_reg); - - template <typename P, typename V, typename F> - void - move_shape(fllt_node(P, V)& node, - fllt_node(P, V)& hole, - fllt_tree(P, V)& tree, - const image2d<fllt_node(P, V)*>& hole_reg, - const image2d<fllt_node(P, V)*>& other_reg) - { - // FIXME : debug to remove. - // std::cout << " [move_shape] "<< &hole << " as son of "<< &node << std::endl; - //node.elt().points = set::uni(hole.elt().points, node.elt().points); - node.add_child(&hole); - fill_a_shape<P,V,typename F::opposite>(hole, tree, hole_reg, other_reg); - } - - template <typename P, typename V, typename F> - fllt_node(P, V)* - find_the_hole(fllt_node(P, V)& node, - const P p, - const image2d<fllt_node(P, V)*>& other_reg) - { - fllt_node(P, V)* s = other_reg(p); - mln_assertion(s); - while (s->parent() && F::opposite::compare(s->parent()->elt().value, node.elt().value)) - //FIXME : Was while (s->parent() && (s->parent()->elt().value < node.elt().value)) - { - mln_assertion(s); - s = s->parent(); - mln_assertion(s); - } -// std::cout << " [Find the hole] of " << p -// << " from " << &node -// << " return " << s -// << std::endl; - return s; - } - - template <typename P, typename V, typename F> - void - fill_a_shape(fllt_node(P, V)& node, - fllt_tree(P, V)& tree, - const image2d<fllt_node(P, V)*>& node_reg, - const image2d<fllt_node(P, V)*>& hole_reg) - { -// std::cout << "[Start fill_a_shape] " << &node << " " -// << node.elt().holes.npoints() -// << " holes." << std::endl; - - if (node.elt().holes.npoints() == 0) - { - // std::cout << "[End fill_a_shape]" << std::endl; - return; - } - mln_piter(p_set<P>) p(node.elt().holes); - for_all(p) - { - bool h = true; - - fllt_node(P, V)* hole; - if (node.elt().brighter == F::parent_is_brighter) - hole = find_the_hole<P,V,F>(node, point2d(p), hole_reg); - else - hole = find_the_hole<P,V,typename F::opposite>(node, point2d(p), node_reg); - - mln_assertion(hole); - - typename fllt_node(P, V)::children_t::iterator it; - for (it = node.children().begin(); - it != node.children().end(); - it++) - { - // Browse the hole of each child. - mln_piter(p_set<P>) q((*it)->elt().holes); - for_all(q) - { - fllt_node(P, V)* child_hole = find_the_hole<P,V,F>((**it), point2d(q), hole_reg); - if (set::is_subset_of(hole->elt().points, - child_hole->elt().points)) - -// if (hole->elt().points < child_hole->elt().points) - { - h = false; - break; - } - - } - if (!h) - break; - } - if (h) - move_shape<P,V,F>(node, *hole, tree, hole_reg, node_reg); - } - - node.elt().holes.clear(); - // std::cout << "[end fill_a_shape]" << std::endl; - } - - template <typename P, typename V> - fllt_tree(P, V) - merge_trees(fllt_tree(P, V)& lower_tree, - fllt_tree(P, V)& upper_tree, - const image2d<fllt_node(P, V)*>& low_reg, - const image2d<fllt_node(P, V)*>& upp_reg, - const image2d<V>& ima) - { - - // In order to merge the trees, we only have to find for each shape S - // with a hole H in it whether one of its children has a hole HŽ - // containing H. If it is the case, we do nothing. Otherwise, we - // put the shape of the hole H (and all its descendants) as child of - // the shape . - { - std::cout << "[Merge first tree]------------" << std::endl; - - fllt_branch_iter_ind(P, V) p(lower_tree.main_branch()); - for_all(p) - { - fllt_node(P, V)& n(p); - fill_a_shape< P, V, lower<V> >(n, lower_tree, low_reg, upp_reg); - mln_assertion(lower_tree.check_consistency()); - mln_assertion(upper_tree.check_consistency()); - } - - } - - { - std::cout << "[Merge second tree]------------" << std::endl; - - fllt_branch_iter_ind(P, V) p(upper_tree.main_branch()); - for_all(p) - { - fllt_node(P, V)& n(p); - fill_a_shape< P, V, upper<V> >(n, upper_tree, upp_reg, low_reg); - mln_assertion(lower_tree.check_consistency()); - mln_assertion(upper_tree.check_consistency()); - } - } - - fllt_tree(P, V)* main_tree = &lower_tree; - fllt_tree(P, V)* other_tree = &upper_tree; - - if (lower_tree.root()->elt().points.npoints() >= ima.domain().npoints()) - { - main_tree = &upper_tree; - other_tree = &lower_tree; - } - - typename fllt_node(P, V)::children_t::iterator it; - for (it = other_tree->root()->children().begin(); - it != other_tree->root()->children().end(); ) - { - main_tree->root()->add_child(*it); - } - mln_assertion(main_tree->check_consistency()); - return *main_tree; - } - - - template <typename P, typename V> - void - visualize_deepness(image2d<value::int_u8>& output, - fllt_tree(P, V)& tree) - { - fllt_branch_iter_ind(P, V) p(tree.main_branch()); - level::fill(output, 0); - for_all(p) - { - //std::cout << (&*p) << ":" << p.deepness() << std::endl; - mln_piter(p_set<point2d>) q((*p).elt().points); - for_all(q) - { - if (output(q) < p.deepness()) - output(q) = p.deepness(); - } - } - } - - - template <typename P, typename V> - void - visualize_bounds(image2d<value::int_u8>& output, - fllt_tree(P, V)& tree, - unsigned limit) - { - fllt_branch_iter_ind(P, V) p(tree.main_branch()); - level::fill(output, 255); - for_all(p) - { - if ((*p).elt().points.npoints() > limit) - { - mln_piter(p_set<point2d>) q((*p).elt().points); - for_all(q) - { - mln_niter(neighb2d) n(c4(), q); - bool is_border = false; - for_all (n) - if (!((*p).elt().points).has (n)) - is_border = true; - if (is_border) - output(q) = 0; - } - } - } - } - - template <typename P, typename V> - void - draw_tree(const image2d<V>& ima, - fllt_tree(P, V)& tree) +namespace mln { - fllt_branch_iter_ind(P, V) p(tree.main_branch()); - for_all(p) + namespace fllt { - std::cout << "region mere : " << (*p).parent() << std::endl; - std::cout << " ^" << std::endl; - std::cout << " |" << std::endl; - std::cout << "region : " << &*p - << " value = " << (*p).elt().value << std::endl - << " holes : " - << (*p).elt().holes.npoints() - << (*p).elt().holes - << std::endl; - - debug::println(ima | (*p).elt().points); - std::cout << std::endl; - } - } template <typename V> // Fixme : return type Index: trunk/milena/sandbox/garrigues/fllt/compute_level_set.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/compute_level_set.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/compute_level_set.hh (revision 1753) @@ -0,0 +1,410 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// +// 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_FIXME_FLLT_COMPUTE_LEVEL_SET_HH +# define MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_HH + +/*! \file compute_level_set.hh + * + * \brief Compute Level Set for Fast level line transform. + * + */ + +namespace mln +{ + namespace fllt + { + + + template <typename V> + void step1 (const image2d<V>& ima, + point2d p, + V& g, + point2d& x0) + { + //std::cout << "entering step 1" << std::endl; + // x0 <- a not tagged local mininum of ima. + //std::cout << std::endl << "x0 = " << p << std::endl; + x0 = p; + // g <- u(x0) + g = ima(x0); + //std::cout << "g = " << g << std::endl; + //std::cout << "exiting step 1" << std::endl; + } + + template <typename P> + void step2 (p_set<P>& A, + p_set<P>& R, + p_set<P>& N, + point2d& x0) + { + //std::cout << "entering step 2" << std::endl; + // A <- {x0} + A.clear(); + A.insert(x0); + // R <- {} + R.clear(); + // N <- {} + N.clear(); + //std::cout << "exiting step 2" << std::endl; + } + + + template <typename V, typename P, typename F> + void step3 (const image2d<V>& u, + image2d<bool>& tagged, + p_set<P>& A, + p_set<P>& R, + p_set<P>& N, + V& gn) + { + static bool finished = false; + //std::cout << "entering step 3" << std::endl; + + // Stop the algorithm. + if (finished) + { finished = false; gn -= 2 * F::inc; return; } + + // N <- N union {x neighbor of a pixel in a\R} + mln_piter(p_set<P>) qa(A); + for_all(qa) + { + mln_niter(neighb2d) n(F::reg_nbh(), qa); + for_all (n) + if (!R.has (n)) + N.insert (n); + } + + // debug::println(u); + + // //std::cout << "A :" << std::endl; + // if (A.npoints()) + // //debug::println(u | A); + // //std::cout << "N :" << std::endl; + // if (N.npoints()) + // //debug::println(u | N); + // //std::cout << "R :" << std::endl; + // if (R.npoints()) + // //debug::println(u | R); + + // gn <- min u(x) x belongs to N. + if ((u | set::inter(N, u.domain())).npoints() > 0) + gn = level::compute< typename F::accu_for_gn >(u | set::inter(N, u.domain())); + else + { + finished = true; + gn += F::inc; + } + //std::cout << std::endl << "gN = " << gn << std::endl; + // R <- R union A + // tag the pixels of A. + + for_all(qa) + { + R.insert(qa); + tagged(qa) = true; + } + //std::cout << "exiting step 3" << std::endl; + } + + + /// IF g < gn. + template <typename V, typename P, typename F> + void step4_1 (image2d<V>& u, + p_set<P>& A, + p_set<P>& R, + p_set<P>& N, + V& g, + V& gn, + fllt_node(P, V)*& current_region, + image2d<fllt_node(P, V)*>& regions + ) + { + //std::cout << "entering step 4_1" << std::endl; + + // If the region is bounded + // Create a new conected component. + // FIXME : we can make it faster. + + if ((R.bbox() < u.domain()) || (R.npoints() == u.domain().npoints())) + { + mln_piter(p_set<P>) p(R); + current_region = new fllt_node(P, V)(); + current_region->elt().brighter = F::parent_is_brighter; + current_region->elt().value = g; + for_all(p) + { + current_region->elt().points.insert(p); + + if (regions(p) == 0) + { + //current_region->elt().points.insert(p); + regions(p) = current_region; + } + else + { + if (regions(p)->parent() == 0) + regions(p)->set_parent(current_region); + } + } + + + // Count the number of conected components of the border of R. + static image2d<unsigned> tmp(u.domain().to_larger(1)); + static image2d<bool> border_ima(tmp.domain()); + level::fill(border_ima, false); + + // level::fill(inplace(border_ima | N), true); + // std::cout << "tmp border = " << tmp.border () << std::endl; + // std::cout << "ima border = " << border_ima.border () << std::endl; + mln_piter(p_set<P>) z(N); + for_all(z) + { + mln_assertion(border_ima.owns_(z)); + border_ima(z) = true; + } + unsigned n; + tmp = labeling::level(border_ima, true, F::bdr_nbh(), n); + + // debug::println(border_ima); + //std::cout << "nb composantes :" << n << std::endl; + // debug::println(tmp); + if (n > 1) + { + + // IF number of conected components of the border > 1 + for (int i = 2; i <= n; i++) + { + // follow each border to find which is the exterior border + // and which are the holes. Keep one pixel of each holes. + + // WARNING : We trust labeling::level to label the exterior border with 1. + current_region->elt().holes.insert(a_point_of(tmp | pw::value(tmp) == pw::cst(i))); + + // FIXME : [optimisation] Remove from N border of holes???. + // Recompute gn <- min u(x) x belongs to A + } + } + + } + g = gn; + // A <- {x belongs to N / u(x) == g} + A.clear(); + A = set::uni(A, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + // N <- N\{x belongs to N / u(x) == g} + N = set::diff(N, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + + // std::cout << "A :" << std::endl; + // if (A.npoints()) + // debug::println(u | A); + // std::cout << "N :" << std::endl; + // if (N.npoints()) + // debug::println(u | N); + + //std::cout << "exiting step 4_1" << std::endl; + } + + + /// IF g == gn. + template <typename V, typename P> + void step4_2 (const image2d<V>& u, + p_set<P>& A, + p_set<P>& N, + V& g, + fllt_node(P, V)* current_region, + image2d<fllt_node(P, V)*>& regions + ) + { + //std::cout << "entering step 4_2" << std::endl; + + // A <- {x belongs to N / u(x) == g} + A = set::uni(A, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + // N <- N\{x belongs to N / u(x) == g} + N = set::diff(N, set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + + // std::cout << "A :" << std::endl; + // if (A.npoints()) + // debug::println(u | A); + // std::cout << "N :" << std::endl; + // if (N.npoints()) + // debug::println(u | N); + + //std::cout << "exiting step 4_2" << std::endl; + } + + /// IF g > gn. + template <typename V, typename P> + void step4_3 (image2d<V>& u, + const image2d<bool>& tagged, + const p_set<P>& R, + const V& g) + { + //std::cout << "entering step 4_3" << std::endl; + + // set the gray-level of the pixels of R to g. + mln_piter(p_set<P>) p(R); + for_all(p) + { + mln_assertion (tagged(p)); + u (p) = g; + } + + //std::cout << "exiting step 4_3" << std::endl; + + } + + + template <typename V, typename F> + fllt_tree(point2d, V)& + compute_level_set(const image2d<V>& ima, + image2d< fllt_node(point2d, V)* >& regions) + { + typedef point2d P; + typedef image2d<V> I; + + // FIXME: not nice. + typedef mln::image_if< + mln::image2d<unsigned>, + mln::fun::greater_p2b_expr_<mln::pw::value_<mln::image2d<unsigned> >, + mln::pw::cst_<int> > + > I_IF; + + // Check + mln_assertion(ima.domain() == regions.domain()); + + // Declarations. + p_set<P> R, N, A; + V g, gn; + point2d x0; + image2d<unsigned> min_locals(ima.domain()); + image2d<V> u = clone(ima); + border::fill(u, 0); + + //std::cout << "image U:" << std::endl; + // debug::println_with_border(u); + image2d<bool> tagged(ima.domain()); + fllt_node(P, V)* current_region; + + // INIT + R.clear(); + N.clear(); + A.clear(); + g= 0; + gn = 0; + current_region = 0; + + level::fill(regions, 0); + level::fill(tagged, false); + + // Get the locals extremums + unsigned nlabels; + min_locals = F::regional_extremum(ima, F::reg_nbh(), nlabels); + + // debug::println(min_locals); + // debug::println(min_locals | (pw::value(min_locals) > pw::cst(0))); + + /// Algorithm. + { + // For all locals extremums + //void* x = min_locals | (pw::value(min_locals) > pw::cst(0)); + I_IF min_locals_list(min_locals | (pw::value(min_locals) > pw::cst(0))); + mln_piter(I_IF) p(min_locals_list.domain()); + for_all(p) + { + if (tagged(p)) + continue; + + step1(ima, p, g, x0); + step2(A, R, N, x0); + while (1) + { + //std::cout << "g = " << g << std::endl; + step3<V, P, F>(u, tagged, A, R, N, gn); + /// step4. + if (F::compare(g, gn)) + { + step4_1<V, P, F>(u, A, R, N, g, gn, current_region, regions); + // GO TO 3) + continue; + } + + + if (g == gn) + { + step4_2(u, A, N, g, current_region, regions); + // GO TO 3) + continue; + } + + + if (!F::compare(g, gn)) + { + step4_3(u, tagged, R, g); + // GO TO 1) + break; + } + } + //std::cout << "current_region = " << current_region << std::endl; + } + } // end of Algorithm + + image2d<value::int_u8> output (ima.domain ()); + fllt_tree(P, V)& tree = *new fllt_tree(P, V)(current_region); + util::tree_to_image (tree, output); + + // util::display_tree(ima, tree); + + // debug::println(output); + // std::cout << std::endl; + // debug::println(ima); + + // if (output != ima) + // { + // std::cerr << "BUG!!!" << std::endl; + // abort(); + // } + + // io::pgm::save(output, "out.pgm"); + // std::cout << "out.pgm generate" + // << std::endl; + + + // debug::println(regions); + //debug::println(ima | regions(make:defined reference to `mln::fllt::lower<mln::value::int_u<8u> >::inc':point2d(-4,-1))->elt().points); + + return (tree); + + } // end of compute_level_set + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_HH
participants (1)
-
Matthieu Garrigues