
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2008-04-16 Matthieu Garrigues <garrigues@lrde.epita.fr> Commit my last version of fllt. * sandbox/garrigues/fllt/compute_level_set_fast.hh: New. * sandbox/garrigues/fllt/compute_level_set_fast2.hh: New. * sandbox/garrigues/fllt/debug.hh: . * sandbox/garrigues/fllt/doc.hh: . * sandbox/garrigues/fllt/fllt.hh: . * sandbox/garrigues/fllt/give_confs.cc: New. * sandbox/garrigues/fllt/local_configurations.hh: New. * sandbox/garrigues/fllt/lower.hh: . * sandbox/garrigues/fllt/test.cc: New. * sandbox/garrigues/fllt/test_fllt2.cc: . * sandbox/garrigues/fllt/types.hh: . * sandbox/garrigues/fllt/upper.hh: . --- compute_level_set_fast.hh | 486 +++++++++++++++++++++++++++++++++++++++++++++ compute_level_set_fast2.hh | 471 +++++++++++++++++++++++++++++++++++++++++++ debug.hh | 83 +++++++ doc.hh | 1 fllt.hh | 49 ---- give_confs.cc | 56 +++++ local_configurations.hh | 144 +++++++++++++ lower.hh | 4 test.cc | 62 +++++ test_fllt2.cc | 4 types.hh | 150 +++++++++++++ upper.hh | 4 12 files changed, 1460 insertions(+), 54 deletions(-) Index: trunk/milena/sandbox/garrigues/fllt/lower.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/lower.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/lower.hh (revision 1870) @@ -36,6 +36,7 @@ */ # include <mln/core/neighb2d.hh> +# include <mln/core/clock_neighb2d.hh> # include <mln/labeling/regional_minima.hh> # include <mln/accu/min.hh> @@ -75,6 +76,9 @@ static const neighb2d& bdr_nbh() { return c8(); } static const neighb2d& reg_nbh() { return c4(); } + static const clock_neighb2d bdr_c_nbh(dpoint2d& dp) { return cc8(dp); } + static const clock_neighb2d reg_c_nbh(dpoint2d& dp) { return cc4(dp); } + }; } // end of namespace mln::fllt Index: trunk/milena/sandbox/garrigues/fllt/upper.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/upper.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/upper.hh (revision 1870) @@ -36,6 +36,7 @@ */ # include <mln/core/neighb2d.hh> +# include <mln/core/clock_neighb2d.hh> # include <mln/labeling/regional_maxima.hh> # include <mln/accu/max.hh> @@ -74,6 +75,9 @@ static const neighb2d& bdr_nbh() { return c4(); } static const neighb2d& reg_nbh() { return c8(); } + + static const clock_neighb2d bdr_c_nbh(dpoint2d& dp) { return cc4(dp); } + static const clock_neighb2d reg_c_nbh(dpoint2d& dp) { return cc8(dp); } }; } // end of namespace mln::fllt Index: trunk/milena/sandbox/garrigues/fllt/types.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/types.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/types.hh (revision 1870) @@ -39,6 +39,12 @@ # include <mln/util/tree.hh> # include <mln/util/branch_iter_ind.hh> + +# define fllt_tree(P, V) mln::util::tree< mln::fllt::fllt_node_elt<P, V> > +# define fllt_node(P, V) mln::util::tree_node< mln::fllt::fllt_node_elt<P, V> > +# define fllt_branch(P, V) mln::util::branch< mln::fllt::fllt_node_elt<P, V> > +# define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< mln::fllt::fllt_node_elt<P, V> > + namespace mln { namespace fllt @@ -55,13 +61,147 @@ 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 + + class ran_domains + { + public: + + /// Forward Point_Iterator associated type. + typedef mln_fwd_piter_(box2d) fwd_piter; + + /// Backward Point_Iterator associated type. + typedef mln_bkd_piter_(box2d) bkd_piter; + + /// Constructor. + ran_domains(const box2d& b); + + /// Add a point to a domain. + template <char domain> + ran_domains& add_to(const point2d& p); + + /// Test if a point belong to a domain. + template <char domain> + bool belongs_to(const point2d& p) const; + + /// Move a point from a domain to another domain. + template <char src, char dest> + ran_domains& move_to(const point2d& p); + + /// Clear the image. + void clear(); + + /// Give the exact bounding box. + const box2d& bbox() const; + + /// Give the number of points. + unsigned npoints() const; + + /// Hook to the image2d containing the points. + sub_image<image2d<value::int_u8>, box2d> image(); + + private: + image2d<value::int_u8> ima_; + unsigned npoints_; + accu::bbox<point2d> bb_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + inline + ran_domains::ran_domains(const box2d& b) + : ima_(b) + { + bb_.init(); + npoints_ = 0; + + level::fill(ima_, false); + } + + template <char domain> + inline + ran_domains& + ran_domains::add_to(const point2d& p) + { + bb_.take(p); + ima_(p) = domain; + npoints_++; + return *this; + } + + + template <char src, char dest> + ran_domains& + ran_domains::move_to(const point2d& p) + { + mln_assertion(ima_(p) == src); + ima_(p) += dest - src; + return *this; + } + + template <char domain> + inline + bool + ran_domains::belongs_to(const point2d& p) const + { + return ima_(p) == domain; + } + + + void + ran_domains::clear() + { + if (npoints_ == 0) + return; + + // unsigned bb_nrows = geom::nrows(bb_.to_result()); + // unsigned ima_nrows = geom::nrows(points_); + + // if (bb_nrows * 3 < ima_nrows * 2) + // { + // unsigned bb_ncols = geom::ncols(bb_.to_result()); + // mln_line_piter_(image2d<value::int_u8>) p(bb_.to_result()); + // for_all(p) + // { + // level::memset_(ima_, p, false, bb_ncols); + // } + // } + // else + level::fill(ima_, false); + + npoints_ = 0; + bb_.init(); + } + + + inline + const box2d& + ran_domains::bbox() const + { + mln_precondition(npoints_ != 0); + return bb_.to_result(); + } + + inline + unsigned + ran_domains::npoints() const + { + return npoints_; + } + + inline + sub_image<image2d<value::int_u8>, box2d> + ran_domains::image() + { + mln_precondition(npoints_ > 0); + mln_assertion(ima_.has_data()); + return ima_ | bb_.to_result(); + } + +# endif // ! MLN_INCLUDE_ONLY + } // end of namespace mln::fllt } // end of namespace mln Index: trunk/milena/sandbox/garrigues/fllt/doc.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/doc.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/doc.hh (revision 1870) @@ -58,6 +58,7 @@ // gn <- min u(x) x belongs to N. // R <- R union A // tag the pixels of A. + // Update the number of holes of R. // 4) // IF g < gn Index: trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast2.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast2.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast2.hh (revision 1870) @@ -0,0 +1,471 @@ +// 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_FAST_HH +# define MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_FAST_HH + +/*! \file compute_level_set_fast2.hh + * + * \brief Compute Level Set for Fast level line transform. + * Version with one image for A, R, N. + * + */ + +# include <mln/core/p_image2d.hh> +# include <mln/core/image_if_value.hh> +# include "local_configurations.hh" + +# define SET_R 3 +# define SET_A 2 +# define SET_N 1 + +# define image_sub_if_value image_if_value<const sub_image<image2d<value::int_u8>, box2d> > + +namespace mln +{ + namespace fllt_fast + { + using namespace fllt; + + class fllt::ran_domains; + + template <typename V> + void step_fast1 (const image2d<V>& ima, + point2d p, + V& g, + point2d& x0) + { + //std::cout << "entering step_fast 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_fast 1" << std::endl; + } + + void step_fast2 (ran_domains& r_a_n, + point2d& x0) + { + //std::cout << "entering step_fast 2" << std::endl; + // R <- {} + // N <- {} + // A <- {x0} + r_a_n.clear(); + r_a_n.add_to<SET_A>(x0); + + + //std::cout << "exiting step_fast 2" << std::endl; + } + + + template <typename V, typename F> + void step_fast3 (const image2d<V>& u, + image2d<bool>& tagged, + ran_domains& r_a_n, + V& gn, + fllt_node(point2d, V)*& current_region, + image2d<fllt_node(point2d, V)*>& regions) + { + static bool finished = false; + //std::cout << "entering step_fast 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_image2d<P>) qa(A); + + // p_image2d_fwd_pixter<point2d> qa(A); + image_sub_if_value ima(r_a_n.image() | SET_A); + mln_assertion(ima.has_data()); + image_sub_if_value::fwd_piter qa(ima.domain()); + mln_assertion(ima.has_data()); + for_all(qa) + { + mln_assertion(ima.has_data()); + mln_niter(neighb2d) n(F::reg_nbh(), qa); + for_all (n) + if (u.has(n) && !r_a_n.belongs_to<SET_R>(n) && + !r_a_n.belongs_to<SET_A>(n)) + r_a_n.add_to<SET_N>(n); + } + + // debug::println(u); + +// std::cout << "A :" << A << std::endl; +// debug::println(A.image()); +// std::cout << "N :" << N << std::endl; +// debug::println(N.image()); +// std::cout << "R :" << R << std::endl; +// debug::println(R.image()); + + // gn <- min u(x) x belongs to N. + + image_sub_if_value tmp(r_a_n.image() | SET_N); + finished = tmp.npoints() == 0; + + if (!finished) + gn = level::compute< typename F::accu_for_gn >(u | tmp.domain()); + + if (finished) + gn += F::inc; + + //std::cout << std::endl << "gN = " << gn << std::endl; + // R <- R union A + // tag the pixels of A. + + for_all(qa) + { + if (!r_a_n.belongs_to<SET_A>(qa)) + continue; +// std::cout << "Added to R" << tmp << std::endl; + mln_assertion(!r_a_n.belongs_to<SET_R>(qa)); + r_a_n.move_to<SET_A, SET_R>(qa); + tagged(qa) = true; + // Update the number of holes of R. + //n_added_holes<point2d, F>(R, qa); + } + + + //std::cout << "exiting step_fast 3" << std::endl; + } + + + template <typename V> + void update_set(const image2d<V>& u, + ran_domains& r_a_n, + V& g) + { + // A <- {x belongs to N / u(x) == g} + + // This is slow. + // A.insert(set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + + // N <- N\{x belongs to N / u(x) == g} + // N.remove(set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + // mln_assertion(check_step_4_2(u, N, g)); + + // This is faster. + +// if (N.npoints() >= 0) +// { + image_sub_if_value tmp(r_a_n.image() | SET_N); + image_sub_if_value::fwd_piter qn(tmp.domain()); + for_all(qn) + { + if (u(qn) == g) + r_a_n.move_to<SET_N, SET_A>(qn); + } +// } +// else { +// mln_fwd_piter(p_image2d<P>) p(N); +// for_all(p) +// { +// if (u(p) == g) +// { +// A.insert(p); +// N.remove(p); +// } +// } +// mln_assertion(check_step_4_2(u, N, g)); +// } + } + /// IF g < gn. + template <typename V, typename F> + void step_fast4_1 (image2d<V>& u, + ran_domains& r_a_n, + V& g, + V& gn, + fllt_node(point2d, V)*& current_region, + image2d<fllt_node(point2d, V)*>& regions + ) + { +// std::cout << "entering step_fast 4_1" << std::endl; + + // If the region is bounded + // Create a new conected component. + // FIXME : we can make it faster. + + // FIXME : rewrite this test. + // if ((R.bbox() < u.domain()) || (R.npoints() == u.domain().npoints())) +// { + image_sub_if_value tmp(r_a_n.image() | SET_R); + image_sub_if_value::fwd_piter p(tmp.domain()); + current_region = new fllt_node(point2d, 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_image2d<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; + + update_set(u, r_a_n, 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_fast 4_1" << std::endl; + } + + /// IF g == gn. + template <typename V, typename P> + void step_fast4_2 (const image2d<V>& u, + ran_domains& r_a_n, + V& g, + fllt_node(P, V)* current_region, + image2d<fllt_node(P, V)*>& regions + ) + { +// std::cout << "entering step_fast 4_2" << std::endl; + + update_set(u,r_a_n,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_fast 4_2" << std::endl; + } + + /// IF g > gn. + template <typename V> + void step_fast4_3 (image2d<V>& u, + const image2d<bool>& tagged, + ran_domains& r_a_n, + const V& g) + { +// std::cout << "entering step_fast 4_3" << std::endl; + + // set the gray-level of the pixels of R to g. + image_sub_if_value tmp(r_a_n.image() | SET_R); + image_sub_if_value::fwd_piter p(tmp.domain()); + for_all(p) + { + mln_assertion (tagged(p)); + u (p) = g; + } +// std::cout << "exiting step_fast 4_3" << std::endl; + + } + + + template <typename V, typename F> + fllt_tree(point2d, V)& + compute_level_set_fast(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. + ran_domains r_a_n(ima.domain()); + 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 + 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 + I_IF min_locals_list(min_locals | (pw::value(min_locals) > pw::cst(0))); + mln_piter(I_IF) p(min_locals_list.domain()); + int cpt = 0, snapshop = 0; + for_all(p) + { + if (tagged(p)) + continue; + + //std::cout << "boucle no " << cpt++ << std::endl; + step_fast1(ima, p, g, x0); + step_fast2(r_a_n, x0); + while (1) + { + // To have a view of the progression of the algotithm. +#ifdef FLLT_TRACE + save_state(ima, r_a_n); +#endif + //std::cout << "g = " << g << std::endl; + step_fast3<V, F>(u, tagged, r_a_n, gn, current_region, regions); + /// step_fast4. + if (F::compare(g, gn)) + { + step_fast4_1<V, F>(u, r_a_n, g, gn, current_region, regions); + // GO TO 3) + continue; + } + + + if (g == gn) + { + step_fast4_2(u, r_a_n, g, current_region, regions); + // GO TO 3) + continue; + } + + + if (!F::compare(g, gn)) + { + step_fast4_3(u, tagged, r_a_n, 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_fast + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_FAST_HH Index: trunk/milena/sandbox/garrigues/fllt/debug.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/debug.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/debug.hh (revision 1870) @@ -35,6 +35,12 @@ * */ +# include <iomanip> +# include <iostream> +# include <sstream> +# include "mln/core/p_image2d.hh" +# include "mln/literal/all.hh" +# include "mln/io/ppm/save.hh" # include "types.hh" namespace mln @@ -113,6 +119,83 @@ } } + template <typename P, typename V> + void + debug(const image2d<V>& ima, + fllt_tree(P, V)& result_tree) + { + std::cout << "4/ Generate outputs." << std::endl; + + image2d<value::int_u8> output (ima.domain ()); + util::tree_to_image (result_tree, output); + + + // io::pgm::save(output, "out_final.pgm"); + // std::cout << "out_final.pgm generate" + // << std::endl; + + + // util::display_tree(ima, lower_tree); + draw_tree(ima, result_tree); + + // debug::println(ima); + // debug::println(output); + + // if (output != ima) + // { + // std::cerr << "BUG!!!" << std::endl; + // abort(); + // } + + image2d<value::int_u8> viz(ima.domain()); + // image2d<value::int_u8> viz2(ima.domain()); + + // visualize_deepness(viz, lower_tree); + // level::stretch(viz, viz2); + // debug::println(viz); + // debug::println(viz2); + // io::pgm::save(viz2, "fllt.pgm"); + + visualize_bounds(viz, result_tree, 200); + //debug::println(viz); + io::pgm::save(viz, "fllt_bounds_200.pgm"); + + visualize_bounds(viz, result_tree, 100); + io::pgm::save(viz, "fllt_bounds_100.pgm"); + + visualize_bounds(viz, result_tree, 50); + io::pgm::save(viz, "fllt_bounds_50.pgm"); + + visualize_bounds(viz, result_tree, 20); + io::pgm::save(viz, "fllt_bounds_20.pgm"); + + } + + template <typename P, typename V> + void save_state(const image2d<V>& ima, + const p_image2d<P>& R, + const p_image2d<P>& A, + const p_image2d<P>& N) + { + static int id = 0; + std::stringstream filename; + filename << "fllt_trace_" << std::setw(5) << std::setfill('0') + << std::right << id++ << ".ppm"; + + image2d<value::rgb8> out(ima.domain()); + + level::fill(out, literal::white); + + if (R.npoints() != 0) + level::fill(inplace(out | R), literal::green); + if (A.npoints() != 0) + level::fill(inplace(out | A), literal::blue); + if (N.npoints() != 0) + level::fill(inplace(out | N), literal::red); + + io::ppm::save(out, filename.str()); + } + } // end of namespace mln::fllt } // end of namespace mln Index: trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/compute_level_set_fast.hh (revision 1870) @@ -0,0 +1,486 @@ +// 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_FAST_HH +# define MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_FAST_HH + +/*! \file compute_level_set_fast.hh + * + * \brief Compute Level Set for Fast level line transform. + * Version with three p_image2d for A, R, N. + * + */ + +# include <mln/core/p_image2d.hh> +# include "local_configurations.hh" + +namespace mln +{ + namespace fllt_fast + { + using namespace fllt; + + template <typename V> + void step_fast1 (const image2d<V>& ima, + point2d p, + V& g, + point2d& x0) + { + //std::cout << "entering step_fast 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_fast 1" << std::endl; + } + + template <typename P> + void step_fast2 (p_image2d<P>& A, + p_image2d<P>& R, + p_image2d<P>& N, + point2d& x0) + { + //std::cout << "entering step_fast 2" << std::endl; + // A <- {x0} + A.clear(); + A.insert(x0); + // R <- {} + R.clear(); + // N <- {} + N.clear(); + //std::cout << "exiting step_fast 2" << std::endl; + } + + + template <typename V, typename P, typename F> + void step_fast3 (const image2d<V>& u, + image2d<bool>& tagged, + p_image2d<P>& A, + p_image2d<P>& R, + p_image2d<P>& N, + V& gn, + fllt_node(P, V)*& current_region, + image2d<fllt_node(P, V)*>& regions) + { + static bool finished = false; + //std::cout << "entering step_fast 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_image2d<P>) qa(A); + + // p_image2d_fwd_pixter<point2d> qa(A); + p_image2d_fwd_piter_<point2d> qa(A); + for_all(qa) + { + mln_niter(neighb2d) n(F::reg_nbh(), qa); + for_all (n) + if (u.has(n) && !R.has (n) && !A.has (n)) + N.insert (n); + } + + // debug::println(u); + +// std::cout << "A :" << A << std::endl; +// debug::println(A.image()); +// std::cout << "N :" << N << std::endl; +// debug::println(N.image()); +// std::cout << "R :" << R << std::endl; +// debug::println(R.image()); + + // gn <- min u(x) x belongs to N. + + finished = N.npoints() == 0; + + if (!finished) + gn = level::compute< typename F::accu_for_gn >(u | N); + else + gn += F::inc; + + //std::cout << std::endl << "gN = " << gn << std::endl; + // R <- R union A + // tag the pixels of A. + + for_all(qa) + { + point2d tmp = qa; +// std::cout << "Added to R" << tmp << std::endl; + mln_assertion(!R.has(tmp)); + R.insert(tmp); + tagged(tmp) = true; + // Update the number of holes of R. + //n_added_holes<point2d, F>(R, qa); + } + + + //std::cout << "exiting step_fast 3" << std::endl; + } + + + template <typename V, typename P> + void update_set(const image2d<V>& u, + p_image2d<P>& A, + p_image2d<P>& N, + V& g) + { + // A <- {x belongs to N / u(x) == g} + A.clear(); + mln_assertion(A.is_empty()); + + // This is slow. + // A.insert(set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + + // N <- N\{x belongs to N / u(x) == g} + // N.remove(set::inter(N, u.domain()) | pw::value(u) == pw::cst(g)); + // mln_assertion(check_step_4_2(u, N, g)); + + // This is faster. + +// if (N.npoints() >= 0) +// { + p_image2d_fwd_pixter<point2d> pxl(N); + for_all(pxl) + { + point2d tmp = pxl.to_point(); + if (u(tmp) == g) + { + A.insert(tmp); + N.remove(tmp); + } + } +// } +// else { +// mln_fwd_piter(p_image2d<P>) p(N); +// for_all(p) +// { +// if (u(p) == g) +// { +// A.insert(p); +// N.remove(p); +// } +// } +// mln_assertion(check_step_4_2(u, N, g)); +// } + } + /// IF g < gn. + template <typename V, typename P, typename F> + void step_fast4_1 (image2d<V>& u, + p_image2d<P>& A, + p_image2d<P>& R, + p_image2d<P>& N, + V& g, + V& gn, + fllt_node(P, V)*& current_region, + image2d<fllt_node(P, V)*>& regions + ) + { +// std::cout << "entering step_fast 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_image2d<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_image2d<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; + + update_set(u,A,N,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_fast 4_1" << std::endl; + } + + + template <typename V, typename P> + bool check_step_4_2(const image2d<V>& u, + p_image2d<P>& N, + V& g) + { + mln_fwd_piter(p_image2d<P>) p(N); + for_all(p) + { + mln_assertion(u(p) != g); + } + return true; + } + + + /// IF g == gn. + template <typename V, typename P> + void step_fast4_2 (const image2d<V>& u, + p_image2d<P>& A, + p_image2d<P>& N, + V& g, + fllt_node(P, V)* current_region, + image2d<fllt_node(P, V)*>& regions + ) + { +// std::cout << "entering step_fast 4_2" << std::endl; + + update_set(u,A,N,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_fast 4_2" << std::endl; + } + + /// IF g > gn. + template <typename V, typename P> + void step_fast4_3 (image2d<V>& u, + const image2d<bool>& tagged, + const p_image2d<P>& R, + const V& g) + { +// std::cout << "entering step_fast 4_3" << std::endl; + + // set the gray-level of the pixels of R to g. + mln_piter(p_image2d<P>) p(R); + for_all(p) + { + mln_assertion (tagged(p)); + u (p) = g; + } +// std::cout << "exiting step_fast 4_3" << std::endl; + + } + + + template <typename V, typename F> + fllt_tree(point2d, V)& + compute_level_set_fast(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_image2d<P> R(ima.domain()), + N(ima.domain()), + A(ima.domain()); + + 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 + I_IF min_locals_list(min_locals | (pw::value(min_locals) > pw::cst(0))); + mln_piter(I_IF) p(min_locals_list.domain()); + int cpt = 0, snapshop = 0; + for_all(p) + { + if (tagged(p)) + continue; + + //std::cout << "boucle no " << cpt++ << std::endl; + step_fast1(ima, p, g, x0); + step_fast2(A, R, N, x0); + mln_assertion(R.is_empty() && N.is_empty()); + while (1) + { + // To have a view of the progression of the algotithm. +#ifdef FLLT_TRACE + save_state(ima, R, A, N); +#endif + //std::cout << "g = " << g << std::endl; + step_fast3<V, P, F>(u, tagged, A, R, N, gn, current_region, regions); + /// step_fast4. + if (F::compare(g, gn)) + { + step_fast4_1<V, P, F>(u, A, R, N, g, gn, current_region, regions); + // GO TO 3) + continue; + } + + + if (g == gn) + { + step_fast4_2(u, A, N, g, current_region, regions); + // GO TO 3) + continue; + } + + + if (!F::compare(g, gn)) + { + step_fast4_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_fast + + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_COMPUTE_LEVEL_SET_FAST_HH Index: trunk/milena/sandbox/garrigues/fllt/fllt.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/fllt.hh (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/fllt.hh (revision 1870) @@ -94,7 +94,7 @@ template <typename V> // Fixme : return type - void + fllt_tree(point2d, V) fllt(const image2d<V>& ima) { typedef point2d P; @@ -124,52 +124,7 @@ //fllt_tree(P, V) result_tree = merge_trees(upper_tree, lower_tree, upp_reg, low_reg, ima); fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, ima); - - std::cout << "4/ Generate outputs." << std::endl; - - image2d<value::int_u8> output (ima.domain ()); - util::tree_to_image (result_tree, output); - - - // io::pgm::save(output, "out_final.pgm"); - // std::cout << "out_final.pgm generate" - // << std::endl; - - - // util::display_tree(ima, lower_tree); - draw_tree(ima, result_tree); - - // debug::println(ima); - // debug::println(output); - - // if (output != ima) - // { - // std::cerr << "BUG!!!" << std::endl; - // abort(); - // } - - image2d<value::int_u8> viz(ima.domain()); - // image2d<value::int_u8> viz2(ima.domain()); - - // visualize_deepness(viz, lower_tree); - // level::stretch(viz, viz2); - // debug::println(viz); - // debug::println(viz2); - // io::pgm::save(viz2, "fllt.pgm"); - - visualize_bounds(viz, result_tree, 200); - //debug::println(viz); - io::pgm::save(viz, "fllt_bounds_200.pgm"); - - visualize_bounds(viz, result_tree, 100); - io::pgm::save(viz, "fllt_bounds_100.pgm"); - - visualize_bounds(viz, result_tree, 50); - io::pgm::save(viz, "fllt_bounds_50.pgm"); - - visualize_bounds(viz, result_tree, 20); - io::pgm::save(viz, "fllt_bounds_20.pgm"); - + return result_tree; } } // end of namespace mln::fllt Index: trunk/milena/sandbox/garrigues/fllt/local_configurations.hh =================================================================== --- trunk/milena/sandbox/garrigues/fllt/local_configurations.hh (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/local_configurations.hh (revision 1870) @@ -0,0 +1,144 @@ +// 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_LOCAL_CONFIGURATIONS_HH +# define MLN_FIXME_FLLT_LOCAL_CONFIGURATIONS_HH + +/*! \file local_configurations.hh + * + * \brief Stuffs related to local configurations for the FLLT. + * + */ + +#include <mln/core/clock_neighb2d.hh> +#include "upper.hh" +#include "lower.hh" + +namespace mln +{ + namespace fllt + { + + template <typename V> + struct lower; + + template <typename V> + struct upper; + + template <typename F> + struct added_holes; + + template <typename V> + struct added_holes<upper<V> > + { + // For each possible configuration (of the c8-neighbourghood) of the + // added pixel, stock the number of added holes. + // ==> region with c8, holes with c4. + static char ret[256]; + }; + + template <typename V> + char added_holes<upper<V> >::ret[256] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + + 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, -1, 0, -1, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, -1, 0, -1, + + 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, + 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + + 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, -1, 0, -1, + 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, + 0, 0, 1, 0, 0, -1, 0, -1, 0, 0, 1, 0, 0, -1, 0, -1 + }; + + template <typename V> + struct added_holes<lower<V> > + { + // For each possible configuration (of the c4-neighbourghood) of the + // added pixel, stock the number of added holes. + // ==> region with c4, holes with c8. + static char ret[256]; + }; + + template <typename V> + char added_holes<lower<V> >::ret[256] = + { + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, + 1, 2, 1, 2, 2, 3, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 1, 2, 1, 1, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, + + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1 + }; + + template <typename P, typename F> + char n_added_holes(const p_image2d<P>& set, const point2d& p) + { + unsigned char res = 0; + dpoint2d dp(1,1); + clock_neighb2d nbh = F::reg_c_nbh(dp); + mln_fwd_niter_(clock_neighb2d) n(nbh , p); + for_all(n) + { + res = (res << 1); + if (set.has(n)) + res = res | 1; + } +// std::cout << int(res) << ":" << int(added_holes<F>::ret[res]) << " hole added." << std::endl; + return added_holes<F>::ret[res]; + } + } // end of namespace mln::fllt + +} // end of namespace mln + + + +#endif // ! MLN_FIXME_FLLT_HH Index: trunk/milena/sandbox/garrigues/fllt/test.cc =================================================================== --- trunk/milena/sandbox/garrigues/fllt/test.cc (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/test.cc (revision 1870) @@ -0,0 +1,62 @@ +# include "fllt.hh" +//# include "compute_level_set.hh" + +# include "compute_level_set_fast2.hh" + +# include <mln/core/image2d.hh> +# include <mln/core/cast_image.hh> +# include <mln/core/clone.hh> +# include <mln/value/int_u8.hh> +# include <mln/debug/println.hh> +# include <mln/convert/to_w_window.hh> +# include <mln/core/w_window2d_int.hh> +# include <mln/convert/to_image.hh> +# include <mln/level/fill.hh> +# include <mln/io/pgm/load.hh> +# include <mln/io/pbm/load.hh> + +int main() +{ + + using namespace mln; + + typedef point2d P; + typedef int V; + + //trace::quiet = false; + +// V ws[81] = {5,5,5,5,5,5,5,5,5, +// 5,5,5,5,5,5,5,5,5, +// 5,5,5,5,5,5,8,8,5, +// 5,5,5,9,5,5,8,8,5, +// 5,5,5,9,5,5,8,8,5, +// 5,5,5,5,5,5,8,8,5, +// 5,5,5,5,5,5,8,8,5, +// 5,5,5,5,5,5,5,5,5, +// 5,5,5,5,5,5,5,5,5}; + +// w_window2d_int w_win = make::w_window2d(ws); +// image2d<V> ima = convert::to_image(w_win); + + image2d<value::int_u8> ima_ = io::pgm::load<value::int_u8>("small.pgm"); + image2d<V> ima(ima_.domain()); + + level::fill(ima, ima_); + +// { +// image2d<fllt_node(P, V)*> low_reg(ima.domain()); +// fllt_tree(P, V) lower_tree; +// lower_tree +// = fllt::compute_level_set<V, fllt::lower<V> >(ima, low_reg); +// fllt::draw_tree(ima, lower_tree); +// } + + + { + image2d<fllt_node(P, V)*> low_reg(ima.domain()); + fllt_tree(P, V) lower_tree; + lower_tree + = fllt_fast::compute_level_set_fast<V, fllt::upper<V> >(ima, low_reg); + //fllt::draw_tree(ima, lower_tree); + } +} Index: trunk/milena/sandbox/garrigues/fllt/give_confs.cc =================================================================== --- trunk/milena/sandbox/garrigues/fllt/give_confs.cc (revision 0) +++ trunk/milena/sandbox/garrigues/fllt/give_confs.cc (revision 1870) @@ -0,0 +1,56 @@ +#include <mln/core/image2d.hh> +#include <mln/core/point2d.hh> +#include <mln/core/p_set.hh> +#include <mln/core/clock_neighb2d.hh> +#include <mln/core/neighb2d.hh> + +#include <mln/labeling/level.hh> +#include <mln/level/fill.hh> +#include <mln/debug/println.hh> +#include <iomanip> + +int main() +{ + using namespace mln; + using namespace mln::value; + + image2d<bool> ima(3,3); + point2d p(1,1); + dpoint2d dp(-1,0); + clock_neighb2d nbh = cc8(dp); + int n_holes = 0; + + bool tab[8][8]; + for (int i = 0; i < 256; i++) + { + level::fill(ima, false); + int_u8 tmp = i; + + mln_fwd_niter_(clock_neighb2d) n(nbh , p); + for_all(n) + { + if (tmp % 2) + ima(n) = true; + tmp = tmp >> 1; + } + + + int x, y; + labeling::level(ima, false, c8(), x); + + + ima(p) = true; + labeling::level(ima, false, c8(), y); + +// std::cout << "----- conf no " << i << "------" << std::endl; +// debug::println(ima); +// std::cout << "----- " << x << " holes before------" << std::endl; +// std::cout << "----- " << y << " holes after------" << std::endl; +// std::cout << "----- " << y - x << " holes added------" << std::endl << std::endl; + + std::cout << std::setw(2) << y - x << ", "; + if (! ((i + 1) % 4)) std::cout << " "; + if (! ((i + 1) % 16)) std::cout << std::endl; + if (! ((i + 1) % 64)) std::cout << std::endl; + } +} Index: trunk/milena/sandbox/garrigues/fllt/test_fllt2.cc =================================================================== --- trunk/milena/sandbox/garrigues/fllt/test_fllt2.cc (revision 1869) +++ trunk/milena/sandbox/garrigues/fllt/test_fllt2.cc (revision 1870) @@ -1,4 +1,4 @@ -# include "fllt_optimized.hh" +# include "fllt.hh" # include <mln/core/image2d.hh> # include <mln/core/clone.hh> # include <mln/value/int_u8.hh> @@ -29,5 +29,5 @@ image2d<int> ima = convert::to_image(w_win); fllt_tree(point2d, int) t = fllt::fllt(ima); - fllt::debug(ima, t); + fllt::draw_tree(ima, t); }