
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Fetch Ugo's code to prepare merging it with 1st steps. * jardonnet/n_cmpt/n_cmpt5.hh: Fix typo. Copy to... * geraud/tufa_2008/n_cmpt.cc: ...this new file. Cleanup code. Fix typos. (main): New. geraud/tufa_2008/n_cmpt.cc | 190 ++++++++++++++++++++++++-------------------- jardonnet/n_cmpt/n_cmpt5.hh | 2 2 files changed, 105 insertions(+), 87 deletions(-) Index: jardonnet/n_cmpt/n_cmpt5.hh --- jardonnet/n_cmpt/n_cmpt5.hh (revision 3044) +++ jardonnet/n_cmpt/n_cmpt5.hh (working copy) @@ -96,7 +96,7 @@ // number of minima unsigned cmpts = label; if (lambda > cmpts) - std::cout << "warning : lambda value is to hight." << std::endl; + std::cout << "Warning: lambda value is too high!" << std::endl; std::cout << cmpts << std::endl; Index: geraud/tufa_2008/n_cmpt.cc --- geraud/tufa_2008/n_cmpt.cc (revision 3043) +++ geraud/tufa_2008/n_cmpt.cc (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2008 EPITA Research and Development Laboratory +// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -25,78 +25,68 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_N_CMPT3_HH -# define MLN_N_CMPT3_HH - -# include <mln/labeling/regional_minima.hh> +#include <mln/core/image/image2d.hh> # include <mln/core/alias/neighb2d.hh> -# include <mln/util/set.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/int_u16.hh> +#include <mln/io/pgm/load.hh> # include <mln/debug/println.hh> # include <mln/debug/iota.hh> -# include <mln/accu/volume.hh> +#include <mln/labeling/regional_minima.hh> +#include <mln/level/fill.hh> + # include <mln/morpho/tree/data.hh> # include <mln/morpho/tree/compute_attribute_image.hh> -namespace mln -{ - - namespace n_cmpt - { +#include <mln/accu/volume.hh> +#include <mln/accu/count.hh> - template < typename I > - void n_cmpt5(const I& (((((((ima)))))))); -# ifndef MLN_INCLUDE_ONLY +namespace mln +{ template <typename I> inline - mln_psite(I) - find_root(I& parent, - const mln_psite(I)& x) + mln_psite(I) find_root__(I& parent, const mln_psite(I)& x) { if (parent(x) == x) return x; else - return parent(x) = find_root(parent, parent(x)); + return parent(x) = find_root__(parent, parent(x)); } - template < typename I, typename N> - I - n_cmpt3(const I& ima, const N& nbh, - unsigned lambda) - { - std::cout << "/ima/" << std::endl; - debug::println(ima); - // compute volume image - //--------------------- + template <typename A, typename I, typename N> + mln_concrete(I) + n_cmpt(A a, const I& f, const N& nbh, unsigned lambda) + { + // Compute attribute image. + //------------------------- typedef p_array<mln_psite(I)> S; - typedef mln_ch_value(I,unsigned) V; - typedef accu::volume<I> A; + typedef mln_ch_value(I, mln_result(A)) Attr; - S sp = level::sort_psites_decreasing(ima); - morpho::tree::data<I,S> t(ima, sp, nbh); - V volume = morpho::tree::compute_attribute_image(A(), t); - sp = level::sort_psites_increasing(volume); - std::cout << "/volume/" << std::endl; - debug::println(volume); + S s = level::sort_psites_decreasing(f); + morpho::tree::data<I,S> t(f, s, nbh); + Attr attr = morpho::tree::compute_attribute_image(a, t); + s = level::sort_psites_increasing(attr); + debug::println("attr =", attr); - // get /volume/ regional minima - //----------------------------- + // Compute regional minima of attribute image. + //-------------------------------------------- unsigned label; - mln_ch_value(I, unsigned) min_v = labeling::regional_minima(volume, nbh, label); - std::cout << "/volume/ regional minima" << std::endl; - debug::println(min_v); + mln_ch_value(I, unsigned) min_v = labeling::regional_minima(attr, nbh, label); + debug::println("regmin =", min_v); // number of minima unsigned cmpts = label; if (lambda > cmpts) - std::cout << "warning : lambda value is to hight." << std::endl; + std::cout << "Warning: lambda value is too high!" << std::endl; std::cout << cmpts << std::endl; @@ -106,23 +96,21 @@ // init fused image mln_ch_value(I, bool) fused; - initialize(fused, volume); + initialize(fused, attr); mln::level::fill(fused, false); // prepare union find - typedef mln_psite(V) P; - - //data - mln_ch_value(V, accu::volume<V>) data(volume.domain()); + typedef mln_psite(I) P; //deja_vu - mln_ch_value(V, bool) deja_vu(volume.domain()); - mln::level::fill(deja_vu, false); + mln_ch_value(I, bool) deja_vu; + initialize(deja_vu, f); + level::fill(deja_vu, false); //parent - mln_ch_value(V, P) parent(volume.domain()); + mln_ch_value(I, P) parent(attr.domain()); { - mln_fwd_piter(S) p(sp); + mln_fwd_piter(S) p(s); for_all(p) { parent(p) = p; @@ -133,32 +121,30 @@ } } - // UNION FIND ON VOLUME - mln_fwd_piter(S) p(sp); + // UNION FIND ON ATTR + mln_fwd_piter(S) p(s); mln_niter(N) n(nbh, p); for_all(p) { - std::cout << p << std::endl; - //if (volume(p) > lambda) - // goto step2; + // std::cout << p << std::endl; for_all(n) { - if (volume.domain().has(n) && deja_vu(n)) + if (attr.domain().has(n) && deja_vu(n)) { - //do_union(n, p); - P r = find_root(parent, n); + P r = find_root__(parent, n); if (r != p) { - std::cout << "neighb: " << n << std::endl; - std::cout << "v(r): " << volume(r) << " v(p): " << volume(p) << " f(p): " << fused(p) << std::endl; + // std::cout << "neighb: " << n << std::endl; + // std::cout << "v(r): " << attr(r) << " v(p): " + // << attr(p) << " f(p): " << fused(p) << std::endl; - //if (volume(r) != volume(p)) // r and p have different volumes + //if (attr(r) != attr(p)) // r and p have different attrs // This check was wrong. // you just fused with a minima. - // then you fuse with a neighbor already fused that has the same volume as you + // then you fuse with a neighbor already fused that has the same attr as you // a) 1 50 1 // 2 2 2 - // we don't have ( volume(r) == volume(p) ) => not fused(r) + // we don't have ( attr(r) == attr(p) ) => not fused(r) // even if r and p are not minima // problem : @@ -166,39 +152,44 @@ // - when fusing cmpts (a) : same level, both fused. DEC // One cmpt less if - if (fused(r) && min_v(p) == 0) // p is not a minima - if (fused(p)) // p already belong to a cmpt (fused for an another n) - if (cmpts >= lambda) // union is still allowed + +// if (fused(r) && min_v(p) == 0) // p is not a minima +// if (fused(p)) // p already belong to a cmpt (fused for an another n) +// if (cmpts >= lambda) // union is still allowed + + if (fused(r) && min_v(p) == 0 // p is not a minima + && fused(p) // p already belong to a cmpt (fused for an another n) + && cmpts >= lambda) // union is still allowed { - cmpts--; - std::cout << "dec" << std::endl; + --cmpts; + // std::cout << "dec" << std::endl; } - mln_invariant(fused(r) || volume(r) == volume(p)); + mln_invariant(fused(r) || attr(r) == attr(p)); // Union made if if (cmpts >= lambda || // union is still allowed or - not fused(r) || // r not fused or - not fused(p) || // p not fused or + ! fused(r) || // r not fused or + ! fused(p) || // p not fused or min_v(p) != 0) // p is a minima { - std::cout << "fuse" << p << n << std::endl; + // std::cout << "fusing " << p << " with " << n << std::endl; parent(r) = p; // This test is mandatory. Sometimes (--_) points are fused - // tought none of these points belongs to a component (attached + // tough none of these points belongs to a component (attached // to a local minima). In this case fused(p) must not be true // since it can be fused again without removing a component. - // looking if r is fused should be enought. + // looking if r is fused should be enough. // This test force minima to be initialized fused. if (fused(r)) fused(p) = true; // If I try to fuse with something never fused I am on a plateau. - // not fused(r) => ( volume(r) == volume(p) ) - mln_invariant(fused(r) || volume(r) == volume(p)); - // fused(r) and ( volume(r) == volume(p) ) happen on minima plateau. + // not fused(r) => ( attr(r) == attr(p) ) + mln_invariant(fused(r) || attr(r) == attr(p)); + // fused(r) and ( attr(r) == attr(p) ) happen on minima plateau. // fused(n) = true; // useless ? probably yes because when we // want to know that we really fuse component, we look at @@ -206,7 +197,8 @@ // fused(n) is not an invariant: --_. And it is ok (I think). // We don't have to retro-propagate fused. - std::cerr << "volume " << volume(p) << " - " << cmpts << std::endl; + + // std::cout << "attr " << attr(p) << " - " << cmpts << std::endl; //debug::println(fused); } } @@ -215,16 +207,17 @@ deja_vu(p) = true; } - mln_ch_value(I,value::int_u<16>) iota(ima.domain()); + mln_ch_value(I,value::int_u<16>) iota(f.domain()); debug::iota(iota); std::cout << std::endl; std::cout << "cmpts : " << cmpts << std::endl; // second pass - I output(ima.domain()); + mln_concrete(I) output; + initialize(output, f); { - mln_bkd_piter(S) p(sp); + mln_bkd_piter(S) p(s); for_all(p) if (parent(p) == p) // p is root. output(p) = iota(p); @@ -235,11 +228,36 @@ return output; } - } // end of namespace n_cmpt +} // end of namespace mln -# endif // ! MLN_INCLUDE_ONLY -} // end of namespace mln -#endif /* MLN_N_CMPT3_HH */ +void usage(char* argv[]) +{ + std::cerr << "usage: " << argv[0] << " input.pgm n" << std::endl; + std::cerr << "n: expected number of basins" << std::endl; + std::abort(); +} + + +int main(int argc, char* argv[]) +{ + using namespace mln; + using value::int_u8; + + if (argc != 3) + usage(argv); + typedef image2d<int_u8> I; + I f; + io::pgm::load(f, argv[1]); + debug::println("f =", f); + + unsigned n = std::atoi(argv[2]); + + accu::count< util::pix<I> > acc; + // accu::volume<I> acc; + + image2d<int_u8> g = n_cmpt(acc, f, c4(), n + 1); + debug::println(g); +}