URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-10-03 Guillaume Duhamel <guillaume.duhamel@lrde.epita.fr> Add labeling_fast in mln. * canvas/labeling.hh: New canvas for labeling fast. * convert/to_window.hh: New function to_upper_window. * labeling/level.hh: Add level_fast. --- canvas/labeling.hh | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++- convert/to_window.hh | 20 ++++++++- labeling/level.hh | 47 ++++++++++++++++++++++ 3 files changed, 171 insertions(+), 3 deletions(-) Index: trunk/milena/mln/convert/to_window.hh =================================================================== --- trunk/milena/mln/convert/to_window.hh (revision 1233) +++ trunk/milena/mln/convert/to_window.hh (revision 1234) @@ -53,6 +53,10 @@ template <typename N> window<mln_dpoint(N)> to_window(const Neighborhood<N>& nbh); + /// Convert a neighborhood \p nbh into an upper window. + template <typename N> + window<mln_dpoint(N)> to_upper_window(const Neighborhood<N>& nbh); + /// Convert a binary image \p ima into a window. template <typename I> window<mln_dpoint(I)> to_window(const Image<I>& ima); @@ -77,8 +81,20 @@ window<D> win; mln_niter(N) n(nbh, P::zero); for_all(n) -// FIXME: pour Guillaume -// if (n < P::zero) + win.insert(n - P::zero); + return win; + } + + template <typename N> + window<mln_dpoint(N)> to_upper_window(const Neighborhood<N>& nbh_) + { + const N& nbh = exact(nbh_); + typedef mln_dpoint(N) D; + typedef mln_point(D) P; + window<D> win; + mln_niter(N) n(nbh, P::zero); + for_all(n) + if (n > P::zero) win.insert(n - P::zero); return win; } Index: trunk/milena/mln/canvas/labeling.hh =================================================================== --- trunk/milena/mln/canvas/labeling.hh (revision 1233) +++ trunk/milena/mln/canvas/labeling.hh (revision 1234) @@ -36,7 +36,7 @@ # include <mln/level/fill.hh> # include <mln/level/sort_points.hh> - +# include <mln/convert/to_window.hh> namespace mln { @@ -154,6 +154,111 @@ // FIXME: Fast version. + template <typename F> + struct labeling_fast + { + F& f; + + typedef typename F::I I; + typedef typename F::N N; + typedef typename F::O O; + + // aux: + mln_ch_value(O, unsigned) parent; + + labeling_fast(F& f) + : f(f), + parent(f.output.domain(), f.input.border()) + { + run(); + } + + void run() + { + + // init + { + f.nlabels = 0; + f.init(); + } + + // first pass + { + mln_bkd_pixter(const I) p(f.input); + // mln_nixter(const I, N) n(p, f.nbh); + + typedef window<mln_dpoint(I)> W; + W win = mln::convert::to_upper_window(f.nbh); + mln_qixter(const I, W) n(p, win); + + for_all(p) if (f.handles(p)) + { + make_set(p); + for_all(n) + if (f.equiv(n, p)) + do_union(n, p); + else + f.do_no_union(n, p); + } + } + + // second pass + { + mln_fwd_pixter(const I) p(f.input); + for_all(p) if (f.handles(p)) + { + if (is_root(p)) + { + if (f.labels(p)) + { + if (f.nlabels == mln_max(mln_value(O))) + { + f.status = false; + return; + } + f.output[p] = ++f.nlabels; + } + } + else + f.output[p] = f.output[parent[p]]; + } + f.status = true; + } + + } // end of run() + + void make_set(unsigned p) + { + parent[p] = p; + f.init_attr(p); + } + + bool is_root(unsigned p) const + { + return parent[p] == p; + } + + unsigned find_root(unsigned x) + { + if (parent[x] == x) + return x; + else + return parent[x] = find_root(parent[x]); + } + + void do_union(unsigned n, unsigned p) + { + unsigned r = find_root(n); + if (r != p) + { + parent[r] = p; + f.merge_attr(r, p); + } + } + + }; + + } // end of namespace mln::canvas } // end of namespace mln Index: trunk/milena/mln/labeling/level.hh =================================================================== --- trunk/milena/mln/labeling/level.hh (revision 1233) +++ trunk/milena/mln/labeling/level.hh (revision 1234) @@ -34,10 +34,12 @@ * level. */ +# include <mln/core/concept/fast_image.hh> # include <mln/labeling/base.hh> # include <mln/level/fill.hh> + namespace mln { @@ -59,6 +61,9 @@ bool level(const Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, Image<O>& output, unsigned& nlabels); + template <typename I, typename N, typename O> + bool level_fast(const Fast_Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, + Fast_Image<O>& output, unsigned& nlabels); # ifndef MLN_INCLUDE_ONLY @@ -108,6 +113,40 @@ // FIXME: Add fast versions. + template <typename I_, typename N_, typename O_> + struct level_fast_t : labeling::impl::base_fast_<I_,N_,O_> + { + typedef mln_point(I_) P; + + // typedef mln_pset(I_) S; + // const S& s; + + void init() { level::fill(this->output, 0); } + bool handles(unsigned p) const { return this->input[p] == val; } + bool equiv(unsigned n, unsigned) const { return this->input[n] == val; } + + const mln_value(I_)& val; + + level_fast_t(const I_& input, const mln_value(I_)& val, const N_& nbh, O_& output) + : labeling::impl::base_fast_<I_,N_,O_>(input, nbh, output), + // s(input.domain()), + val(val) + {} + }; + + + template <typename I, typename N, typename O> + bool level_fast_(const Fast_Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, + Fast_Image<O>& output, unsigned& nlabels) + { + typedef level_fast_t<I,N,O> F; + F f(exact(input), val, exact(nbh), exact(output)); + canvas::labeling_fast<F> run(f); + nlabels = f.nlabels; + return f.status; + } + + } // end of namespace mln::labeling::impl @@ -121,6 +160,14 @@ return impl::level_(exact(input), val, nbh, output, nlabels); } + template <typename I, typename N, typename O> + bool level_fast(const Fast_Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, + Fast_Image<O>& output, unsigned& nlabels) + { + mln_precondition(exact(output).domain() == exact(input).domain()); + return impl::level_fast_(exact(input), val, nbh, output, nlabels); + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::labeling