
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Clean up 'labeling' and fix pbm i/o. * doc/examples: New directory. * tests/labeling_blobs.cc: Rename as... * tests/labeling/blobs.cc: ...this. * tests/labeling_algo.cc: Rename as... * doc/examples/labeling_algo.cc: ...this. * tests/labeling_level_fast.cc: Rename as... * tests/labeling/level.cc: ...this. * tests/labeling_regional_maxima.cc: Rename as... * tests/labeling/regional_maxima.cc: ...this. * tests/labeling_foreground.cc: Rename as... * tests/labeling/foreground.cc: ...this. * tests/labeling_estimate.cc: Remove; meaningless. * mln/labeling/estimate.hh: Rename as... * sandbox/geraud/estimate.hh: ...this. * tests/labeling/background.cc: New. * tests/labeling/flat_zones.cc: New. * tests/labeling/regional_minima.cc: New. * tests/labeling/Makefile.am: Update. * mln/canvas/labeling.hh, * mln/labeling/blobs.hh, * mln/labeling/flat_zones.hh, * mln/labeling/level.hh, * mln/labeling/regional_minima.hh, * mln/labeling/foreground.hh, * mln/labeling/regional_maxima.hh, * mln/labeling/background.hh: Clean up. * mln/labeling/all.hh: Update. * mln/labeling/base.hh: Remove. * mln/labeling/level.spe.hh: New. * tests/value/rgb8.cc: Add comment. * mln/trait/value/kind.hh: Add comment about tags' hierarchy. * mln/core/internal/set_of.hh (element): Fix precondition. * mln/value/rgb.hh (operator metal::vec): New; experimental. * mln/fun/v2v/saturate.hh: Uncomment. * mln/io/pbm/save.hh (save_), * mln/io/pbm/load.hh (load_ascii, load_raw_2d): Swap 0 and 1. * img/tiny.pgm: Rename as... * img/small.pgm: ...this. * img/tiny.pgm: New 16x16 lena reduction. * img/README: New. img/README | 8 + mln/canvas/labeling.hh | 116 +++++++++++++++---------- mln/core/internal/set_of.hh | 2 mln/fun/v2v/saturate.hh | 2 mln/io/pbm/load.hh | 5 - mln/io/pbm/save.hh | 2 mln/labeling/all.hh | 2 mln/labeling/background.hh | 19 +++- mln/labeling/blobs.hh | 54 ++++++++--- mln/labeling/flat_zones.hh | 103 +++++++++++++++------- mln/labeling/foreground.hh | 15 +++ mln/labeling/level.hh | 145 ++++++++++++------------------- mln/labeling/level.spe.hh | 175 ++++++++++++++++++++++++++++++++++++++ mln/labeling/regional_maxima.hh | 103 +++++++++++++++------- mln/labeling/regional_minima.hh | 105 +++++++++++++++------- mln/trait/value/kind.hh | 7 + mln/value/rgb.hh | 2 sandbox/geraud/estimate.hh | 39 +++++--- tests/labeling/Makefile.am | 19 ++++ tests/labeling/background.cc | 48 ++++++++++ tests/labeling/blobs.cc | 40 +------- tests/labeling/flat_zones.cc | 65 ++++++++++++++ tests/labeling/foreground.cc | 36 +------ tests/labeling/level.cc | 34 +++---- tests/labeling/regional_maxima.cc | 17 +-- tests/labeling/regional_minima.cc | 52 +++++++++++ tests/value/rgb8.cc | 5 + 27 files changed, 861 insertions(+), 359 deletions(-) Index: tests/value/rgb8.cc --- tests/value/rgb8.cc (revision 1598) +++ tests/value/rgb8.cc (working copy) @@ -50,6 +50,11 @@ v.blue() = 2; rgb8 c(0, 1, 2); + // FIXME: Do not compile because we lack ops! + // mln_sum_(rgb8) sum; + // sum + c; + // c = c + c; + std::cout << c << std::endl; std::cout << v << std::endl; Index: tests/labeling/regional_maxima.cc --- tests/labeling/regional_maxima.cc (revision 1528) +++ tests/labeling/regional_maxima.cc (working copy) @@ -25,18 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/labeling_regional_maxima.cc +/*! \file tests/labeling/regional_maxima.cc * * \brief Test on mln::labeling::regional_maxima. */ #include <mln/core/image2d.hh> -#include <mln/core/neighb2d.hh> #include <mln/value/int_u8.hh> - +#include <mln/core/neighb2d.hh> #include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> - #include <mln/labeling/regional_maxima.hh> @@ -45,13 +42,9 @@ using namespace mln; using value::int_u8; - image2d<int_u8> - lena = io::pgm::load("../img/lena.pgm"), - out(lena.domain()); + image2d<int_u8> lena = io::pgm::load<int_u8>("../../img/tiny.pgm"); unsigned n; - labeling::regional_maxima(lena, c4(), out, n); - mln_assertion(n = 255); - - io::pgm::save(out, "out.pgm"); + labeling::regional_maxima(lena, c4(), n); + mln_assertion(n = 25); } Index: tests/labeling/background.cc --- tests/labeling/background.cc (revision 0) +++ tests/labeling/background.cc (revision 0) @@ -0,0 +1,48 @@ +// Copyright (C) 2007 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. + +/*! \file tests/labeling/background.cc + * + * \brief Test on mln::labeling::background. + */ + +#include <mln/core/image2d.hh> +#include <mln/io/pbm/load.hh> +#include <mln/core/neighb2d.hh> +#include <mln/labeling/background.hh> +#include <mln/logical/not.hh> + + +int main() +{ + using namespace mln; + + image2d<bool> pic = io::pbm::load("../../img/picasso.pbm"); + unsigned n; + labeling::background(logical::not_(pic), c4(), n); + mln_assertion(n = 33); +} Index: tests/labeling/blobs.cc --- tests/labeling/blobs.cc (revision 1528) +++ tests/labeling/blobs.cc (working copy) @@ -25,51 +25,23 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/labeling_blob.cc +/*! \file tests/labeling/blobs.cc * - * \brief Test on mln::labeling::blob. + * \brief Test on mln::labeling::blobs. */ #include <mln/core/image2d.hh> -#include <mln/core/cast_image.hh> +#include <mln/io/pbm/load.hh> #include <mln/core/neighb2d.hh> -#include <mln/value/int_u8.hh> -#include <mln/pw/all.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> #include <mln/labeling/blobs.hh> -#include <mln/level/transform.hh> - - -struct fold_t : public mln::Function_v2v< fold_t > -{ - typedef mln::value::int_u8 result; - result operator()(unsigned i) const { return i = 0 ? 0 : i % 255 + 1; } -}; - int main() { using namespace mln; - using value::int_u8; - - image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm"); + image2d<bool> pic = io::pbm::load("../../img/picasso.pbm"); unsigned n; - io::pgm::save(cast_image<int_u8>( labeling::blobs((pw::value(lena) > pw::cst(127u)) | lena.domain(), - c4(), n) ), - "out.pgm"); - mln_assertion(n = 14); - -// image2d<int_u8> -// lena = io::pgm::load("../img/lena.pgm"), -// out; -// unsigned n; -// image2d<unsigned> labels = labeling::blobs((pw::value(lena) > pw::cst(127u)) | lena.domain(), -// c8(), n); -// mln_assertion(n = 528); -// io::pgm::save( level::transform(labels, fold_t()), -// "out.pgm" ); + labeling::blobs(pic, c4(), n); + mln_assertion(n = 33); } Index: tests/labeling/flat_zones.cc --- tests/labeling/flat_zones.cc (revision 0) +++ tests/labeling/flat_zones.cc (revision 0) @@ -0,0 +1,65 @@ +// Copyright (C) 2007 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. + +/*! \file tests/labeling/flat_zones.cc + * + * \brief Test on mln::labeling::flat_zones. + */ + +#include <mln/core/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/io/pgm/load.hh> +#include <mln/core/neighb2d.hh> +#include <mln/labeling/flat_zones.hh> + +#include <mln/labeling/blobs.hh> +#include <mln/pw/all.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> lena = io::pgm::load<int_u8>("../../img/tiny.pgm"); + + unsigned n; + image2d<unsigned> labels = labeling::flat_zones(lena, c4(), n); + mln_assertion(n = 247); + + { + unsigned n_ = 0; + for (unsigned i = 0; i <= 255; ++i) + { + unsigned n_i; + labeling::blobs((pw::value(lena) = pw::cst(i)) | lena.domain(), + c4(), n_i); + n_ += n_i; + } + mln_assertion(n_ = n); + } +} Index: tests/labeling/Makefile.am --- tests/labeling/Makefile.am (revision 1598) +++ tests/labeling/Makefile.am (working copy) @@ -1,3 +1,22 @@ ## Process this file through Automake to create Makefile.in -*- Makefile -*- include $(top_srcdir)/milena/tests/tests.mk + +check_PROGRAMS = \ + background \ + blobs \ + flat_zones \ + foreground \ + level \ + regional_maxima \ + regional_minima + +background_SOURCES = background.cc +blobs_SOURCES = blobs.cc +flat_zones_SOURCES = flat_zones.cc +foreground_SOURCES = foreground.cc +level_SOURCES = level.cc +regional_maxima_SOURCES = regional_maxima.cc +regional_minima_SOURCES = regional_minima.cc + +TESTS = $(check_PROGRAMS) Index: tests/labeling/level.cc --- tests/labeling/level.cc (revision 1528) +++ tests/labeling/level.cc (working copy) @@ -25,21 +25,23 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/labeling_level_fast.cc +/*! \file tests/labeling/level.cc * * \brief Test on mln::labeling::level. */ #include <mln/core/image2d.hh> -#include <mln/core/image1d.hh> #include <mln/core/neighb2d.hh> #include <mln/value/int_u8.hh> -#include <mln/pw/all.hh> - #include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> + +#include <mln/accu/count.hh> +#include <mln/accu/compute.hh> #include <mln/labeling/level.hh> -#include <mln/debug/iota.hh> +#include <mln/level/paste.hh> +#include <mln/pw/all.hh> +#include <mln/core/image_if.hh> + #include <mln/debug/println.hh> @@ -48,15 +50,15 @@ using namespace mln; using value::int_u8; - image2d<value::int_u8> i1(5, 5); - debug::iota(i1); - i1(point2d(0, 2)) = i1(point2d(1, 2)) = i1(point2d(1, 3)) = i1(point2d(2, 3)) = i1(point2d(2, 4)) = 2; - i1(point2d(2, 0)) = i1(point2d(3, 0)) = 2; - debug::println(i1); - - unsigned n; - image2d<unsigned> out = labeling::level(i1, 2, c4(), n); + image2d<int_u8> lena = io::pgm::load<int_u8>("../../img/tiny.pgm"); + image2d<bool> lvl(lena.domain()); - std::cout << "n = " << n << std::endl; - debug::println(out); + unsigned n, npixels = 0; + for (unsigned l = 0; l <= 255; ++l) + { + image2d<unsigned> labels = labeling::level(lena, l, c4(), n); + unsigned npix = accu::compute< accu::count >(labels | (pw::value(labels) != pw::cst(0))); + npixels += npix; + } + mln_assertion(npixels = lena.npoints()); } Index: tests/labeling/foreground.cc --- tests/labeling/foreground.cc (revision 1528) +++ tests/labeling/foreground.cc (working copy) @@ -25,49 +25,23 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/labeling_foreground.cc +/*! \file tests/labeling/foreground.cc * * \brief Test on mln::labeling::foreground. */ #include <mln/core/image2d.hh> +#include <mln/io/pbm/load.hh> #include <mln/core/neighb2d.hh> -#include <mln/value/int_u8.hh> -#include <mln/pw/all.hh> -#include <mln/core/cast_image.hh> - -#include <mln/io/pgm/load.hh> -#include <mln/io/pgm/save.hh> #include <mln/labeling/foreground.hh> -#include <mln/level/transform.hh> - - -struct fold_t : public mln::Function_v2v< fold_t > -{ - typedef mln::value::int_u8 result; - result operator()(unsigned i) const { return i = 0 ? 0 : i % 255 + 1; } -}; int main() { using namespace mln; - using value::int_u8; - image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm"); + image2d<bool> pic = io::pbm::load("../../img/picasso.pbm"); unsigned n; - io::pgm::save(cast_image<int_u8>( labeling::foreground((pw::value(lena) > pw::cst(127u)) | lena.domain(), - c4(), n) ), - "out.pgm"); - mln_assertion(n = 14); - -// image2d<int_u8> -// lena = io::pgm::load("../img/lena.pgm"), -// out; -// unsigned n; -// image2d<unsigned> labels = labeling::foreground((pw::value(lena) > pw::cst(127u)) | lena.domain(), -// c8(), n); -// mln_assertion(n = 528); -// io::pgm::save( level::transform(labels, fold_t()), -// "out.pgm" ); + labeling::foreground(pic, c4(), n); + mln_assertion(n = 33); } Index: tests/labeling/regional_minima.cc --- tests/labeling/regional_minima.cc (revision 0) +++ tests/labeling/regional_minima.cc (revision 0) @@ -0,0 +1,52 @@ +// Copyright (C) 2007 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. + +/*! \file tests/labeling/regional_minima.cc + * + * \brief Test on mln::labeling::regional_minima. + */ + +#include <mln/core/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/core/neighb2d.hh> +#include <mln/io/pgm/load.hh> +#include <mln/pw/all.hh> +#include <mln/labeling/regional_minima.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> lena = io::pgm::load<int_u8>("../../img/tiny.pgm"); + + unsigned n; + labeling::regional_minima((pw::cst(255) - pw::value(lena)) | lena.domain(), + c4(), n); + mln_assertion(n = 25); +} Index: mln/trait/value/kind.hh --- mln/trait/value/kind.hh (revision 1598) +++ mln/trait/value/kind.hh (working copy) @@ -56,6 +56,13 @@ struct logic : label { std::string name() const { return "kind::logic"; } }; struct binary : logic { std::string name() const { return "kind::binary"; } }; + // FIXME: Why not? + // label logic + // \ / \ + // \ nary_logic \ + // \ / \ \ + // binary ternary fuzzy + struct data : any { std::string name() const { return "kind::data"; } }; }; Index: mln/core/internal/set_of.hh --- mln/core/internal/set_of.hh (revision 1598) +++ mln/core/internal/set_of.hh (working copy) @@ -224,9 +224,9 @@ const E& set_of_<E>::element(unsigned i) const { - assert(i < v_.size()); if (needs_update_) update_(); + mln_precondition(i < v_.size()); return v_[i]; } Index: mln/value/rgb.hh --- mln/value/rgb.hh (revision 1598) +++ mln/value/rgb.hh (working copy) @@ -125,6 +125,8 @@ rgb<n>(const metal::vec<3, unsigned>& rhs); rgb<n>(const metal::vec<3, int_u<n> >& rhs); + operator metal::vec<3, float>() const { return this->v_; } + /// \{ Constructors with literals. rgb<n>(const literal::white_t&); rgb<n>(const literal::black_t&); Index: mln/fun/v2v/saturate.hh --- mln/fun/v2v/saturate.hh (revision 1598) +++ mln/fun/v2v/saturate.hh (working copy) @@ -102,7 +102,7 @@ min_W = mln::value::cast<W>(min_); max_W = mln::value::cast<W>(max_); // FIXME -// needs_update_ = false; + needs_update_ = false; } // FIXME: Below we need something more powerful that mlc_converts_to Index: mln/io/pbm/save.hh --- mln/io/pbm/save.hh (revision 1598) +++ mln/io/pbm/save.hh (working copy) @@ -95,7 +95,7 @@ for_all(p) { c <<= 1; - c += (ima(p) = true ? 1 : 0); // FIXME: Swap. + c += (ima(p) = true ? 0 : 1); // In pbm, '0' means 'white' so 'object', thus 'true'! if (++col >= ncols) { c <<= (8 - stride - 1); Index: mln/io/pbm/load.hh --- mln/io/pbm/load.hh (revision 1598) +++ mln/io/pbm/load.hh (working copy) @@ -87,7 +87,8 @@ { unsigned value; file >> value; - ima(p) = value; + mln_assertion(value = 0 || value = 1); + ima(p) = (value = 0); // In pbm, '0' means 'white' so 'object', thus 'true'! // FIXME: Test alt code below. // file >> ima(p); } @@ -116,7 +117,7 @@ { if (i % 8 = 0) file.read((char*)(&c), 1); - ima(p) = c & 128; + ima(p) = !(c & 128); c *= 2; ++i; } Index: mln/canvas/labeling.hh --- mln/canvas/labeling.hh (revision 1598) +++ mln/canvas/labeling.hh (working copy) @@ -34,9 +34,9 @@ * image. */ +# include <mln/core/concept/image.hh> # include <mln/level/fill.hh> -# include <mln/level/sort_points.hh> -# include <mln/convert/to_window.hh> +# include <mln/convert/to_window.hh> // FIXME: to_upper_window namespace mln @@ -50,35 +50,52 @@ template <typename F> struct labeling { + // Functor. F& f; typedef typename F::I I; typedef typename F::N N; - typedef typename F::O O; + typedef typename F::L L; typedef typename F::S S; - typedef mln_point(I) point; - // aux: - mln_ch_value(O, bool) deja_vu; - mln_ch_value(O, point) parent; + // Local type. + typedef mln_psite(I) point; + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, point) parent; + + // Output. + mln_ch_value(I, L) output; + L nlabels; + bool status; + + // Ctor. labeling(F& f) : f(f) { - run(); + trace::entering("canvas::labeling"); + + init(); + f.init(); // Client initialization. + pass_1(); + pass_2(); + + trace::exiting("canvas::labeling"); } - void run() - { - // init + + void init() { initialize(deja_vu, f.input); mln::level::fill(deja_vu, false); initialize(parent, f.input); - f.nlabels = 0; - f.init(); + initialize(output, f.input); + mln::level::fill(output, 0); // FIXME: Use literal::zero. + nlabels = 0; } - // first pass + + void pass_1() { mln_fwd_piter(S) p(f.s); mln_niter(N) n(f.nbh, p); @@ -95,7 +112,7 @@ } } - // second pass + void pass_2() { mln_bkd_piter(S) p(f.s); for_all(p) if (f.handles(p)) @@ -104,21 +121,22 @@ { if (f.labels(p)) { - if (f.nlabels = mln_max(mln_value(O))) + if (nlabels = mln_max(L)) { - f.status = false; + status = false; return; } - f.output(p) = ++f.nlabels; + output(p) = ++nlabels; } } else - f.output(p) = f.output(parent(p)); + output(p) = output(parent(p)); } - f.status = true; + status = true; } - } // end of run() + + // Auxiliary methods. void make_set(const point& p) { @@ -152,41 +170,52 @@ }; - // FIXME: Fast version. template <typename F> - struct labeling_fast + struct labeling_fastest { + // Functor. F& f; typedef typename F::I I; typedef typename F::N N; - typedef typename F::O O; + typedef typename F::L L; + + // Auxiliary data. + mln_ch_value(I, unsigned) parent; - // aux: - mln_ch_value(O, unsigned) parent; + // Output. + mln_ch_value(I, L) output; + L nlabels; + bool status; - labeling_fast(F& f) + // Ctor. + labeling_fastest(F& f) : f(f) { - run(); + trace::entering("canvas::labeling_fastest"); + + init(); + f.init(); // Client initialization. + pass_1(); + pass_2(); + + trace::exiting("canvas::labeling_fastest"); } - void run() - { - // init + void init() { initialize(parent, f.input); - f.nlabels = 0; - f.init(); - // make_set for all points: for (unsigned p = 0; p < parent.ncells(); ++p) - parent[p] = p; + parent[p] = p; // make_set + initialize(output, f.input); + mln::level::fill(output, 0); // FIXME: Use literal::zero. + nlabels = 0; } - // first pass + void pass_1() { mln_bkd_pixter(const I) p(f.input); @@ -205,30 +234,31 @@ } } - // second pass + void pass_2() { 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))) + if (nlabels = mln_max(L)) { - f.status = false; + status = false; return; } - f.output[p] = ++f.nlabels; + output[p] = ++nlabels; } } else - f.output[p] = f.output[parent[p]]; + output[p] = output[parent[p]]; } - f.status = true; + status = true; } - } // end of run() + // Auxiliary methods. bool is_root(unsigned p) const { Index: mln/labeling/blobs.hh --- mln/labeling/blobs.hh (revision 1598) +++ mln/labeling/blobs.hh (working copy) @@ -30,8 +30,8 @@ /*! \file mln/labeling/blobs.hh * - * \brief Connected component labeling of the image objects at a given - * blobs. + * \brief Connected component labeling of the binary objects of a binary + * image using a queue-based algorithm. */ # include <mln/core/concept/image.hh> @@ -55,6 +55,8 @@ * \param[out] nlabels The number of labels. * \return The label image. * + * \pre The input image has to be binary (checked at compile-time). + * * A fast queue is used so that the algorithm is not recursive and * can handle large binary objects (blobs). */ @@ -69,22 +71,13 @@ namespace impl { - // ... - - } // end of namespace mln::labeling::impl - - - // Facade. + namespace generic + { template <typename I, typename N> - inline mln_ch_value(I, unsigned) - blobs(const Image<I>& input_, const Neighborhood<N>& nbh_, unsigned& nlabels) + blobs_(const I& input, const N& nbh, unsigned& nlabels) { - const I& input = exact(input_); - const N& nbh = exact(nbh_); - mln_precondition(input.has_data()); - typedef mln_psite(I) P; P cur; @@ -125,6 +118,39 @@ return output; } + } // end of namespace mln::labeling::impl::generic + + + template <typename I, typename N> + mln_ch_value(I, unsigned) + blobs_(const I& input, const N& nbh, unsigned& nlabels) + { + // The only implementation is the generic one. + return generic::blobs_(input, nbh, nlabels); + } + + } // end of namespace mln::labeling::impl + + + // Facade. + + template <typename I, typename N> + inline + mln_ch_value(I, unsigned) + blobs(const Image<I>& input_, const Neighborhood<N>& nbh_, unsigned& nlabels) + { + trace::entering("labeling::blobs"); + mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check(); + const I& input = exact(input_); + const N& nbh = exact(nbh_); + mln_precondition(input.has_data()); + + mln_ch_value(I, unsigned) output = impl::blobs_(input, nbh, nlabels); + + trace::exiting("labeling::blobs"); + return output; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::labeling Index: mln/labeling/flat_zones.hh --- mln/labeling/flat_zones.hh (revision 1598) +++ mln/labeling/flat_zones.hh (working copy) @@ -33,7 +33,9 @@ * \brief Connected component labeling of the flat zones of an image. */ -# include <mln/labeling/base.hh> +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/canvas/labeling.hh> namespace mln @@ -46,15 +48,14 @@ * * \param[in] input The input image. * \param[in] nbh The neighborhood to consider. - * \param[out] output The label image. * \param[out] nlabels The number of labels. - * - * \return The number of labels. + * \return The label image. */ - template <typename I, typename N, typename O> - bool flat_zones(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, - unsigned& nlabels); + template <typename I, typename N, typename L> + mln_ch_value(I, L) + flat_zones(const Image<I>& input, const Neighborhood<N>& nbh, + L& nlabels); + # ifndef MLN_INCLUDE_ONLY @@ -62,47 +63,87 @@ namespace impl { - template <typename I_, typename N_, typename O_> - struct flat_zones_ : base_<I_,N_,O_> + // Flat zone functor for the labeling canvas. + + template <typename I_, typename N_, typename L_> + struct flat_zones_functor { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::labeling: - typedef mln_pset(I_) S; + typedef I_ I; + typedef N_ N; + typedef L_ L; + typedef mln_pset(I) S; + + const I& input; + const N& nbh; const S& s; - mln_value(O) nlabels; - bool status; - inline - bool equiv(const P& n, const P&) const { return input(n) = input(p); } + bool handles(const P&) const { return true; } + bool equiv(const P& n, const P& p) const { return input(n) = input(p); } + + void init() {} + bool labels(const P&) const { return true; } + void do_no_union(const P&, const P&) {} + void init_attr(const P&) {} + void merge_attr(const P&, const P&) {} // end of requirements - inline - flat_zones_(const I_& input, const N_& nbh, O_& output) - : base_<I_,N_,O_>(input, nbh, output), + flat_zones_functor(const I_& input, const N_& nbh) + : input(input), + nbh(nbh), s(input.domain()) {} }; + + // Generic implementation. + + namespace generic + { + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + flat_zones_(const I& input, const N& nbh, L& nlabels) + { + trace::entering("labeling::impl::generic::flat_zones_"); + + typedef flat_zones_functor<I,N,L> F; + F f(input, nbh); + canvas::labeling<F> run(f); + nlabels = run.nlabels; + + trace::exiting("labeling::impl::generic::flat_zones_"); + return run.output; + } + + } // end of namespace mln::labeling::impl::generic + + } // end of namespace mln::labeling::impl + // Facade. - template <typename I, typename N, typename O> - inline - bool flat_zones(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, - unsigned& nlabels) - { - mln_precondition(exact(output).domain() = exact(input).domain()); - typedef impl::flat_zones_<I,N,O> F; - F f(exact(input), exact(nbh), exact(output)); - canvas::labeling<F> run(f); - nlabels = f.nlabels; - return f.status; + template <typename I, typename N, typename L> + mln_ch_value(I, L) + flat_zones(const Image<I>& input_, const Neighborhood<N>& nbh_, + L& nlabels) + { + trace::entering("labeling::flat_zones"); + const I& input = exact(input_); + const N& nbh = exact(nbh_); + mln_precondition(input.has_data()); + + // Calls the only (generic) impl. + mln_ch_value(I, L) output = impl::generic::flat_zones_(input, nbh, nlabels); + + trace::exiting("labeling::flat_zones"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/labeling/level.hh --- mln/labeling/level.hh (revision 1598) +++ mln/labeling/level.hh (working copy) @@ -35,10 +35,12 @@ */ # include <mln/core/concept/image.hh> -# include <mln/labeling/base.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/canvas/labeling.hh> # include <mln/level/fill.hh> -# include <mln/border/adjust.hh> -# include <mln/value/other.hh> + +// The 'fastest' specialization is in: +# include <mln/labeling/level.spe.hh> @@ -57,10 +59,11 @@ * \param[out] nlabels The number of labels. * \return The label image. */ - template <typename I, typename N> - mln_ch_value(I, unsigned) + template <typename I, typename N, typename L> + mln_ch_value(I, L) level(const Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, - unsigned& nlabels); + L& nlabels); + # ifndef MLN_INCLUDE_ONLY @@ -68,125 +71,91 @@ namespace impl { - // Functors. + // Generic functor. - template <typename I_, typename N_, typename O_> - struct level_t : base_<I_,N_,O_> + template <typename I_, typename N_, typename L_> + struct level_functor { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::labeling: - typedef mln_pset(I_) S; + typedef I_ I; + typedef N_ N; + typedef L_ L; + typedef mln_pset(I) S; + + const I& input; + const N& nbh; const S& s; - inline - void init() { mln::level::fill(this->output, 0); } // FIXME: use literal::zero - inline bool handles(const P& p) const { return input(p) = val; } - inline bool equiv(const P& n, const P&) const { return input(n) = val; } + void init() {} + bool labels(const P&) const { return true; } + void do_no_union(const P&, const P&) {} + void init_attr(const P&) {} + void merge_attr(const P&, const P&) {} + // end of requirements const mln_value(I_)& val; - inline - level_t(const I_& input, const mln_value(I_)& val, const N_& nbh, O_& output) - : base_<I_,N_,O_>(input, nbh, output), + level_functor(const I_& input, const mln_value(I_)& val, const N_& nbh) + : input(input), + nbh(nbh), s(input.domain()), val(val) {} }; - // Routines. - template <typename I, typename N> - inline - mln_ch_value(I, unsigned) - level_(trait::image::speed::any, const I& input, - const mln_value(I)& val, const Neighborhood<N>& nbh, - unsigned& nlabels) - { - typedef mln_ch_value(I, unsigned) O; - O output; - initialize(output, input); + // Generic implementation. - typedef impl::level_t<I,N,O> F; - F f(input, val, exact(nbh), output); - canvas::labeling<F> run(f); - - nlabels = f.nlabels; - // FIXME: Handle f.status - return output; - } - - // FIXME: Add fast versions. - - template <typename I_, typename N_, typename O_> - struct level_fast_t : labeling::impl::base_fast_<I_,N_,O_> + namespace generic { - typedef mln_point(I_) P; - - // typedef mln_pset(I_) S; - // const S& s; - - inline - void init() { mln::level::fill(this->output, 0); } - inline - bool handles(unsigned p) const { return this->input[p] = val; } - inline - bool equiv(unsigned n, unsigned) const { return this->input[n] = val; } - - const mln_value(I_)& val; - inline - 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 L> + mln_ch_value(I, L) + level_(const I& input, const mln_value(I)& val, const N& nbh, + L& nlabels) + { + trace::entering("labeling::impl::generic::level_"); + typedef level_functor<I,N,L> F; + F f(input, val, nbh); + canvas::labeling<F> run(f); - template <typename I, typename N> - inline - mln_ch_value(I, unsigned) - level_(trait::image::speed::fastest, const I& input, - const mln_value(I)& val, const Neighborhood<N>& nbh, - unsigned& nlabels) - { - typedef mln_ch_value(I, unsigned) O; - typedef level_fast_t<I,N,O> F; - - border::adjust(input, exact(nbh).delta()); - O output; - initialize(output, input); - mln_assertion(output.border() = input.border()); + nlabels = run.nlabels; + // FIXME: Handle run.status - F f(input, val, exact(nbh), output); - canvas::labeling_fast<F> run(f); + trace::exiting("labeling::impl::generic::level_"); + return run.output; + } - // FIXME: Handle f.status + } // end of namespace mln::labeling::impl::generic - nlabels = f.nlabels; - return output; - } } // end of namespace mln::labeling::impl + // Facade. - template <typename I, typename N> - inline - mln_ch_value(I, unsigned) + template <typename I, typename N, typename L> + mln_ch_value(I, L) level(const Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, - unsigned& nlabels) + L& nlabels) { + trace::entering("labeling::level"); mln_precondition(exact(input).has_data()); - return impl::level_(mln_trait_image_speed(I)(), exact(input), - val, nbh, nlabels); + + mln_ch_value(I, L) output = impl::level_(mln_trait_image_speed(I)(), + exact(input), val, exact(nbh), nlabels); + + trace::exiting("labeling::level"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/labeling/all.hh --- mln/labeling/all.hh (revision 1598) +++ mln/labeling/all.hh (working copy) @@ -47,7 +47,7 @@ } # include <mln/labeling/background.hh> -# include <mln/labeling/base.hh> +# include <mln/labeling/blobs.hh> # include <mln/labeling/estimate.hh> # include <mln/labeling/flat_zones.hh> # include <mln/labeling/foreground.hh> Index: mln/labeling/regional_minima.hh --- mln/labeling/regional_minima.hh (revision 1598) +++ mln/labeling/regional_minima.hh (working copy) @@ -34,7 +34,10 @@ * image. */ -# include <mln/labeling/base.hh> +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/canvas/labeling.hh> +# include <mln/level/fill.hh> # include <mln/level/sort_points.hh> @@ -49,14 +52,14 @@ * * \param[in] input The input image. * \param[in] nbh The neighborhood to consider. - * \param[out] output The label image. - * \param[out] nlabels The number of labels. + * \param[out] nlabels The number of labeled regions. + * \return The label image. * - * \return The number of labels. */ - template <typename I, typename N, typename O> - bool regional_minima(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, unsigned& nlabels); + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_minima(const Image<I>& input, const Neighborhood<N>& nbh, + L& nlabels); @@ -65,58 +68,92 @@ namespace impl { - template <typename I_, typename N_, typename O_> - struct regional_minima_ : base_<I_,N_,O_> + // Generic functor. + + template <typename I_, typename N_, typename L_> + struct regional_minima_functor { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::labeling: + typedef I_ I; + typedef N_ N; + typedef L_ L; typedef p_array<P> S; + + const I& input; + const N& nbh; S s; - inline - void init() { mln::level::fill(this->output, 0); - level::fill(attr, true); } - inline + void init() { level::fill(attr, true); } + bool handles(const P&) const { return true; } bool labels(const P& p) const { return attr(p); } - inline bool equiv(const P& n, const P& p) const { return input(n) = input(p); } - inline void do_no_union(const P& n, const P& p) { mln_invariant(input(n) < input(p)); attr(p) = false; } - inline + void init_attr(const P&) {} void merge_attr(const P& r, const P& p) { attr(p) = attr(p) && attr(r); } // end of requirements - mln_ch_value(O_, bool) attr; + mln_ch_value(I, bool) attr; - inline - regional_minima_(const I_& input, const N_& nbh, O_& output) - : base_<I_,N_,O_>(input, nbh, output), - s(level::sort_points_increasing(input)), - attr(output.domain()) + regional_minima_functor(const I_& input, const N_& nbh) + : input(input), + nbh(nbh), + s(level::sort_points_increasing(input)), // FIXME: sort_psites_increasing + attr(input.domain()) { } }; + + // Generic implementation. + + namespace generic + { + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_minima_(const I& input, const N& nbh, + L& nlabels) + { + trace::entering("labeling::impl::generic::regional_minima_"); + + typedef impl::regional_minima_functor<I,N,L> F; + F f(input, nbh); + canvas::labeling<F> run(f); + nlabels = run.nlabels; + + trace::exiting("labeling::impl::generic::regional_minima_"); + return run.output; + } + + } // end of namespace mln::labeling::impl::generic + + } // end of namespace mln::labeling::impl + // Facade. - template <typename I, typename N, typename O> - inline - bool regional_minima(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, unsigned& nlabels) - { - mln_precondition(exact(output).domain() = exact(input).domain()); - typedef impl::regional_minima_<I,N,O> F; - F f(exact(input), exact(nbh), exact(output)); - canvas::labeling<F> run(f); - nlabels = f.nlabels; - return f.status; + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_minima(const Image<I>& input_, const Neighborhood<N>& nbh_, + L& nlabels) + { + trace::entering("labeling::regional_minima"); + const I& input = exact(input_); + const N& nbh = exact(nbh_); + mln_precondition(input.has_data()); + + // Calls the only (generic) impl. + mln_ch_value(I, L) output = impl::generic::regional_minima_(input, nbh, nlabels); + + trace::exiting("labeling::regional_minima"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/labeling/foreground.hh --- mln/labeling/foreground.hh (revision 1598) +++ mln/labeling/foreground.hh (working copy) @@ -50,6 +50,13 @@ * \param[in] nbh The neighborhood to consider. * \param[out] nlabels The number of labels. * \return The label image. + * + * \pre The input image has to be binary (checked at compile-time). + * + * This routine actually calls mln::labeling::level with the level + * value set to \c true. + * + * \see mln::labeling::level */ template <typename I, typename N> mln_ch_value(I, unsigned) @@ -65,8 +72,14 @@ foreground(const Image<I>& input, const Neighborhood<N>& nbh, unsigned& nlabels) { + trace::entering("labeling::foreground"); + mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check(); mln_precondition(exact(input).has_data()); - return labeling::level(input, true, nbh, nlabels); + + mln_ch_value(I, unsigned) output = labeling::level(input, true, nbh, nlabels); + + trace::exiting("labeling::foreground"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/labeling/regional_maxima.hh --- mln/labeling/regional_maxima.hh (revision 1598) +++ mln/labeling/regional_maxima.hh (working copy) @@ -34,7 +34,10 @@ * image. */ -# include <mln/labeling/base.hh> +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/canvas/labeling.hh> +# include <mln/level/fill.hh> # include <mln/level/sort_points.hh> @@ -49,14 +52,14 @@ * * \param[in] input The input image. * \param[in] nbh The neighborhood to consider. - * \param[out] output The label image. * \param[out] nlabels The number of labeled regions. + * \return The label image. * - * \return The number of labels. */ - template <typename I, typename N, typename O> - bool regional_maxima(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, unsigned& nlabels); + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_maxima(const Image<I>& input, const Neighborhood<N>& nbh, + L& nlabels); @@ -65,58 +68,92 @@ namespace impl { - template <typename I_, typename N_, typename O_> - struct regional_maxima_ : base_<I_,N_,O_> + // Generic functor. + + template <typename I_, typename N_, typename L_> + struct regional_maxima_functor { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::labeling: + typedef I_ I; + typedef N_ N; + typedef L_ L; typedef p_array<P> S; + + const I& input; + const N& nbh; S s; - inline - void init() { mln::level::fill(this->output, 0); - level::fill(attr, true); } - inline + void init() { level::fill(attr, true); } + bool handles(const P&) const { return true; } bool labels(const P& p) const { return attr(p); } - inline bool equiv(const P& n, const P& p) const { return input(n) = input(p); } - inline void do_no_union(const P& n, const P& p) { mln_invariant(input(n) > input(p)); attr(p) = false; } - inline + void init_attr(const P&) {} void merge_attr(const P& r, const P& p) { attr(p) = attr(p) && attr(r); } // end of requirements - mln_ch_value(O_, bool) attr; + mln_ch_value(I, bool) attr; - inline - regional_maxima_(const I_& input, const N_& nbh, O_& output) - : base_<I_,N_,O_>(input, nbh, output), - s(level::sort_points_decreasing(input)), - attr(output.domain()) + regional_maxima_functor(const I_& input, const N_& nbh) + : input(input), + nbh(nbh), + s(level::sort_points_decreasing(input)), // FIXME: sort_psites_decreasing + attr(input.domain()) { } }; + + // Generic implementation. + + namespace generic + { + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_maxima_(const I& input, const N& nbh, + L& nlabels) + { + trace::entering("labeling::impl::generic::regional_maxima_"); + + typedef impl::regional_maxima_functor<I,N,L> F; + F f(input, nbh); + canvas::labeling<F> run(f); + nlabels = run.nlabels; + + trace::exiting("labeling::impl::generic::regional_maxima_"); + return run.output; + } + + } // end of namespace mln::labeling::impl::generic + + } // end of namespace mln::labeling::impl + // Facade. - template <typename I, typename N, typename O> - inline - bool regional_maxima(const Image<I>& input, const Neighborhood<N>& nbh, - Image<O>& output, unsigned& nlabels) - { - mln_precondition(exact(output).domain() = exact(input).domain()); - typedef impl::regional_maxima_<I,N,O> F; - F f(exact(input), exact(nbh), exact(output)); - canvas::labeling<F> run(f); - nlabels = f.nlabels; - return f.status; + template <typename I, typename N, typename L> + mln_ch_value(I, L) + regional_maxima(const Image<I>& input_, const Neighborhood<N>& nbh_, + L& nlabels) + { + trace::entering("labeling::regional_maxima"); + const I& input = exact(input_); + const N& nbh = exact(nbh_); + mln_precondition(input.has_data()); + + // Calls the only (generic) impl. + mln_ch_value(I, L) output = impl::generic::regional_maxima_(input, nbh, nlabels); + + trace::exiting("labeling::regional_maxima"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: mln/labeling/level.spe.hh --- mln/labeling/level.spe.hh (revision 0) +++ mln/labeling/level.spe.hh (revision 0) @@ -0,0 +1,175 @@ +// Copyright (C) 2007 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_LABELING_LEVEL_SPE_HH +# define MLN_LABELING_LEVEL_SPE_HH + +/*! \file mln/labeling/level.spe.hh + * + * \brief Specialization for mln::labeling::level. + */ + +# include <mln/border/adjust.hh> +# include <mln/border/fill.hh> +# include <mln/value/other.hh> + + + +namespace mln +{ + + namespace labeling + { + + /*! Connected component labeling of the image objects at a given + * level. + * + * \param[in] input The input image. + * \param[in] val The level to consider for the labeling. + * \param[in] nbh The neighborhood. + * \param[out] nlabels The number of labels. + * \return The label image. + */ + template <typename I, typename N, typename L> + mln_ch_value(I, L) + level(const Image<I>& input, const mln_value(I)& val, const Neighborhood<N>& nbh, + L& nlabels); + + +# ifndef MLN_INCLUDE_ONLY + + namespace impl + { + + // Fwd decl of the Generic version. + + namespace generic + { + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + level_(const I& input, const mln_value(I)& val, const N& nbh, + L& nlabels); + + } // end of namespace mln::labeling::impl::generic + + + + // Fastest functor. + + template <typename I_, typename N_, typename L_> + struct level_fastest_functor + { + // requirements from mln::canvas::labeling: + + typedef I_ I; + typedef N_ N; + typedef L_ L; + typedef mln_pset(I) S; + + const I& input; + const N& nbh; + const S& s; + + bool handles(unsigned p) const { return input[p] = val; } + bool equiv(unsigned n, unsigned) const { return input[n] = val; } + + void init() {} + bool labels(unsigned) const { return true; } + void do_no_union(unsigned, unsigned) {} + void init_attr(unsigned) {} + void merge_attr(unsigned, unsigned) {} + + // end of requirements + + const mln_value(I_)& val; + + level_fastest_functor(const I_& input, const mln_value(I_)& val, const N_& nbh) + : input(input), + nbh(nbh), + s(input.domain()), + val(val) + {} + }; + + + // Fastest routine. + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + level_fastest_(const I& input, const mln_value(I)& val, const N& nbh, + L& nlabels) + { + trace::entering("labeling::impl::level_fastest_"); + + border::adjust(input, nbh.delta()); + border::fill(input, value::other(val)); + + typedef level_fastest_functor<I,N,L> F; + F f(input, val, nbh); + canvas::labeling_fastest<F> run(f); + + nlabels = run.nlabels; + // FIXME: Handle run.status + + trace::exiting("labeling::impl::level_fastest_"); + return run.output; + } + + + // Disjunction between "fastest" and "not fastest". + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + level_(trait::image::speed::any, + const I& input, const mln_value(I)& val, const N& nbh, + L& nlabels) + { + return generic::level_(input, val, nbh, nlabels); + } + + template <typename I, typename N, typename L> + mln_ch_value(I, L) + level_(trait::image::speed::fastest, + const I& input, const mln_value(I)& val, const N& nbh, + L& nlabels) + { + return level_fastest_(input, val, nbh, nlabels); + } + + + } // end of namespace mln::labeling::impl + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::labeling + +} // end of namespace mln + + +#endif // ! MLN_LABELING_LEVEL_SPE_HH Index: mln/labeling/background.hh --- mln/labeling/background.hh (revision 1598) +++ mln/labeling/background.hh (working copy) @@ -43,13 +43,20 @@ namespace labeling { - /*! Connected component labeling of the background in a binary - * image. + /*! Connected component labeling of the background part in a + * binary image. * * \param[in] input The input image. * \param[in] nbh The neighborhood to consider. * \param[out] nlabels The number of labels. * \return The label image. + * + * \pre The input image has to be binary (checked at compile-time). + * + * This routine actually calls mln::labeling::level with the level + * value set to \c false. + * + * \see mln::labeling::level */ template <typename I, typename N> mln_ch_value(I, unsigned) @@ -65,8 +72,14 @@ background(const Image<I>& input, const Neighborhood<N>& nbh, unsigned& nlabels) { + trace::entering("labeling::background"); + mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check(); mln_precondition(exact(input).has_data()); - return labeling::level(input, false, nbh, nlabels); + + mln_ch_value(I, unsigned) output = labeling::level(input, false, nbh, nlabels); + + trace::exiting("labeling::background"); + return output; } # endif // ! MLN_INCLUDE_ONLY Index: img/README --- img/README (revision 0) +++ img/README (revision 0) @@ -0,0 +1,8 @@ + -*- outline -*- + +* tiny.pgm + +lena 16x16, graylevel / 8bit + +it was obtained by running the command: +convert -geometry 3.125% lena.pgm tiny.pgm Index: sandbox/geraud/estimate.hh --- sandbox/geraud/estimate.hh (revision 1593) +++ sandbox/geraud/estimate.hh (working copy) @@ -33,8 +33,13 @@ * \brief Compute the estimate pixel value. */ -# include <mln/core/image_if_value.hh> +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/canvas/labeling.hh> + # include <mln/accu/compute.hh> +// # include <mln/core/image_if_value.hh> + namespace mln @@ -43,28 +48,36 @@ namespace labeling { - /*! \brief FIXME: Compute an estimate over the pixels of image \p - * input with value \p val. + /*! \brief Label a binary image and compute some estimations over + * the components. * * \param[in] input The image. - * \param[in] val value. - * \result The estimate value. + * + * The free parameter \c A is a type of accumulator. + * + * FIXME: Not yet impled. */ template <typename A, typename I> - mln_accu_with(A, util::pix<I>)::result - estimate(const Image<I>& input, const mln_value(I)& val); + void + estimate(const Image<I>& input); # ifndef MLN_INCLUDE_ONLY template <typename A, typename I> - inline - mln_accu_with(A, util::pix<I>)::result - estimate(const Image<I>& input, const mln_value(I)& val) + void + estimate(const Image<I>& input) { -// void* v = (input | val); -// return 0; - return accu::compute<A>(input | val); + trace::entering("labeling::estimate"); + mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check(); + mln_precondition(exact(input).has_data()); + + std::cerr << "Sorry: mln::labeling::estimate is not yet implemented!" << std::endl; + + // FIXME: Was: + // mln_accu_with(A, util::pix<I>)::result res = accu::compute<A>(input | val); + + trace::exiting("labeling::estimate"); } # endif // ! MLN_INCLUDE_ONLY