
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-02-05 Fabien Freling <freling@lrde.epita.fr> Compile fastest versions of labeling. * fabien/labeling.hh: Compile fastest versions. * fabien/regional_maxima.cc: Simple test file. * fabien/regional_maxima.hh: Functor in fastest implementation. --- labeling.hh | 293 ++++++++++++++++++++++++++--------------------------- regional_maxima.cc | 53 +++++++++ regional_maxima.hh | 8 - 3 files changed, 204 insertions(+), 150 deletions(-) Index: trunk/milena/sandbox/fabien/regional_maxima.cc =================================================================== --- trunk/milena/sandbox/fabien/regional_maxima.cc (revision 0) +++ trunk/milena/sandbox/fabien/regional_maxima.cc (revision 3291) @@ -0,0 +1,53 @@ +// Copyright (C) 2007, 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 +// 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. + +/*! \file tests/labeling/regional_maxima.cc + * + * \brief Test on mln::labeling::regional_maxima. + */ + +#include <mln/core/image/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/core/alias/neighb2d.hh> +#include <mln/io/pgm/load.hh> + +#include "regional_maxima.hh" + +#include <tests/data.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/tiny.pgm"); + + unsigned n; + labeling::regional_maxima(lena, c4(), n); + mln_assertion(n == 25); +} Index: trunk/milena/sandbox/fabien/regional_maxima.hh =================================================================== --- trunk/milena/sandbox/fabien/regional_maxima.hh (revision 3290) +++ trunk/milena/sandbox/fabien/regional_maxima.hh (revision 3291) @@ -35,7 +35,9 @@ # include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> -# include <mln/canvas/labeling.hh> + +# include "labeling.hh" + # include <mln/data/fill.hh> # include <mln/level/sort_psites.hh> @@ -102,7 +104,7 @@ void do_no_union_(unsigned n, unsigned p) { mln_invariant(input.element(n) > input.element(p)); attr.element(p) = false; } - void init_attr_(const P&) {} + void init_attr_(unsigned) {} void merge_attr_(unsigned r, unsigned p) { attr.element(p) = attr.element(p) && attr.element(r); } @@ -110,7 +112,7 @@ mln_ch_value(I, bool) attr; - regional_maxima_functor(const I_& input, const N_& nbh) + regional_maxima_functor(const I& input) : input(input) { initialize(attr, input); Index: trunk/milena/sandbox/fabien/labeling.hh =================================================================== --- trunk/milena/sandbox/fabien/labeling.hh (revision 3290) +++ trunk/milena/sandbox/fabien/labeling.hh (revision 3291) @@ -223,105 +223,104 @@ if (parent.element(x) == x) return x; else - return parent.element(x) = find_root(parent, parent.element(x)); + return parent.element(x) = find_root_fastest(parent, parent.element(x)); } -// // FIXME: Use the same functer for the generic and the fastest versions -// template <typename I, typename N, typename L, -// typename F> -// mln_ch_value(I, L) -// labeling_fastest_video(const Image<I>& input_, const Neighborhood<N>& nbh_, -// F& f, L& nlabels) -// { -// trace::entering("canvas::impl::labeling"); - -// // FIXME: Test?! - -// const I& input = exact(input_); -// const N& nbh = exact(nbh_); - -// // Local type. -// typedef mln_psite(I) P; - -// // Auxiliary data. -// mln_ch_value(I, bool) deja_vu; -// mln_ch_value(I, P) parent; - -// // Output. -// mln_ch_value(I, L) output; -// bool status; - -// // Initialization. -// { -// initialize(deja_vu, input); -// mln::data::fill(deja_vu, false); - -// initialize(parent, input); - -// initialize(output, input); -// mln::data::fill(output, L(literal::zero)); -// nlabels = 0; - -// f.init(); // Client initialization. -// } - -// // First Pass. -// { -// mln_pixter(const S) p(f.s); -// mln_nixter(const S, N) n(p, nbh); -// for_all(p) if (f.handles(p)) -// { -// // Make-Set. -// parent.element(p) = p; -// f.init_attr(p); - -// for_all(n) -// if (input.has(n) && deja_vu(n)) -// { -// if (f.equiv(n, p)) -// { -// // Do-Union. -// unsigned r = find_root_fastest(parent, n); -// if (r != p) -// { -// parent.element(r) = p; -// f.merge_attr(r, p); -// } -// } -// else -// f.do_no_union(n, p); -// (p) = true; -// } -// } -// } - -// // Second Pass. -// { -// mln_bkd_pixter(S) p(f.s); -// for_all(p) if (f.handles(p)) -// { -// if (parent.element(p) == p) // if p is root -// { -// if (f.labels(p)) -// { -// if (nlabels == mln_max(L)) -// { -// status = false; -// return output; -// } -// output.element(p) = ++nlabels; -// } -// } -// else -// output.element(p) = output(parent.element(p)); -// } -// status = true; -// } - -// trace::exiting("canvas::impl::labeling"); -// return output; -// } + template <typename I, typename N, typename L, + typename F> + mln_ch_value(I, L) + labeling_video_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_, + F& f, L& nlabels) + { + trace::entering("canvas::impl::labeling"); + + // FIXME: Test?! + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + // Local type. + typedef mln_psite(I) P; + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, P) parent; + + // Output. + mln_ch_value(I, L) output; + bool status; + + // Initialization. + { + initialize(deja_vu, input); + mln::data::fill(deja_vu, false); + + initialize(parent, input); + + initialize(output, input); + mln::data::fill(output, L(literal::zero)); + nlabels = 0; + + f.init_(); // Client initialization. + } + + // First Pass. + { + mln_pixter(const I) p(input); + mln_nixter(const I, N) n(p, nbh); + for_all(p) if (f.handles_(p)) + { + // Make-Set. + parent.element(p) = p; + f.init_attr(p); + + for_all(n) + if (input.has(n) && deja_vu(n)) + { + if (f.equiv_(n, p)) + { + // Do-Union. + unsigned r = find_root_fastest(parent, n); + if (r != p) + { + parent.element(r) = p; + f.merge_attr_(r, p); + } + } + else + f.do_no_union_(n, p); + (p) = true; + } + } + } + + // Second Pass. + { + mln_bkd_pixter(I) p(input); + for_all(p) if (f.handles_(p)) + { + if (parent.element(p) == p) // if p is root + { + if (f.labels_(p)) + { + if (nlabels == mln_max(L)) + { + status = false; + return output; + } + output.element(p) = ++nlabels; + } + } + else + output.element(p) = output(parent.element(p)); + } + status = true; + } + + trace::exiting("canvas::impl::labeling"); + return output; + } @@ -345,7 +344,7 @@ // Auxiliary data. mln_ch_value(I, bool) deja_vu; - mln_ch_value(I, P) parent; + mln_ch_value(I, unsigned) parent; // Output. mln_ch_value(I, L) output; @@ -362,13 +361,13 @@ mln::data::fill(output, L(literal::zero)); nlabels = 0; - f.init(); // Client initialization. + f.init_(); // Client initialization. } - util::array<int> dp = offsers_wrt(input, nbh); + util::array<int> dp = offsets_wrt(input, nbh); const unsigned n_nbhs = dp.nelements(); - const unsigned n_points = s.elements(); + const unsigned n_points = s.nelements(); // First Pass. { @@ -376,31 +375,31 @@ for (unsigned i = 0; i < n_points; ++i) { unsigned p = s[i]; - if (!f.handles(p)) + if (!f.handles_(p)) continue; // Make-Set. parent.element(p) = p; - f.init_attr(p); + f.init_attr_(p); for (unsigned j = 0; j < n_nbhs; ++j) { unsigned n = p + dp[j]; - if (!deja_vu[n]) + if (!deja_vu.element(n)) continue; - if (f.equiv(n, p)) + if (f.equiv_(n, p)) { // Do-Union. unsigned r = find_root_fastest(parent, n); if (input.element(r) != input.element(p)) { parent.element(r) = p; - f.merge_attr(r, p); + f.merge_attr_(r, p); } } else - f.do_no_union(n, p); + f.do_no_union_(n, p); } deja_vu.element(p) = true; @@ -412,12 +411,12 @@ for (int i = n_points - 1; i >=0; --i) { unsigned p = s[i]; - if (!f.handles(p)) + if (!f.handles_(p)) continue; if (parent.element(p) == p) // if p is root { - if (f.labels(p)) + if (f.labels_(p)) { if (nlabels == mln_max(L)) { @@ -428,7 +427,7 @@ } } else - output.element(p) = output(parent.element(p)); + output.element(p) = output.element(parent.element(p)); } status = true; } @@ -446,45 +445,45 @@ namespace internal { -// // Video + // Video -// template <typename I, typename N, typename L, -// typename F> -// inline -// mln_ch_value(I, L) -// labeling_video(metal::false_, const Image<I>& input, -// const Neighborhood<N>& nbh, L& nlabels, F& functor) -// { -// return impl::generic::labeling(input, nbh, input.domain(), -// nlabels, functor); -// } - -// template <typename I, typename N, typename L, -// typename F> -// inline -// mln_ch_value(I, L) -// labeling_video(metal::true_, const Image<I>& input, -// const Neighborhood<N>& nbh, L& nlabels, F& functor) -// { -// return impl::labeling_fastest_video(input, nbh, nlabels, functor); -// } - -// template <typename I, typename N, typename L, -// typename F> -// inline -// mln_ch_value(I, L) -// labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, -// L& nlabels, F& functor) -// { -// enum { -// test = mlc_equal(mln_trait_image_speed(I), -// trait::image::speed::fastest)::value -// && -// mln_is_simple_neighborhood(N)::value -// }; -// return impl::generic::labeling_video(metal::bool_<test>(), input, -// nbh, nlabels, functor); -// } + template <typename I, typename N, typename L, + typename F> + inline + mln_ch_value(I, L) + labeling_video(metal::false_, const Image<I>& input, + const Neighborhood<N>& nbh, L& nlabels, F& functor) + { + return impl::generic::labeling(input, nbh, input.domain(), + nlabels, functor); + } + + template <typename I, typename N, typename L, + typename F> + inline + mln_ch_value(I, L) + labeling_video(metal::true_, const Image<I>& input, + const Neighborhood<N>& nbh, L& nlabels, F& functor) + { + return impl::labeling_video_fastest(input, nbh, nlabels, functor); + } + + template <typename I, typename N, typename L, + typename F> + inline + mln_ch_value(I, L) + labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, + L& nlabels, F& functor) + { + enum { + test = mlc_equal(mln_trait_image_speed(I), + trait::image::speed::fastest)::value + && + mln_is_simple_neighborhood(N)::value + }; + return impl::generic::labeling(metal::bool_<test>(), input, + nbh, nlabels, functor); + } // Sorted dispatch.