
* mln/core/concept/function.hh: add Function_l2b and Function_l2l. * mln/fun/i2v/array.hh: inherits from array_base. * mln/fun/internal/array_base.hh: base implementation for functions based on an array. * mln/fun/l2l/relabel.hh: l2l function used in labeling::relabel. * mln/labeling/blobs.hh: use literal::zero and compare output(p) to literal::zero instead of using operator!. * mln/labeling/relabel.hh: new routine. * mln/make/relabelfun.hh: new. Create a l2l function from a l2b function. * mln/value/label.hh: update. Make it work. * mln/value/label_16.hh, * mln/value/label_8.hh: New aliases. * tests/labeling/Makefile.am, * tests/labeling/relabel.cc: add a new test for labeling::relabel. --- milena/ChangeLog | 29 +++ milena/mln/core/concept/function.hh | 200 +++++++++++++------- milena/mln/fun/i2v/array.hh | 63 ++----- .../fun/{i2v/array.hh => internal/array_base.hh} | 146 +++++---------- milena/mln/fun/{i2v/array.hh => l2l/relabel.hh} | 161 +++++++--------- milena/mln/labeling/blobs.hh | 47 +++--- milena/mln/labeling/relabel.hh | 130 +++++++++++++ milena/mln/make/relabelfun.hh | 93 +++++++++ milena/mln/value/label.hh | 142 +++++++------- milena/mln/value/label_16.hh | 54 ++++++ milena/mln/value/label_8.hh | 54 ++++++ milena/tests/labeling/Makefile.am | 4 +- milena/tests/labeling/relabel.cc | 96 ++++++++++ 13 files changed, 808 insertions(+), 411 deletions(-) copy milena/mln/fun/{i2v/array.hh => internal/array_base.hh} (58%) copy milena/mln/fun/{i2v/array.hh => l2l/relabel.hh} (53%) create mode 100644 milena/mln/labeling/relabel.hh create mode 100644 milena/mln/make/relabelfun.hh create mode 100644 milena/mln/value/label_16.hh create mode 100644 milena/mln/value/label_8.hh create mode 100644 milena/tests/labeling/relabel.cc diff --git a/milena/ChangeLog b/milena/ChangeLog index c8f90ed..07bdbdc 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,3 +1,32 @@ +2008-11-20 Guillaume Lazzara <z@lrde.epita.fr> + + Add labeling::relabel. + + * mln/core/concept/function.hh: add Function_l2b and Function_l2l. + + * mln/fun/i2v/array.hh: inherits from array_base. + + * mln/fun/internal/array_base.hh: base implementation for functions + based on an array. + + * mln/fun/l2l/relabel.hh: l2l function used in labeling::relabel. + + * mln/labeling/blobs.hh: use literal::zero and compare output(p) to + literal::zero instead of using operator!. + + * mln/labeling/relabel.hh: new routine. + + * mln/make/relabelfun.hh: new. Create a l2l function from a l2b + function. + + * mln/value/label.hh: update. Make it work. + + * mln/value/label_16.hh, + * mln/value/label_8.hh: New aliases. + + * tests/labeling/Makefile.am, + * tests/labeling/relabel.cc: add a new test for labeling::relabel. + 2008-11-20 Thierry Geraud <thierry.geraud@lrde.epita.fr> Bench the diff between canvas as class v. as procedure. diff --git a/milena/mln/core/concept/function.hh b/milena/mln/core/concept/function.hh index 68cb2d8..37112a4 100644 --- a/milena/mln/core/concept/function.hh +++ b/milena/mln/core/concept/function.hh @@ -1,4 +1,5 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// 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 @@ -28,10 +29,9 @@ #ifndef MLN_CORE_CONCEPT_FUNCTION_HH # define MLN_CORE_CONCEPT_FUNCTION_HH -/*! \file mln/core/concept/function.hh - * - * \brief Definition of several concepts of functions. - */ +/// \file mln/core/concept/function.hh +/// +/// Definition of several concepts of functions. # include <mln/core/concept/object.hh> @@ -48,10 +48,11 @@ namespace mln template <typename E> struct Function_p2b; template <typename E> struct Function_p2p; template <typename E> struct Function_x2x; + template <typename E> struct Function_l2b; + template <typename E> struct Function_l2l; template <typename E> struct Function_vv2v; - /// Function category flag type. template <> struct Function<void> @@ -60,19 +61,20 @@ namespace mln }; - /*! \brief Base class for implementation of function-objects. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function : public Object<E> { typedef Function<void> category; - /* - An operator() has to be provided. Its signature depends - on the particular function-object one considers. - */ + /* + ** An operator() has to be provided. Its signature depends + ** on the particular function-object one considers. + */ + protected: Function(); Function(const Function&); @@ -86,12 +88,11 @@ namespace mln template <> struct Function_v2v<void> { typedef Function<void> super; }; - /*! - * \brief Base class for implementation of function-objects from - * value to value. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from + /// value to value. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_v2v : public Function<E> { @@ -109,12 +110,11 @@ namespace mln template <> struct Function_i2v<void> { typedef Function_v2v<void> super; }; - /*! - * \brief Base class for implementation of function-objects from - * index to value. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from + /// index to value. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_i2v : public Function_v2v<E> { @@ -132,12 +132,11 @@ namespace mln template <> struct Function_p2v<void> { typedef Function_v2v<void> super; }; - /*! - * \brief Base class for implementation of function-objects from point to - * value. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from point to + /// value. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_p2v : public virtual Function_v2v<E> { @@ -155,12 +154,11 @@ namespace mln template <> struct Function_v2b<void> { typedef Function_v2v<void> super; }; - /*! - * \brief Base class for implementation of function-objects from value to - * bool. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from value to + /// bool. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_v2b : public virtual Function_v2v<E> { @@ -179,12 +177,11 @@ namespace mln template <> struct Function_p2b<void> { typedef Function_p2v<void> super; }; // FIXME - /*! - * \brief Base class for implementation of function-objects from point to - * bool. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from point to + /// bool. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_p2b : public Function_p2v<E>, public Function_v2b<E> @@ -204,12 +201,11 @@ namespace mln template <> struct Function_p2p<void> { typedef Function_p2v<void> super; }; // FIXME - /*! - * \brief Base class for implementation of function-objects from point to - * point. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from point to + /// point. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_p2p : public Function_p2v<E> { @@ -227,12 +223,11 @@ namespace mln template <> struct Function_x2x<void> { typedef Function_v2v<void> super; }; // FIXME - /*! - * \brief Base class for implementation of function-objects from vector to - * vector. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from vector to + /// Vector. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_x2x : public Function_v2v<E> { @@ -247,12 +242,11 @@ namespace mln | Vector <-> Vector. | `--------------------*/ - /*! - * \brief Base class for implementation of bijective function-objects from - * vector to vector. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of bijective function-objects from + /// vector to vector. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Bijection_x2x : public Function_x2x< E > { @@ -265,6 +259,50 @@ namespace mln }; + /*-----------------. + | Label -> Value. | + `-----------------*/ + + template <> + struct Function_l2b<void> { typedef Function_v2b<void> super; }; + + /// Base class for implementation of function-objects from + /// label to value. + /// + /// The parameter \a E is the exact type. + /// + template <typename E> + struct Function_l2b : public Function_v2b<E> + { + typedef Function_l2b<void> category; + protected: + Function_l2b(); + Function_l2b(const Function_l2b&); + }; + + + /*-----------------. + | Label -> Label. | + `-----------------*/ + + template <> + struct Function_l2l<void> { typedef Function_v2v<void> super; }; + + /// Base class for implementation of function-objects from + /// label to value. + /// + /// The parameter \a E is the exact type. + /// + template <typename E> + struct Function_l2l : public Function_v2v<E> + { + typedef Function_l2l<void> category; + protected: + Function_l2l(); + Function_l2l(const Function_l2l&); + }; + + /*------------------------. | Value, Value -> Value. | `------------------------*/ @@ -272,12 +310,11 @@ namespace mln template <> struct Function_vv2v<void> { typedef Function<void> super; }; - /*! - * \brief Base class for implementation of function-objects from - * a couple of values to a value. - * - * The parameter \a E is the exact type. - */ + /// Base class for implementation of function-objects from + /// a couple of values to a value. + /// + /// The parameter \a E is the exact type. + /// template <typename E> struct Function_vv2v : public Function<E> { @@ -408,6 +445,33 @@ namespace mln template <typename E> inline + Function_l2b<E>::Function_l2b() + { + } + + template <typename E> + inline + Function_l2b<E>::Function_l2b(const Function_l2b<E>& rhs) + : Function_v2v<E>(rhs), + Function_v2b<E>(rhs) + { + } + + template <typename E> + inline + Function_l2l<E>::Function_l2l() + { + } + + template <typename E> + inline + Function_l2l<E>::Function_l2l(const Function_l2l<E>& rhs) + : Function_v2v<E>(rhs) + { + } + + template <typename E> + inline Function_vv2v<E>::Function_vv2v() { } diff --git a/milena/mln/fun/i2v/array.hh b/milena/mln/fun/i2v/array.hh index a97bf33..ee9b1bb 100644 --- a/milena/mln/fun/i2v/array.hh +++ b/milena/mln/fun/i2v/array.hh @@ -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 @@ -34,6 +34,7 @@ # include <vector> # include <algorithm> +# include <mln/fun/internal/array_base.hh> # include <mln/core/concept/function.hh> # include <mln/util/array.hh> @@ -41,7 +42,6 @@ namespace mln { - /// Forward declaration. namespace fun { @@ -74,7 +74,6 @@ namespace mln } // end of namespace mln::convert - namespace fun { @@ -82,11 +81,12 @@ namespace mln { template <typename T> - class array : public Function_i2v< array<T> > + class array : public Function_i2v< array<T> >, + public internal::array_base<T> { - public: + typedef internal::array_base<T> super_base_; - typedef T result; + public: /// Constructors /// \{ @@ -95,6 +95,8 @@ namespace mln array(); /// Constructs a function with \p nvalues. array(unsigned n); + /// Constructs a function with \p nvalues and \p val as default value. + array(unsigned n, const T& val); /// Used in from_to(). Constructs that function from an util::array. /// Always prefer using from_to instead of this constructor. @@ -105,14 +107,6 @@ namespace mln /// \} - void resize(unsigned n); - unsigned size() const; - - const T& operator()(unsigned i) const; - T& operator()(unsigned i); - - private: - std::vector<T> v_; }; } // end of namespace mln::fun::i2v @@ -120,6 +114,7 @@ namespace mln } // end of namespace mln::fun + # ifndef MLN_INCLUDE_ONLY @@ -165,14 +160,14 @@ namespace mln template <typename T> inline array<T>::array(unsigned n) + : super_base_(n) { - resize(n); } template <typename T> inline array<T>::array(const util::array<T>& from) - : v_(from.std_vector()) + : super_base_(from) { } @@ -180,45 +175,11 @@ namespace mln template <typename T> inline array<T>::array(const std::vector<T>& from) - : v_(from) + : super_base_(from) { } - template <typename T> - inline - void - array<T>::resize(unsigned n) - { - v_.resize(n); - } - - template <typename T> - inline - unsigned - array<T>::size() const - { - return v_.size(); - } - - template <typename T> - inline - const T& - array<T>::operator()(unsigned i) const - { - mln_precondition(i < v_.size()); - return v_[i]; - } - - template <typename T> - inline - T& - array<T>::operator()(unsigned i) - { - mln_precondition(i < v_.size()); - return v_[i]; - } - } // end of namespace mln::fun::i2v } // end of namespace mln::fun diff --git a/milena/mln/fun/i2v/array.hh b/milena/mln/fun/internal/array_base.hh similarity index 58% copy from milena/mln/fun/i2v/array.hh copy to milena/mln/fun/internal/array_base.hh index a97bf33..32abb8a 100644 --- a/milena/mln/fun/i2v/array.hh +++ b/milena/mln/fun/internal/array_base.hh @@ -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,10 +25,10 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_FUN_I2V_ARRAY_HH -# define MLN_FUN_I2V_ARRAY_HH +#ifndef MLN_FUN_INTERNAL_ARRAY_BASE_HH +# define MLN_FUN_INTERNAL_ARRAY_BASE_HH -/// \file mln/fun/i2v/array.hh +/// \file mln/fun/internal/array_base.hh /// /// Function mapping an Id i to a value v. @@ -41,137 +41,92 @@ namespace mln { - - /// Forward declaration. namespace fun { - namespace i2v + namespace internal { template <typename T> - class array; - - } // end of namespace mln::fun::i2v - - } // end of namespace mln::fun - - - - namespace convert - { - - template <typename T> - inline - void - from_to(const util::array<T>& from, fun::i2v::array<T>& to); - - template <typename T> - inline - void - from_to(const std::vector<T>& from, fun::i2v::array<T>& to); - - } // end of namespace mln::convert + class array_base + { + public: + typedef T result; + void resize(unsigned n); + unsigned size() const; - namespace fun - { + const T& operator()(unsigned i) const; + T& operator()(unsigned i); - namespace i2v - { - template <typename T> - class array : public Function_i2v< array<T> > - { - public: + protected: - typedef T result; + std::vector<T> v_; /// Constructors /// \{ /// Default. - array(); - /// Constructs a function with \p nvalues. - array(unsigned n); + array_base(); + /// Constructs an array with \p nvalues. + array_base(unsigned n); - /// Used in from_to(). Constructs that function from an util::array. + /// Constructs an array with \p nvalues and \p val as value. + array_base(unsigned n, const T& val); + + /// Used in from_to(). Constructs that object from an util::array. /// Always prefer using from_to instead of this constructor. - array(const util::array<T>& from); - /// Used in from_to(). Constructs that function from an std::vector. + array_base(const util::array<T>& from); + /// Used in from_to(). Constructs that object from an std::vector. /// Always prefer using from_to instead of this constructor. - array(const std::vector<T>& from); + array_base(const std::vector<T>& from); /// \} - void resize(unsigned n); - unsigned size() const; - - const T& operator()(unsigned i) const; - T& operator()(unsigned i); - - private: - std::vector<T> v_; }; - } // end of namespace mln::fun::i2v + } // end of namespace mln::fun::internal } // end of namespace mln::fun -# ifndef MLN_INCLUDE_ONLY - - - // convert::from_to - - namespace convert - { - - template <typename T> - inline - void - from_to(const util::array<T>& from, fun::i2v::array<T>& to) - { - to = fun::i2v::array<T>(from); - } - - template <typename T> - inline - void - from_to(const std::vector<T>& from, fun::i2v::array<T>& to) - { - to = fun::i2v::array<T>(from); - } - - } // end of namespace mln::convert +# ifndef MLN_INCLUDE_ONLY - /// fun::i2v::array + /// fun::internal::array_base namespace fun { - namespace i2v + namespace internal { template <typename T> inline - array<T>::array() + array_base<T>::array_base() { } template <typename T> inline - array<T>::array(unsigned n) + array_base<T>::array_base(unsigned n) + : v_(n) { - resize(n); } template <typename T> inline - array<T>::array(const util::array<T>& from) + array_base<T>::array_base(unsigned n, const T& val) + : v_(n, val) + { + } + + template <typename T> + inline + array_base<T>::array_base(const util::array<T>& from) : v_(from.std_vector()) { @@ -179,7 +134,7 @@ namespace mln template <typename T> inline - array<T>::array(const std::vector<T>& from) + array_base<T>::array_base(const std::vector<T>& from) : v_(from) { @@ -188,7 +143,7 @@ namespace mln template <typename T> inline void - array<T>::resize(unsigned n) + array_base<T>::resize(unsigned n) { v_.resize(n); } @@ -196,7 +151,7 @@ namespace mln template <typename T> inline unsigned - array<T>::size() const + array_base<T>::size() const { return v_.size(); } @@ -204,7 +159,7 @@ namespace mln template <typename T> inline const T& - array<T>::operator()(unsigned i) const + array_base<T>::operator()(unsigned i) const { mln_precondition(i < v_.size()); return v_[i]; @@ -213,27 +168,20 @@ namespace mln template <typename T> inline T& - array<T>::operator()(unsigned i) + array_base<T>::operator()(unsigned i) { mln_precondition(i < v_.size()); return v_[i]; } - } // end of namespace mln::fun::i2v + } // end of namespace mln::fun::internal } // end of namespace mln::fun - template <typename T> - inline - fun::i2v::array<T> array(T t) - { - fun::i2v::array<T> tmp(t); - return tmp; - } # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln -#endif // ! MLN_FUN_I2V_ARRAY_HH +#endif // ! MLN_FUN_INTERNAL_ARRAY_BASE_HH diff --git a/milena/mln/fun/i2v/array.hh b/milena/mln/fun/l2l/relabel.hh similarity index 53% copy from milena/mln/fun/i2v/array.hh copy to milena/mln/fun/l2l/relabel.hh index a97bf33..f4cd50a 100644 --- a/milena/mln/fun/i2v/array.hh +++ b/milena/mln/fun/l2l/relabel.hh @@ -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,34 +25,36 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_FUN_I2V_ARRAY_HH -# define MLN_FUN_I2V_ARRAY_HH +#ifndef MLN_FUN_L2L_ARRAY_HH +# define MLN_FUN_L2L_ARRAY_HH -/// \file mln/fun/i2v/array.hh +/// \file mln/fun/l2l/array.hh /// -/// Function mapping an Id i to a value v. +/// Function mapping a label to a new one. +/// \sa mln::labeling::relabel # include <vector> # include <algorithm> +# include <mln/fun/internal/array_base.hh> # include <mln/core/concept/function.hh> # include <mln/util/array.hh> +# include <mln/metal/converts_to.hh> namespace mln { - /// Forward declaration. namespace fun { - namespace i2v + namespace l2l { - template <typename T> - class array; + template <typename L> + class relabel; - } // end of namespace mln::fun::i2v + } // end of namespace mln::fun::l2l } // end of namespace mln::fun @@ -61,58 +63,51 @@ namespace mln namespace convert { - template <typename T> + template <typename L> inline void - from_to(const util::array<T>& from, fun::i2v::array<T>& to); + from_to(const util::array<L>& from, + fun::l2l::relabel<L>& to); - template <typename T> + template <typename L> inline void - from_to(const std::vector<T>& from, fun::i2v::array<T>& to); + from_to(const std::vector<L>& from, + fun::l2l::relabel<L>& to); } // end of namespace mln::convert - namespace fun { - namespace i2v + namespace l2l { - template <typename T> - class array : public Function_i2v< array<T> > + template <typename L> + class relabel : public Function_l2l< relabel<L> >, + public internal::array_base<L> { - public: + typedef internal::array_base<L> super_base_; - typedef T result; - - /// Constructors - /// \{ + public: /// Default. - array(); + relabel(); /// Constructs a function with \p nvalues. - array(unsigned n); + relabel(unsigned n); + /// Constructs a function with \p nvalues and \p label as default label. + relabel(unsigned n, const L& label); /// Used in from_to(). Constructs that function from an util::array. /// Always prefer using from_to instead of this constructor. - array(const util::array<T>& from); + relabel(const util::array<L>& from); /// Used in from_to(). Constructs that function from an std::vector. /// Always prefer using from_to instead of this constructor. - array(const std::vector<T>& from); + relabel(const std::vector<L>& from); /// \} - void resize(unsigned n); - unsigned size() const; - - const T& operator()(unsigned i) const; - T& operator()(unsigned i); - - private: - std::vector<T> v_; }; } // end of namespace mln::fun::i2v @@ -120,6 +115,7 @@ namespace mln } // end of namespace mln::fun + # ifndef MLN_INCLUDE_ONLY @@ -128,112 +124,87 @@ namespace mln namespace convert { - template <typename T> + template <typename L> inline void - from_to(const util::array<T>& from, fun::i2v::array<T>& to) + from_to(const util::array<L>& from, fun::l2l::relabel<L>& to) { - to = fun::i2v::array<T>(from); + to = fun::l2l::relabel<L>(from); } - template <typename T> + template <typename L> inline void - from_to(const std::vector<T>& from, fun::i2v::array<T>& to) + from_to(const std::vector<L>& from, fun::l2l::relabel<L>& to) { - to = fun::i2v::array<T>(from); + to = fun::l2l::relabel<L>(from); } } // end of namespace mln::convert - /// fun::i2v::array + /// fun::l2l::relabel namespace fun { - namespace i2v + namespace l2l { - template <typename T> + template <typename L> inline - array<T>::array() + relabel<L>::relabel() { + // FIXME: Too restrictive? + mlc_converts_to(L, unsigned)::check(); } - template <typename T> + template <typename L> inline - array<T>::array(unsigned n) + relabel<L>::relabel(unsigned n) + : super_base_(n) { - resize(n); + // FIXME: Too restrictive? + mlc_converts_to(L, unsigned)::check(); } - template <typename T> + template <typename L> inline - array<T>::array(const util::array<T>& from) - : v_(from.std_vector()) + relabel<L>::relabel(unsigned n, const L& label) + : super_base_(n, label) { - + // FIXME: Too restrictive? + mlc_converts_to(L, unsigned)::check(); } - template <typename T> + template <typename L> inline - array<T>::array(const std::vector<T>& from) - : v_(from) + relabel<L>::relabel(const util::array<L>& from) + : super_base_(from) { - + // FIXME: Too restrictive? + mlc_converts_to(L, unsigned)::check(); } - template <typename T> + template <typename L> inline - void - array<T>::resize(unsigned n) + relabel<L>::relabel(const std::vector<L>& from) + : super_base_(from) { - v_.resize(n); + // FIXME: Too restrictive? + mlc_converts_to(L, unsigned)::check(); } - template <typename T> - inline - unsigned - array<T>::size() const - { - return v_.size(); - } - template <typename T> - inline - const T& - array<T>::operator()(unsigned i) const - { - mln_precondition(i < v_.size()); - return v_[i]; - } +# endif // ! MLN_INCLUDE_ONLY - template <typename T> - inline - T& - array<T>::operator()(unsigned i) - { - mln_precondition(i < v_.size()); - return v_[i]; - } - } // end of namespace mln::fun::i2v + } // end of namespace mln::fun::l2l } // end of namespace mln::fun - template <typename T> - inline - fun::i2v::array<T> array(T t) - { - fun::i2v::array<T> tmp(t); - return tmp; - } - -# endif // ! MLN_INCLUDE_ONLY - } // end of namespace mln -#endif // ! MLN_FUN_I2V_ARRAY_HH +#endif // ! MLN_FUN_L2L_ARRAY_HH diff --git a/milena/mln/labeling/blobs.hh b/milena/mln/labeling/blobs.hh index 9f521a9..f5d6689 100644 --- a/milena/mln/labeling/blobs.hh +++ b/milena/mln/labeling/blobs.hh @@ -29,13 +29,12 @@ #ifndef MLN_LABELING_BLOBS_HH # define MLN_LABELING_BLOBS_HH -/*! \file mln/labeling/blobs.hh - * - * \brief Connected component labeling of the binary objects of a binary - * image using a queue-based algorithm. - * - * \todo Handle abort in a nice way... - */ +/// \file mln/labeling/blobs.hh +/// +/// Connected component labeling of the binary objects of a binary +/// image using a queue-based algorithm. +/// +/// \todo Handle abort in a nice way... # include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> @@ -50,19 +49,19 @@ namespace mln namespace labeling { - /*! Connected component labeling of the binary objects of a binary - * image. - * - * \param[in] input The input image. - * \param[in] nbh The connexity of the objects. - * \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). - */ + /// Connected component labeling of the binary objects of a binary + /// image. + /// + /// \param[in] input The input image. + /// \param[in] nbh The connexity of the objects. + /// \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). + /// template <typename I, typename N, typename L> mln_ch_value(I, L) blobs(const Image<I>& input, const Neighborhood<N>& nbh, @@ -88,15 +87,15 @@ namespace mln p_queue_fast<P> qu; // Initialization. - nlabels = 0; + nlabels = literal::zero; mln_ch_value(I, L) output; initialize(output, input); - level::fill(output, 0); + level::fill(output, literal::zero); // Loop. mln_piter(I) p(input.domain()); for_all(p) - if (input(p) && ! output(p)) // Object point, not labeled yet. + if (input(p) && output(p) == literal::zero) // Object point, not labeled yet. { // Label this point component. if (nlabels == mln_max(L)) @@ -113,7 +112,7 @@ namespace mln cur = qu.front(); qu.pop(); for_all(n) if (input.has(n)) - if (input(n) && ! output(n)) + if (input(n) && output(n) == literal::zero) { mln_invariant(! qu.compute_has(n)); qu.push(n); diff --git a/milena/mln/labeling/relabel.hh b/milena/mln/labeling/relabel.hh new file mode 100644 index 0000000..841cd1c --- /dev/null +++ b/milena/mln/labeling/relabel.hh @@ -0,0 +1,130 @@ +// 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 +// 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_RELABEL_HH +# define MLN_LABELING_RELABEL_HH + +/// \file mln/labeling/relabel.hh +/// +/// Remove components and relabel a labeled image. + +# include <mln/core/concept/image.hh> +# include <mln/make/relabelfun.hh> +# include <mln/level/transform.hh> +# include <mln/level/transform_inplace.hh> +# include <mln/value/label.hh> + +namespace mln +{ + + namespace labeling + { + + /// Remove components and relabel a labeled image. + /// \input[in] label the labeled image. + /// \input[in] nlabels the number of labels in \p label. + /// \input[out] new_nlabels the number of labels after relabeling. + /// \input[in] f function returning the new component id for each pixel + /// value. + /// + /// \return the relabeled image. + template <typename I, typename F> + mln_concrete(I) + relabel(const Image<I>& label, + const mln_value(I)& nlabels, + mln_value(I)& new_nlabels, + const Function_l2b<F>& fl2b); + + /// Remove components and relabel a labeled image inplace. + /// \input[in, out] label the labeled image. + /// \input[in, out] nlabels the number of labels in \p label. + /// \input[in] f function returning the new component id for each + /// pixel value. + /// + template <typename I, typename F> + void + relabel_inplace(Image<I>& label, + mln_value(I)& nlabels, + const Function_l2b<F>& fl2b); + + +# ifndef MLN_INCLUDE_ONLY + + + template <typename I, typename F> + inline + mln_concrete(I) + relabel(const Image<I>& label, + const mln_value(I)& nlabels, + mln_value(I)& new_nlabels, + const Function_l2b<F>& fl2b) + { + trace::entering("labeling::relabel"); + + // FIXME: we may want to check that it is exactly a label. + mlc_is_a(mln_value(I), mln::value::Symbolic)::check(); + mln_precondition(exact(label).has_data()); + + typedef fun::l2l::relabel<mln_value(I)> fl2l_t; + fl2l_t fl2l = make::relabelfun(fl2b, nlabels, new_nlabels); + mln_concrete(I) output = level::transform(label, fl2l); + + trace::exiting("labeling::relabel"); + return output; + } + + + template <typename I, typename F> + inline + void + relabel_inplace(Image<I>& label, + mln_value(I)& nlabels, + const Function_l2b<F>& fl2b) + { + trace::entering("labeling::relabel"); + + // FIXME: we may want to check that it is exactly a label. + mlc_is_a(mln_value(I), mln::value::Symbolic)::check(); + mln_precondition(exact(label).has_data()); + + typedef fun::l2l::relabel<mln_value(I)> fl2l_t; + fl2l_t fl2l = make::relabelfun(fl2b, nlabels, nlabels); + level::transform_inplace(label, fl2l); + + trace::exiting("labeling::relabel"); + } + + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::labeling + +} // end of namespace mln + + +#endif // ! MLN_LABELING_RELABEL_HH diff --git a/milena/mln/make/relabelfun.hh b/milena/mln/make/relabelfun.hh new file mode 100644 index 0000000..d02dd88 --- /dev/null +++ b/milena/mln/make/relabelfun.hh @@ -0,0 +1,93 @@ +// 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 +// 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_MAKE_RELABELFUN_HH +# define MLN_MAKE_RELABELFUN_HH + +/// \file mln/make/relabelfun.hh +/// +/// Routines to construct a function in order to relabel a labeled image. + +# include <mln/core/concept/function.hh> +# include <mln/fun/l2l/relabel.hh> +# include <mln/value/label.hh> + +namespace mln +{ + + namespace make + { + + /// Create a l2l function from a l2b function. + /// This function can be used to relabel a labeled image. + /// + /// \param[in] f a l2b function. + /// + /// \return a l2l function. + /// + /// \sa mln::labeling::relabel + template <unsigned n, typename F> + mln::fun::l2l::relabel< value::label<n> > + relabelfun(const mln::Function_l2b<F>& fl2b, + const value::label<n>& nlabels); + + +# ifndef MLN_INCLUDE_ONLY + + template <unsigned n, typename F> + inline + mln::fun::l2l::relabel< value::label<n> > + relabelfun(const mln::Function_l2b<F>& fl2b_, + const value::label<n>& nlabels, + value::label<n>& new_nlabels) + { + trace::entering("mln::make::relabelfun"); + + const F& fl2b = exact(fl2b_); + + value::label<n> tmp_nlabels = literal::zero; + typedef value::label<n> label_t; + fun::l2l::relabel<label_t> fl2l(nlabels.next(), literal::zero); + for (label_t i = 1; i <= nlabels; ++i) + if (fl2b(i)) + { + fl2l(i) = i; + ++tmp_nlabels; + } + new_nlabels = tmp_nlabels; + trace::exiting("mln::make::relabelfun"); + return fl2l; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::make + +} // end of namespace mln + + +#endif // ! MLN_MAKE_RELABELFUN_HH diff --git a/milena/mln/value/label.hh b/milena/mln/value/label.hh index 7eb1be0..02eec94 100644 --- a/milena/mln/value/label.hh +++ b/milena/mln/value/label.hh @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// 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 @@ -28,10 +28,9 @@ #ifndef MLN_VALUE_LABEL_HH # define MLN_VALUE_LABEL_HH -/*! \file mln/value/label.hh - * - * \brief Define a generic class for labels. - */ +/// \file mln/value/label.hh +/// +/// Define a generic class for labels. # include <mln/metal/math/pow.hh> # include <mln/value/concept/symbolic.hh> @@ -44,11 +43,14 @@ namespace mln { - // Fwd decl. + // Forward declaration. namespace value { template <unsigned n> struct label; } + namespace literal { + struct zero_t; + } namespace trait @@ -59,6 +61,7 @@ namespace mln { private: typedef mln::value::label<n> self_; + public: enum { @@ -71,7 +74,7 @@ namespace mln typedef mln_value_quant_from_(card) quant; static const self_ min() { return 0; } - static const self_ max() { return card - 1; } + static const self_ max() { return mlc_pow_int(2, n) - 1; } }; } // end of namespace trait @@ -82,90 +85,70 @@ namespace mln { - /*! \brief Label value class. - * - * The parameter \c n is the number of encoding bits. - */ + /// Label value class. + /// + /// The parameter \c n is the number of encoding bits. + /// template <unsigned n> - struct label : public Symbolic< label<n> > + struct label + : public Symbolic< label<n> >, + public internal::value_like_< unsigned, // Equivalent. + typename internal::encoding_unsigned_<n>::ret, // Enc. + int, // Interoperation. + label<n> > // Exact. + { public: - /// Encoding associated type. typedef typename internal::encoding_unsigned_<n>::ret enc; - /// Equivalent associated type. - typedef typename internal::encoding_unsigned_<n>::ret equiv; - /// Constructor without argument. label(); /// Constructor from an (unsigned) integer. label(unsigned i); + /// Constructor from literal::zero. + label(const literal::zero_t& v); + + /// Conversion to an unsigned integer. + operator unsigned() const; + /// Assignment from an (unsigned) integer. label<n>& operator=(unsigned i); + /// Assignment from literal::zero. + label<n>& operator=(const literal::zero_t& v); + /// Self increment. label<n>& operator++(); /// Self decrement. label<n>& operator--(); + /// Return the next value. + label<n> next() const; + /// Conversion to unsigned. const enc& to_enc() const; - /// Unit value. - static const label<n> one; - protected: enc v_; }; - namespace internal - { - - template <unsigned n> - struct convert_< label<n> > - { - static label<n> value_at_index(unsigned i) - { - return i; - } - static unsigned index_of_value(const label<n>& v) - { - return v.to_enc(); - } - }; - - } // end of mln::value::internal - - - // Safety. template <> struct label<0>; template <> struct label<1>; - - /// Equality comparison. - template <unsigned n> - bool operator==(const label<n>& lhs, const label<n>& rhs); - - /// Ordering comparison. - template <unsigned n> - bool operator<(const label<n>& lhs, const label<n>& rhs); - - - - /*! \brief Print a label \p l into the output stream \p ostr. - * - * \param[in,out] ostr An output stream. - * \param[in] l A label. - * - * \return The modified output stream \p ostr. - */ + /// Print a label \p l into the output stream \p ostr. + /// + /// \param[in,out] ostr An output stream. + /// \param[in] l A label. + /// + /// \return The modified output stream \p ostr. + /// template <unsigned n> std::ostream& operator<<(std::ostream& ostr, const label<n>& l); @@ -182,12 +165,25 @@ namespace mln inline label<n>::label(unsigned i) { - mln_precondition(i <= mln_max(enc)); v_ = enc(i); } template <unsigned n> inline + label<n>::label(const literal::zero_t&) + { + v_ = 0; + } + + template <unsigned n> + inline + label<n>::operator unsigned() const + { + return to_enc(); + } + + template <unsigned n> + inline label<n>& label<n>::operator=(unsigned i) { @@ -199,6 +195,15 @@ namespace mln template <unsigned n> inline label<n>& + label<n>::operator=(const literal::zero_t&) + { + v_ = 0; + return *this; + } + + template <unsigned n> + inline + label<n>& label<n>::operator++() { mln_precondition(v_ < mln_max(enc)); @@ -217,28 +222,19 @@ namespace mln } template <unsigned n> - const label<n> label<n>::one = 1; - - template <unsigned n> inline - const mln_enc(label<n>)& - label<n>::to_enc() const + label<n> + label<n>::next() const { - return v_; + return label<n>(v_ + 1); } template <unsigned n> inline - bool operator==(const label<n>& lhs, const label<n>& rhs) - { - return lhs.to_enc() == rhs.to_enc(); - } - - template <unsigned n> - inline - bool operator<(const label<n>& lhs, const label<n>& rhs) + const mln_enc(label<n>)& + label<n>::to_enc() const { - return lhs.to_enc() < rhs.to_enc(); + return v_; } template <unsigned n> diff --git a/milena/mln/value/label_16.hh b/milena/mln/value/label_16.hh new file mode 100644 index 0000000..c7d4e13 --- /dev/null +++ b/milena/mln/value/label_16.hh @@ -0,0 +1,54 @@ +// 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 +// 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_VALUE_LABEL_16_HH +# define MLN_VALUE_LABEL_16_HH + +/// \file mln/value/label16.hh +/// +/// Define the alias value::label16. + +# include <mln/value/label.hh> + + +namespace mln +{ + + namespace value + { + + + /// Alias for 16-bit integers. + typedef label<16> label16; + + + } // end of namespace mln::value + +} // end of namespace mln + + +#endif // ! MLN_VALUE_LABEL_16_HH diff --git a/milena/mln/value/label_8.hh b/milena/mln/value/label_8.hh new file mode 100644 index 0000000..2a27179 --- /dev/null +++ b/milena/mln/value/label_8.hh @@ -0,0 +1,54 @@ +// 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 +// 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_VALUE_LABEL_8_HH +# define MLN_VALUE_LABEL_8_HH + +/// \file mln/value/label8.hh +/// +/// Define the alias value::label8. + +# include <mln/value/label.hh> + + +namespace mln +{ + + namespace value + { + + + /// Alias for 8-bit labels. + typedef mln::value::label<8> label8; + + + } // end of namespace mln::value + +} // end of namespace mln + + +#endif // ! MLN_VALUE_LABEL_8_HH diff --git a/milena/tests/labeling/Makefile.am b/milena/tests/labeling/Makefile.am index 399a1eb..044f83d 100644 --- a/milena/tests/labeling/Makefile.am +++ b/milena/tests/labeling/Makefile.am @@ -10,7 +10,8 @@ check_PROGRAMS = \ foreground \ level \ regional_maxima \ - regional_minima + regional_minima \ + relabel background_SOURCES = background.cc blobs_SOURCES = blobs.cc @@ -20,5 +21,6 @@ foreground_SOURCES = foreground.cc level_SOURCES = level.cc regional_maxima_SOURCES = regional_maxima.cc regional_minima_SOURCES = regional_minima.cc +relabel_SOURCES = relabel.cc TESTS = $(check_PROGRAMS) diff --git a/milena/tests/labeling/relabel.cc b/milena/tests/labeling/relabel.cc new file mode 100644 index 0000000..409ded7 --- /dev/null +++ b/milena/tests/labeling/relabel.cc @@ -0,0 +1,96 @@ +// 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 +// 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/relabel.cc +/// +/// Tests on mln::labeling::relabel. + + +#include <mln/core/image/image2d.hh> +#include <mln/labeling/relabel.hh> +#include <mln/value/label_16.hh> +#include <mln/debug/println.hh> + + +struct not_to_removed : public mln::Function_l2b< not_to_removed > +{ + bool operator()(const mln::value::label16& l) const + { + return l < mln::value::label16(3); + } +}; + + +bool is_valid(const mln::value::label16& l) +{ + return l == 0u|| l == 1u || l == 2u; +} + + + +int main() +{ + using namespace mln; + using value::label16; + + label16 vals[6][5] = { + {0, 1, 1, 0, 0}, + {0, 1, 1, 4, 0}, + {0, 0, 0, 0, 0}, + {2, 2, 0, 3, 0}, + {2, 5, 3, 3, 3}, + {2, 5, 5, 0, 0} + }; + + image2d<label16> lbl = make::image(vals); + label16 nlabels = 5; + + + { + label16 new_nlabels; + image2d<label16> lbl2 = labeling::relabel(lbl, + nlabels, + new_nlabels, + not_to_removed()); + mln_assertion(new_nlabels == 2u); + mln_piter_(image2d<label16>) p(lbl2.domain()); + for_all(p) + mln_assertion(is_valid(lbl2(p))); + } + + { + label16 new_nlabels; + labeling::relabel_inplace(lbl, + nlabels, + not_to_removed()); + mln_assertion(nlabels == 2u); + mln_piter_(image2d<label16>) p(lbl.domain()); + for_all(p) + mln_assertion(is_valid(lbl(p))); + } +} -- 1.5.6.5