
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-02-23 Frederic Bour <bour@lrde.epita.fr> Work on meta-functions and overloading added.. * Makefile: . * accu_trait.hh: Remove. * accuprops.cc: Remove. * accuprops2.cc: Remove. * algebraic.cc: Remove. * closing_area.cc: Remove. * connected_filter.hh: Remove. * leveling.cc: Remove. * leveling_filter.hh: Remove. * mean.hh: Remove. * meantest.cc: Remove. * old/accu_trait.hh: New. * old/accuprops.cc: New. * old/accuprops2.cc: New. * old/algebraic.cc: New. * old/closing_area.cc: New. * old/connected_filter.hh: New. * old/leveling.cc: New. * old/leveling_filter.hh: New. * old/mean.hh: New. * old/meantest.cc: New. * old/p2p: New. * old/value_wrapper.hh: New. * old: New. * overload.cc: New. * p2p: Remove. * value_wrapper.hh: Remove. --- Makefile | 2 old/accu_trait.hh | 94 ++++++++++ old/accuprops.cc | 331 +++++++++++++++++++++++++++++++++++ old/accuprops2.cc | 380 +++++++++++++++++++++++++++++++++++++++++ old/algebraic.cc | 406 ++++++++++++++++++++++++++++++++++++++++++++ old/closing_area.cc | 50 +++++ old/connected_filter.hh | 123 +++++++++++++ old/leveling.cc | 47 +++++ old/leveling_filter.hh | 381 +++++++++++++++++++++++++++++++++++++++++ old/mean.hh | 202 +++++++++++++++++++++ old/meantest.cc | 21 ++ old/p2p/Makefile | 12 + old/p2p/compose_p2p.hh | 44 ++++ old/p2p/p2p_morpher.hh | 284 ++++++++++++++++++++++++++++++ old/p2p/symmetry_p2p.hh | 47 +++++ old/p2p/test_morph_image.cc | 62 ++++++ old/p2p/translate_p2p.hh | 43 ++++ old/value_wrapper.hh | 188 ++++++++++++++++++++ overload.cc | 283 ++++++++++++++++++++++++++++++ 19 files changed, 2999 insertions(+), 1 deletion(-) Index: trunk/milena/sandbox/fred/accuprops.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/meantest.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/accuprops2.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/connected_filter.hh (deleted) =================================================================== Index: trunk/milena/sandbox/fred/leveling_filter.hh (deleted) =================================================================== Index: trunk/milena/sandbox/fred/leveling.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/closing_area.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/value_wrapper.hh (deleted) =================================================================== Index: trunk/milena/sandbox/fred/accu_trait.hh (deleted) =================================================================== Index: trunk/milena/sandbox/fred/algebraic.cc (deleted) =================================================================== Index: trunk/milena/sandbox/fred/mean.hh (deleted) =================================================================== Index: trunk/milena/sandbox/fred/overload.cc =================================================================== --- trunk/milena/sandbox/fred/overload.cc (revision 0) +++ trunk/milena/sandbox/fred/overload.cc (revision 3415) @@ -0,0 +1,283 @@ +#include <mln/core/concept/function.hh> +#include <mln/core/concept/value.hh> +#include <mln/fun/internal/resolve.hh> +#include <mln/trait/op/plus.hh> + +// Avantage de cette methode: +// - la surcharge est rendue effectivement possible pour des familles de types +// et permet de passer en argument une fonction meme s'il existe de multiple definitions +// (^^ sic pour la qualite de l'explication ^^) +// - de maniere souple (set_previse_binary & set_binary). +// +// Inconvenients: +// - beaucoup de code/verbeux +// - necessite de reecrire la resolution a la main +// - l'implementation des differentes surcharge n'est pas aussi intuitive qu'en C++ +// naturel +// - passage par les categories. Impossible de tirer parti de la hierarchie +// "naturelle" des types en C++. +// + +// INF +namespace mln +{ + + // Forward declaration. + namespace fun { + namespace vv2v { + template <typename T> struct inf; + } + } + + + namespace trait + { + + // Default (whatever the category): + // "inf" performs a "min"! + template <template <class> class Category, typename T> + struct set_unary_< fun::vv2v::inf, Category, T > + { + typedef set_unary_< fun::vv2v::inf, Category, T > ret; + + static T exec(const T& t1, const T& t2) + { + return t1 < t2 ? t1 : t2; + } + + // In the case of a binary function with two different argument + // types, we shall instrument this definition with the result + // type... + }; + + } // mln::trait + + + + namespace fun + { + + namespace vv2v + { + + // fun::vv2v::inf<T> + + template <typename T> + struct inf : Function_vv2v< inf<T> > + { + typedef T result; + + typedef mln_fun_internal_resolve(inf) impl; + + T operator()(const T& t1, const T& t2) const + { + return impl::exec(t1, t2); + } + }; + + + // fun::vv2v::meta::inf + + namespace meta + { + + struct inf + { + + // A meta-fun can act as a function :-) + + template <typename T> + T operator()(const T& t1, const T& t2) const + // Here, we know the result type of vv2v::inf<T> so + // we explictly write it. + { + fun::vv2v::inf<T> f; + return f(t1, t2); + } + + // The "meta-fun -> fun" code is similar to the one in + // mln/accu/min.hh + template <typename T> + struct with + { + typedef fun::vv2v::inf<T> ret; + }; + }; + + } // mln::fun::vv2v::meta + + } // mln::fun::vv2v + + } // mln::fun + + // Yay! A special type equipped with a particular 'inf'. + + struct rgb : Value<rgb> + { + typedef rgb enc; + typedef rgb equiv; // Those couple of typedefs are required by the concept. + rgb() {} + rgb(int r, int g, int b) : r(r), g(g), b(b) {} + int r, g, b; + }; + + std::ostream& operator<<(std::ostream& ostr, const rgb& c) + { + ostr << c.r << ' ' << c.g << ' ' << c.b; + } + + namespace trait + { + + template <> + struct set_precise_unary_< fun::vv2v::inf, rgb > + { + typedef set_precise_unary_< fun::vv2v::inf, rgb > ret; + + static rgb exec(const rgb& c1, const rgb& c2) + { + // "Inf" is component-wise "min". + return rgb(c1.r < c2.r ? c1.r : c2.r, + c1.g < c2.g ? c1.g : c2.g, + c1.b < c2.b ? c1.b : c2.b); + } + }; + + } // mln::trait + +} // mln + +// PLUS +namespace mln +{ + + // Forward declaration. + namespace fun { + namespace vv2v { + template <typename L, typename R> struct plus; + } + } + + + namespace trait + { + + // Default (whatever the category): + // "inf" performs a "min"! + template <template <class> class Category_L, typename L, template <class> class Category_R, typename R> + struct set_binary_< fun::vv2v::plus, Category_L, L, Category_R, R> + { + typedef set_binary_< fun::vv2v::plus, Category_L, L, Category_R, R> ret; + + static mln_trait_op_plus(L,R) exec(const L& t1, const R& t2) + { + return t1 + t2; + } + + // In the case of a binary function with two different argument + // types, we shall instrument this definition with the result + // type... + }; + + } // mln::trait + + + + namespace fun + { + + namespace vv2v + { + + // fun::vv2v::plus<L,R> + + template <typename L, typename R> + struct plus : Function_vv2v< plus<L,R> > + { + typedef mln_trait_op_plus(L,R) result; + + typedef mln_fun_internal_resolve(plus) impl; + + result operator()(const L& t1, const R& t2) const + { + return impl::exec(t1, t2); + } + }; + + + // fun::vv2v::meta::plus + + namespace meta + { + + struct plus + { + + // A meta-fun can act as a function :-) + + template <typename L, typename R> + typename fun::vv2v::plus<L,R>::result operator()(const L& t1, const R& t2) const + // Here, we know the result type of vv2v::plus<L,R> so + // we explictly write it. + { + fun::vv2v::plus<L,R> f; + return f(t1, t2); + } + + // The "meta-fun -> fun" code is similar to the one in + // mln/accu/min.hh + template <typename L, typename R> + struct with + { + typedef fun::vv2v::plus<L,R> ret; + }; + }; + + } // mln::fun::vv2v::meta + + } // mln::fun::vv2v + + } // mln::fun + + namespace trait + { + + template <> + struct set_precise_binary_< fun::vv2v::plus, rgb, rgb > + { + typedef set_precise_binary_< fun::vv2v::plus, rgb, rgb > ret; + + static rgb exec(const rgb& c1, const rgb& c2) + { + // "Inf" is component-wise "min". + return rgb(c1.r + c2.r, + c1.g + c2.g, + c1.b + c2.b); + } + }; + + template <> + struct set_precise_binary_< mln::trait::op::plus, rgb, rgb > + { + typedef rgb ret; + }; + + } // mln::trait + +} // mln + +using namespace mln; + +int main() +{ + fun::vv2v::meta::inf inf; + std::cout << inf(3, 5) << std::endl; + + rgb c1(1, 2, 3), c2(2, 1, 2); + std::cout << inf(c1, c2) << std::endl; + + fun::vv2v::meta::plus plus; + std::cout << plus(plus(3.1f, 5), 3.1415926535) << std::endl; + + std::cout << plus(c1, c2) << std::endl; +} Index: trunk/milena/sandbox/fred/Makefile =================================================================== --- trunk/milena/sandbox/fred/Makefile (revision 3414) +++ trunk/milena/sandbox/fred/Makefile (revision 3415) @@ -1,4 +1,4 @@ -TARGET=connected +TARGET=overload OBJS=$(TARGET).o OLENADIR=../../.. Index: trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh =================================================================== --- trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/compose_p2p.hh (revision 3415) @@ -0,0 +1,44 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/macros.hh> +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> +#include <mln/core/var.hh> + +namespace mln +{ + + template <typename P, typename F, typename G> + class compose_t : public Function_p2p< compose_t<P, F, G> > + { + public: + typedef P result; + typedef compose_t<P, typename G::inverse, typename F::inverse> inverse; + + compose_t (const F& f, const G& g) + : f_ (f), g_ (g) {}; + + P operator() (const P& point) const + { + return (f_ (g_ (point))); + }; + + inverse inv () const + { + inverse comp(g_.inv (), f_.inv ()); + return comp; + }; + + private: + const F f_; + const G g_; + }; + + template <typename F, typename G> + compose_t<typename F::result, F, G> operator* (const Function_p2p< F >& f, + const Function_p2p< G >& g) + { + compose_t<typename F::result, F, G> comp (exact (f), exact (g)); + return comp; + } + +} \ No newline at end of file Index: trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh =================================================================== --- trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/symmetry_p2p.hh (revision 3415) @@ -0,0 +1,47 @@ +#include <mln/core/contract.hh> +#include <mln/core/image/image2d.hh> +#include <mln/core/macros.hh> +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> +#include <mln/core/var.hh> + +namespace mln +{ + + template <typename P> + class symmetry_t : public Function_p2p< symmetry_t<P> > + { + public: + typedef P result; + typedef symmetry_t<P> inverse; + + symmetry_t (unsigned dim) + : dim_ (dim) + { + mln_assertion(dim < P::dim); + }; + + P operator() (const P& point) const + { + P pt = point; + pt[dim_] = -pt[dim_]; + return pt; + }; + + inverse inv () const + { + return *this; + }; + + private: + const unsigned dim_; + }; + + template <typename P> + symmetry_t<P> flip (unsigned dim) + { + symmetry_t<P> f (dim); + return f; + } + +} \ No newline at end of file Index: trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc =================================================================== --- trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/test_morph_image.cc (revision 3415) @@ -0,0 +1,62 @@ +// 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/core/image/t_image.cc + * + * \brief Tests on mln::t_image. + */ + +#include <mln/core/image/image2d.hh> + +#include <mln/debug/iota.hh> +#include <mln/debug/println.hh> + +#include "trans_image.hh" +#include "translate_p2p.hh" +#include "symmetry_p2p.hh" +#include "compose_p2p.hh" + +#include <iostream> + +int main() +{ + using namespace mln; + + typedef image2d<int> I; + + I ima(2, 3); + debug::iota(ima); + debug::println(ima); + // translate(dpoint2d(2,2)) * + mln_VAR(tr, transform_image(ima, flip<I::site>(0) * translate(dpoint2d(2,2)) * flip<I::site>(1))); + debug::println(tr); + + std::cout << ima.domain () << " => " << tr.domain () << std::endl; + + // FIXME: Enrich this test (exercise more features and write + // assertions). +} Index: trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh =================================================================== --- trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/p2p_morpher.hh (revision 3415) @@ -0,0 +1,284 @@ +// Copyright (C) 2007, 2008, 2009 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_CORE_IMAGE_TRANS_IMAGE_HH +# define MLN_CORE_IMAGE_TRANS_IMAGE_HH + +/*! \file sandbox/fred/trans_image.hh + * + * \brief Definition of the "transformed" image class mln::trans_image. + */ + +# include <mln/core/internal/image_morpher.hh> +# include <mln/core/site_set/box.hh> +# include <mln/value/set.hh> +# include <mln/core/concept/function.hh> +# include <mln/accu/bbox.hh> + +namespace mln +{ + + // Fwd decl. + template <typename I, typename F> struct trans_image; + + namespace internal + { + + /// Data structure for \c mln::trans_image<I>. + template <typename I, typename F> + struct data< trans_image<I, F> > + { + /// \brief Build the data object held by a trans_image. + /// + /// \param ima The underlying image. + /// \param fun The underlying functor. + data(I& ima, const F& fun, const box<mln_psite(I)>& box); + + /// Underlying image. + I ima_; + /// Underlying transformation function. + // FIXME: do we need to conserve original transformation or just inverse ? + //F fun_; + typename F::inverse funinv_; + /// The bounding box of the morphed image. + box<mln_psite(I)> box_; + }; + + } // end of namespace mln::internal + + + /*! \brief Transformed image class. + * + * Applies an fun::p2p functor to coordinates of image pixels. + * + * \warning This class only works on images whose domain is a box. + * \warning Transformation function must transform domain to a + * domain with same cardinality. + * \warning You need to give the INVERSE of the desired transformation. + */ + template <typename I, typename F> + class trans_image + : public internal::image_morpher<I, mln_value(I), mln_pset(I), trans_image<I, F> > + { + public: + /// Super type. + typedef internal::image_morpher< I, mln_value(I), mln_pset(I), + trans_image<I, F> > super_; + + /// Point_Site associated type. + typedef mln_psite(I) psite; + + /// Value associated type. + typedef mln_value(I) value; + + /// Type returned by the read-write pixel value operator. + typedef mln_morpher_lvalue(I) lvalue; + + /// Return type of read-only access. + typedef mln_rvalue(I) rvalue; + + /// Skeleton. + typedef trans_image< tag::image_<I>, F > skeleton; + + public: + /// \brief Build a transformation of an image. + /// + /// The trans_image morpher allows to apply a p2p functor to every cell + /// of an image. + /// The functor \a fun must transform points so that transformed \a ima + /// image domain remains a box with same cardinality. + /// + /// \param ima The underlying image. + /// \param fun p2p functor to apply. + trans_image(I& ima, const F& fun); + + /// Initialize an empty image. + void init_(I& ima, const F& fun); + + /// Test if this image has been initialized. + bool is_valid() const; + + /// Test if a pixel value is accessible at \p p. + bool has(const mln_psite(I)& p) const; + + /// Give the definition domain. + const box<mln_psite(I)>& domain() const; + + /// Read-only access of pixel value at point site \p p. + mln_rvalue(I) operator()(const mln_psite(I)& p) const; + + /// Read-write access of pixel value at point site \p p. + mln_morpher_lvalue(I) operator()(const mln_psite(I)& p); + + + protected: + /// Transform \a p point through functor. + mln_psite(I) transform_(const mln_psite(I)& p) const; + box<mln_psite(I)> transform_(const box<mln_psite(I)>& p) const; + }; + +# ifndef MLN_INCLUDE_ONLY + + namespace internal + { + + // internal::data< trans_image<I,S> > + + template <typename I, typename F> + inline + data< trans_image<I, F> >::data(I& ima, const F& fun, const box<mln_psite(I)>& box) + : ima_ (ima), + // FIXME: do we need to conserve original transformation or just inverse ? + // fun_ (fun), + funinv_ (fun.inv ()), + box_ (box) + { + } + + } // end of namespace mln::internal + + + template <typename I, typename F> + inline + trans_image<I, F>::trans_image(I& ima, const F& fun) + { + init_(ima, fun); + } + + template <typename I, typename F> + inline + void + trans_image<I, F>::init_(I& ima, const F& fun) + { + typedef mln_psite(I) P; + mln_precondition(ima.is_valid()); + + /* FIXME: Add a precondition on the fact that the domain of ima is + a box. */ + + // Create transformed bounding box + accu::bbox<P> tbox; + + tbox.take_as_init (fun (ima.domain ().pmin ())); + tbox.take (fun (ima.domain ().pmax ())); + + this->data_ = new internal::data< trans_image<I, F> >(ima, fun, tbox); + } + + + template <typename I, typename F> + inline + bool trans_image<I, F>::is_valid() const + { + mln_invariant(this->delegatee_()->is_valid()); + return true; + } + + template <typename I, typename F> + inline + bool + trans_image<I, F>::has(const mln_psite(I)& p) const + { + mln_precondition(this->is_valid()); + return this->delegatee_()->has(transform_(p)); + } + + template <typename I, typename F> + inline + mln_psite(I) + trans_image<I, F>::transform_(const mln_psite(I)& p) const + { + return this->data_->funinv_(p); + } + + template <typename I, typename F> + inline + box<mln_psite(I)> + trans_image<I, F>::transform_(const box<mln_psite(I)>& p) const + { + typedef mln_psite(I) P; + + // Create transformed bounding box + accu::bbox<P> tbox; + + tbox.take_as_init (this->data_->funinv_ (this->data_->ima_.domain ().pmin ())); + tbox.take (this->data_->funinv_ (this->data_->ima_.domain ().pmax ())); + + return tbox; + } + + template <typename I, typename F> + inline + const box<mln_psite(I)>& + trans_image<I, F>::domain() const + { + mln_precondition(this->is_valid()); + return this->data_->box_; + } + + template <typename I, typename F> + inline + mln_rvalue(I) + trans_image<I, F>::operator()(const mln_psite(I)& p) const + { + mln_precondition(this->has(p)); + return (*this->delegatee_())(transform_(p)); + } + + template <typename I, typename F> + inline + mln_morpher_lvalue(I) + trans_image<I, F>::operator()(const mln_psite(I)& p) + { + mln_precondition(this->has(p)); + return (*this->delegatee_())(transform_(p)); + } + + template <typename I, typename F> + inline + trans_image<I, F> + transform_image(Image<I>& ima, const Function_p2p<F>& fun) + { + trans_image<I, F> tmp(exact(ima), exact(fun)); + return tmp; + } + + template <typename I, typename F> + inline + trans_image<const I, F> + transform_image(const Image<I>& ima, const Function_p2p<F>& fun) + { + trans_image<const I, F> tmp(exact(ima), exact(fun)); + return tmp; + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + +#endif // ! MLN_CORE_IMAGE_T_IMAGE_HH Index: trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh =================================================================== --- trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/translate_p2p.hh (revision 3415) @@ -0,0 +1,43 @@ +#include <mln/core/image/image2d.hh> +#include <mln/core/macros.hh> +#include <mln/core/alias/point2d.hh> +#include <mln/core/alias/dpoint2d.hh> +#include <mln/core/var.hh> + +namespace mln +{ + + template <typename P> + class translate_t : public Function_p2p< translate_t<P> > + { + public: + typedef P result; + typedef translate_t<P> inverse; + + translate_t (mln_delta(P) dp) + : dp_ (dp) {}; + + P operator() (const P& point) const + { + P pt = point; + return (pt + dp_); + }; + + inverse inv () const + { + translate_t<P> tmp(-dp_); + return tmp; + }; + + private: + const mln_delta(P) dp_; + }; + + template <typename D> + translate_t<mln_site(D)> translate (const Gdpoint<D>& delta) + { + translate_t<mln_site(D)> f (exact (delta)); + return f; + } + +} \ No newline at end of file Index: trunk/milena/sandbox/fred/old/p2p/Makefile =================================================================== --- trunk/milena/sandbox/fred/old/p2p/Makefile (revision 0) +++ trunk/milena/sandbox/fred/old/p2p/Makefile (revision 3415) @@ -0,0 +1,12 @@ +SRC=test_trans_image.cc +OBJ=${SRC:.cc=.o} +CXXFLAGS=-I ~/lrde/olena/trunk/milena + +all: $(OBJ) + g++ $< + +%.o: %cc + g++ $(CXXFLAGS) -o$@ $< + +clean: + rm -f *~ *.o a.out \ No newline at end of file Index: trunk/milena/sandbox/fred/old/accuprops.cc =================================================================== --- trunk/milena/sandbox/fred/old/accuprops.cc (revision 0) +++ trunk/milena/sandbox/fred/old/accuprops.cc (revision 3415) @@ -0,0 +1,331 @@ +# include <iostream> +# include <string> + +# include <mln/trait/undef.hh> +# include <mln/trait/image/props.hh> +# include <mln/trait/value_.hh> + +# include <mln/metal/bexpr.hh> +# include <mln/metal/equal.hh> +# include <mln/metal/if.hh> +# include <mln/metal/is_const.hh> + +# include <mln/core/concept/image.hh> +# include <mln/accu/all.hh> +# include <mln/util/pix.hh> +# include <mln/make/pix.hh> + +/// Shortcut to the accumulator property about untake method disponibility +# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake + +/// Shortcut to the accumulator property about setvalue method disponibility +# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue + +/// Shortcut to the accumulator property about stop method disponibility +# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop + +/// Shortcut to the accumulator property about behavior when pixel is given as take() value +/// Used for instance in mln::canvas::morpho::leveling +# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix + +namespace mln { + + namespace trait { + + namespace accu { + + // Basic accumulators properties + + struct has_untake + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_untake::no"; } }; + + struct yes : any { std::string name() const { return "has_untake::yes"; } }; + }; + + struct has_stop + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_stop::yes"; } }; + }; + + struct has_setvalue + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_setvalue::yes"; } }; + }; + + // Morphological accumulators properties + struct when_pix + { + struct any { protected: any() {}; }; + + struct use_v : any { std::string name() const { return "when_pix::use_v"; } }; + + struct use_p : any { std::string name() const { return "when_pix::use_p"; } }; + + struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } }; + + struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } }; + }; + + } // end of namespace mln::trait::accu + + template <typename A> + struct undefined_accu_ + { + // general + typedef undef has_untake; + typedef undef has_stop; + typedef undef has_setvalue; + + // morpho + typedef accu::when_pix::not_ok when_pix; + // FIXME: should default be undef ? + }; + + template <typename A> + struct accu_ : undefined_accu_<A> + { + }; + + } // end of namespace mln::trait + + namespace canvas { + + namespace morpho { + + namespace impl { + + namespace generic { + + template <typename I, template <typename P> class A> + inline + void + leveling(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + const I& ima = exact(input); + A< util::pix<I> >& a = exact(acc); + + mln_piter(I) p(ima.domain()); + + for_all(p) + a.take(mln::make::pix(ima, p)); + } + + } // end of namespace mln::canvas::morpho::impl::generic + + // fast implementation (only on values from pixter) + template <typename I, template <typename P> class A> + inline + void + leveling_fastest(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + const I& ima = exact(input); + A< util::pix<I> >& a = exact(acc); + + mln_pixter(const I) px(ima); + + for_all(px) + a.take(px.val()); + } + + } // end of namespace mln::canvas::morpho::impl + + namespace internal { + + template <typename I, typename A> + inline + void + leveling_dispatch(metal::false_, + const Image<I>& input, + Accumulator<A>& acc) + { + impl::generic::leveling(input, acc); + } + + template <typename I, typename A> + inline + void + leveling_dispatch(metal::true_, + const Image<I>& input, + Accumulator<A>& acc) + { + impl::leveling_fastest(input, acc); + } + + template <typename I, typename A> + inline + void + leveling_dispatch(const Image<I>& input, + Accumulator<A>& acc) + { + enum { + test = mlc_equal(mln_trait_image_speed(I), + trait::image::speed::fastest)::value + && + mlc_equal(mln_trait_accu_when_pix(A), + trait::accu::when_pix::use_v)::value + }; + internal::leveling_dispatch(metal::bool_<test>(), + input, acc); + } + + } // end of namespace mln::canvas::morpho::internal + + // Facade. + template <typename I, template <typename P> class A> + inline + void + leveling(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + internal::leveling_dispatch(input, acc); + } + + } // end of namespace mln::canvas::morpho + + } // end of namespace mln::canvas + + namespace morpho { + + namespace accu { + + namespace internal { + + template <typename V> + struct sum_handling_pixels + { typedef mln_sum(V) ret; }; + + template <typename I> + struct sum_handling_pixels< util::pix<I> > + { typedef mln_sum(mln_value(I)) ret; }; + + } // end of namespace mln::morpho::accu::internal + + template <typename T> + /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean. + /// FIXME: is inclusion polyphormism really appliable ? + struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>, + public Accumulator< mean<T> > + { + typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super; + typedef typename super::result result; + + using super::operator result; + using super::take; + + void take(const mean<T>& m); + }; + + template <typename I> + struct mean< util::pix<I> > : public mean< mln_value(I) >, + public Accumulator< mean< util::pix<I> > > + { + typedef mean< mln_value(I) > super; + typedef util::pix<I> argument; + typedef typename super::result result; + + using super::operator result; + using super::take; + + void take(const argument& t); + void take(const mean< util::pix<I> >& m); + }; + +# ifndef MLN_INCLUDE_ONLY + + template <typename T> + inline + void mean<T>::take(const mean<T>& m) + { + this->super::take(m); + } + + template <typename I> + inline + void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t) + { + this->mean< mln_value(I) >::take(t.v()); + } + + template <typename I> + inline + void mean< util::pix<I> >::take(const mean< util::pix<I> >& m) + { + this->super::take(m); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::accu + + } // end of namespace mln::morpho + + namespace trait { + + template <typename I> + struct accu_< morpho::accu::mean< util::pix<I> > > : + public undefined_accu_ < morpho::accu::mean< util::pix<I> > > + { + typedef accu::when_pix::use_v when_pix; + }; + + } // end of namespace mln::trait + +} // end of namespace mln + +# include <mln/accu/all.hh> +# include <mln/core/image/image2d.hh> + +# include <mln/debug/iota.hh> +# include <mln/debug/println.hh> +# include <mln/core/var.hh> +# include <mln/util/timer.hh> +int main() +{ + typedef mln::image2d<int> I; + + I ima(1000, 1000); + mln::morpho::accu::mean< mln::util::pix<I> > acc; + + float elapsed; + mln::util::timer chrono; + + mln::debug::iota(ima); + std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::leveling(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::impl::generic::leveling(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::impl::leveling_fastest(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl; +} Index: trunk/milena/sandbox/fred/old/meantest.cc =================================================================== --- trunk/milena/sandbox/fred/old/meantest.cc (revision 0) +++ trunk/milena/sandbox/fred/old/meantest.cc (revision 3415) @@ -0,0 +1,21 @@ +#include <iostream> +#include <mln/core/image/image2d.hh> +#include "mean.hh" + +int main() +{ + typedef mln::image2d<int> I; + mln::morpho::attribute::mean<I> m; + + m.take (2); + m.take (3); + m.take (4); + + std::cout << m.to_result () << std::endl; + + m.set_value (6); + m.take (3); + m.take (9); + + std::cout << m.to_result () << std::endl; +} Index: trunk/milena/sandbox/fred/old/accuprops2.cc =================================================================== --- trunk/milena/sandbox/fred/old/accuprops2.cc (revision 0) +++ trunk/milena/sandbox/fred/old/accuprops2.cc (revision 3415) @@ -0,0 +1,380 @@ +# include <iostream> +# include <string> + +# include <mln/trait/undef.hh> +# include <mln/trait/image/props.hh> +# include <mln/trait/value_.hh> + +# include <mln/metal/bexpr.hh> +# include <mln/metal/equal.hh> +# include <mln/metal/if.hh> +# include <mln/metal/is_const.hh> + +# include <mln/core/concept/image.hh> +# include <mln/accu/all.hh> +# include <mln/util/pix.hh> +# include <mln/make/pix.hh> + +/// Shortcut to the accumulator property about untake method disponibility +# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake + +/// Shortcut to the accumulator property about setvalue method disponibility +# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue + +/// Shortcut to the accumulator property about stop method disponibility +# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop + +/// Shortcut to the accumulator property about behavior when pixel is given as take() value +/// Used for instance in mln::canvas::morpho::leveling +# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix + +namespace mln { + + namespace trait { + + namespace accu { + + // Basic accumulators properties + + struct has_untake + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_untake::no"; } }; + + struct yes : any { std::string name() const { return "has_untake::yes"; } }; + }; + + struct has_stop + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_stop::yes"; } }; + }; + + struct has_setvalue + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_setvalue::yes"; } }; + }; + + // Morphological accumulators properties + struct when_pix + { + struct any { protected: any() {}; }; + + struct use_v : any { std::string name() const { return "when_pix::use_v"; } }; + + struct use_p : any { std::string name() const { return "when_pix::use_p"; } }; + + struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } }; + + struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } }; + }; + + } // end of namespace mln::trait::accu + + template <typename A> + struct undefined_accu_ + { + // general + typedef undef has_untake; + typedef undef has_stop; + typedef undef has_setvalue; + + // morpho + typedef accu::when_pix::not_ok when_pix; + // FIXME: should default be undef ? + }; + + template <typename A> + struct accu_ : undefined_accu_<A> + { + }; + + } // end of namespace mln::trait + + namespace canvas { + + namespace morpho { + + namespace impl { + + namespace generic { + + template <typename I, template <typename P> class A> + inline + void + leveling(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + const I& ima = exact(input); + A< util::pix<I> >& a = exact(acc); + + mln_piter(I) p(ima.domain()); + + for_all(p) + a.take(mln::make::pix(ima, p)); + } + + } // end of namespace mln::canvas::morpho::impl::generic + + // fast implementation (only on values from pixter) + template <typename I, template <typename P> class A> + inline + void + leveling_fastest(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + const I& ima = exact(input); + A< util::pix<I> >& a = exact(acc); + + mln_pixter(const I) px(ima); + + for_all(px) + a.take(px.val()); + } + + } // end of namespace mln::canvas::morpho::impl + + namespace internal { + + template <typename I, typename A> + inline + void + leveling_dispatch(metal::false_, + const Image<I>& input, + Accumulator<A>& acc) + { + impl::generic::leveling(input, acc); + } + + template <typename I, typename A> + inline + void + leveling_dispatch(metal::true_, + const Image<I>& input, + Accumulator<A>& acc) + { + impl::leveling_fastest(input, acc); + } + + template <typename I, typename A> + inline + void + leveling_dispatch(const Image<I>& input, + Accumulator<A>& acc) + { + enum { + test = mlc_equal(mln_trait_image_speed(I), + trait::image::speed::fastest)::value + && + mlc_equal(mln_trait_accu_when_pix(A), + trait::accu::when_pix::use_v)::value + }; + internal::leveling_dispatch(metal::bool_<test>(), + input, acc); + } + + } // end of namespace mln::canvas::morpho::internal + + // Facade. + template <typename I, template <typename P> class A> + inline + void + leveling(const Image<I>& input, + Accumulator< A< util::pix<I> > >& acc) + { + internal::leveling_dispatch(input, acc); + } + + } // end of namespace mln::canvas::morpho + + } // end of namespace mln::canvas + + namespace morpho { + + namespace accu { + + // MEAN ACCUMULATOR + namespace internal { + + template <typename V> + struct sum_handling_pixels + { typedef mln_sum(V) ret; }; + + template <typename I> + struct sum_handling_pixels< util::pix<I> > + { typedef mln_sum(mln_value(I)) ret; }; + + } // end of namespace mln::morpho::accu::internal + + template <typename T> + /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean. + /// FIXME: is inclusion polyphormism really appliable ? + struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>, + public Accumulator< mean<T> > + { + typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super; + + using super::operator typename super::result; + using super::take; + + void take(const mean<T>& m); + }; + + template <typename I> + struct mean< util::pix<I> > : public mean< mln_value(I) >, + public Accumulator< mean< util::pix<I> > > + { + typedef mean< mln_value(I) > super; + typedef util::pix<I> argument; + + using super::operator typename super::result; + using super::take; + + void take(const argument& t); + void take(const mean< util::pix<I> >& m); + }; + +# ifndef MLN_INCLUDE_ONLY + + template <typename T> + inline + void mean<T>::take(const mean<T>& m) + { + this->super::take(m); + } + + template <typename I> + inline + void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t) + { + this->mean< mln_value(I) >::take(t.v()); + } + + template <typename I> + inline + void mean< util::pix<I> >::take(const mean< util::pix<I> >& m) + { + this->super::take(m); + } + +# endif // ! MLN_INCLUDE_ONLY + + // FROM mln::accu:: TO mln::morpho::acu:: + + template <template <typename T> class A> + struct from_mln_accu + { + template <typename T> + struct ret; + + template <typename I> + struct ret< util::pix<I> > : public A< mln_value(I) >, + public Accumulator< ret< util::pix<I> > > + { + typedef A< mln_value(I) > super; + typedef typename super::result result; + + typedef util::pix<I> argument; + + using super::take; + + void take(const argument& t); + void take(const ret< util::pix<I> >& m); + }; + }; + +# ifndef MLN_INCLUDE_ONLY + + template <template <typename T> class A> + template <typename I> + inline + void from_mln_accu<A>::ret< util::pix<I> >::take(const from_mln_accu<A>::ret< util::pix<I> >& m) + { + this->super::take(m); + } + + template <template <typename T> class A> + template <typename I> + inline + void from_mln_accu<A>::ret< util::pix<I> >::take(const from_mln_accu<A>::ret< util::pix<I> >::argument& t) + { + this->A< mln_value(I) >::take(t.v()); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::accu + + } // end of namespace mln::morpho + + namespace trait { + + template <typename I> + struct accu_< morpho::accu::mean< util::pix<I> > > : + public undefined_accu_ < morpho::accu::mean< util::pix<I> > > + { + typedef accu::when_pix::use_v when_pix; + }; + + template <template <typename T> class A, typename I> + struct accu_< morpho::accu::from_mln_accu < A > :: ret < I > > + { + typedef accu::when_pix::use_v when_pix; + }; + } // end of namespace mln::trait + +} // end of namespace mln + +# include <mln/accu/all.hh> +# include <mln/core/image/image2d.hh> + +# include <mln/debug/iota.hh> +# include <mln/debug/println.hh> +# include <mln/core/var.hh> +# include <mln/util/timer.hh> +int main() +{ + using namespace mln; + typedef image2d<int> I; + + I ima(1000, 1000); + morpho::accu::from_mln_accu<accu::min>::ret<util::pix<I> > acc; + + float elapsed; + mln::util::timer chrono; + + debug::iota(ima); + std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::leveling(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::impl::generic::leveling(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl; + + acc.init(); + chrono.start(); + for (int i = 0; i < 50; i++) + mln::canvas::morpho::impl::leveling_fastest(ima, acc); + elapsed = chrono.stop(); + + std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl; +} Index: trunk/milena/sandbox/fred/old/connected_filter.hh =================================================================== --- trunk/milena/sandbox/fred/old/connected_filter.hh (revision 0) +++ trunk/milena/sandbox/fred/old/connected_filter.hh (revision 3415) @@ -0,0 +1,123 @@ +// Copyright (C) 2007, 2008, 2009 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_CANVAS_MORPHO_CONNECTED_FILTER_HH +# define MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH + +/// \file mln/canvas/morpho/connected_filter.hh +/// +/// Connected filters dispatch (algebraic & leveling filters). +/// + +# include "leveling_filter.hh" +# include <mln/canvas/morpho/algebraic_filter.hh> +# include <mln/trait/accumulators.hh> + +namespace mln { + namespace canvas { + namespace morpho { + + // Facade Fwd Declaration + template <typename I, typename N, typename A> + mln_concrete(I) + connected_filter(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, bool increasing); + +# ifndef MLN_INCLUDE_ONLY + + // Dispatch. + namespace internal + { + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + connected_filter_dispatch(mln::trait::accumulator::when_pix::use_none, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + return algebraic_filter_dispatch(input, nbh, a, lambda, increasing); + } + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + connected_filter_dispatch(mln::trait::accumulator::when_pix::use_p, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + return algebraic_filter_dispatch(input, nbh, a, lambda, increasing); + } + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + connected_filter_dispatch(mln::trait::accumulator::when_pix::use_v, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + return leveling_filter_dispatch(input, nbh, a, lambda, increasing); + } + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + connected_filter_dispatch(mln::trait::accumulator::when_pix::use_pix, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + return leveling_filter_dispatch(input, nbh, a, lambda, increasing); + } + + } // end of namespace mln::canvas::morpho::internal + + +# endif // ! MLN_INCLUDE_ONLY + + // Facade. + + template <typename I, typename N, typename A> + mln_concrete(I) + connected_filter(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, bool increasing) + { + return internal::connected_filter_dispatch(mln_trait_accu_when_pix(A)(), + input, nbh, a, lambda, increasing); + } + + + } // end of namespace mln::canvas::morpho + } // end of namespace mln::canvas +} // end of namespace mln + + +#endif // ! MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH Index: trunk/milena/sandbox/fred/old/leveling_filter.hh =================================================================== --- trunk/milena/sandbox/fred/old/leveling_filter.hh (revision 0) +++ trunk/milena/sandbox/fred/old/leveling_filter.hh (revision 3415) @@ -0,0 +1,381 @@ +// Copyright (C) 2007, 2008, 2009 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_CANVAS_MORPHO_LEVELING_FILTER_HH +# define MLN_CANVAS_MORPHO_LEVELING_FILTER_HH + +/// \file mln/canvas/morpho/leveling_filter.hh +/// +/// Apply leveling connected filter to images. +/// + +# include <mln/core/concept/image.hh> +# include <mln/core/concept/neighborhood.hh> +# include <mln/core/concept/accumulator.hh> + +# include <mln/data/fill.hh> +# include <mln/extension/adjust_fill.hh> + +# include <mln/level/sort_psites.hh> +# include <mln/level/sort_offsets.hh> + + + + +/*# include <mln/data/fill.hh> +# include <mln/literal/zero.hh> +# include <mln/convert/to_upper_window.hh> +# include <mln/extension/adjust_fill.hh> +# include <mln/util/pix.hh> +*/ + +namespace mln { + namespace canvas { + namespace morpho { + + // Facade Fwd Declaration + template <typename I, typename N, typename A> + mln_concrete(I) + leveling_filter(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing); + + +# ifndef MLN_INCLUDE_ONLY + + // Implementations. + + namespace impl { + + namespace generic { + + // Generic Version + + template <typename I> + static inline + mln_psite(I) + find_root(I& parent, const mln_psite(I) & x) + { + if (parent(x) == x) + return x; + else + return parent(x) = find_root(parent, parent(x)); + } + + template <typename I, typename N, typename S, typename A> + mln_concrete(I) + leveling_filter(const Image<I>& input_, const Neighborhood<N>& nbh_, + const Site_Set<S>& s_, + const Accumulator<A>& a_, const typename A::result& lambda) + { + trace::entering("canvas::morpho::impl::generic::leveling_filter"); + // FIXME: Test?! + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + const S& s = exact(s_); + (void)a_; // To avoid warning at compilation + + mln_concrete(I) output; + initialize(output, input); + + // Local type. + typedef mln_psite(I) P; + + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, bool) activity; + mln_ch_value(I, P) parent; + mln_ch_value(I, A) data; + + // Initialization. + { + initialize(deja_vu, input); + mln::data::fill(deja_vu, false); + initialize(activity, input); + mln::data::fill(activity, true); + initialize(parent, input); + initialize(data, input); + //a.init(); // init required. + } + + // First pass. + { + mln_fwd_piter(S) p(s); // s required. + mln_niter(N) n(nbh, p); + + for_all(p) + { + // Make set. + { + parent(p) = p; + data(p).take_as_init(make::pix(input, p)); + } + + for_all(n) + if (input.domain().has(n) && deja_vu(n)) + { + //do_union(n, p); + P r = find_root(parent, n); + if (r != p) + { + if (input(r) == input(p) || (activity(r) && (data(r) < lambda))) // Equiv(r, p) + // Either a flat zone or the component of r is still growing. + { + /* FIXME: Same remark as above concerning the + initialization of data(p); instead of + + data(p).take(data(r)); + + we should (or could) have + + unite_data(p, r); + + so as to keep the generic aspect of this canvas + (as long as the set of acceptable types for the + template parameter A is not bound). */ + data(p).take(data(r)); + parent(r) = p; + if (activity(r) == false) + activity(p) = false; + } + else + { + activity(p) = false; + } + } + } + deja_vu(p) = true; + } + } + + // Second pass. + { + mln_bkd_piter(S) p(s); + for_all(p) + if (parent(p) == p) // p is root. + output(p) = input(p); + else + output(p) = output(parent(p)); + } + + trace::exiting("canvas::morpho::impl::generic::leveling_filter"); + return output; + } + + } // end of namespace mln::canvas::morpho::impl::generic + + + // Fastest version. + + + template <typename I> + inline + unsigned + find_root_fastest(I& parent, unsigned x) + { + if (parent.element(x) == x) + return x; + else + return parent.element(x) = find_root_fastest(parent, parent.element(x)); + } + + template <typename I, typename N, typename A> + mln_concrete(I) + leveling_filter_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_, + const util::array<unsigned>& s, + const Accumulator<A>& a_, const typename A::result& lambda) + { + trace::entering("canvas::morpho::impl::leveling_fastest"); + + // FIXME: Tests? + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_concrete(I) output; + initialize(output, input); + + // Local type. + typedef mln_psite(I) P; + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, bool) activity; + mln_ch_value(I, unsigned) parent; + mln_ch_value(I, A) data; + + // Initialization. + { + initialize(deja_vu, input); + mln::data::fill(deja_vu, false); + initialize(activity, input); + mln::data::fill(activity, true); + initialize(parent, input); + mln::data::fill(parent, 0); + initialize(data, input); + } + + util::array<int> dp = offsets_wrt(input, nbh); + const unsigned n_nbhs = dp.nelements(); + const unsigned n_points = s.nelements(); + + // First pass. + { + + for (unsigned i = 0; i < n_points; ++i) + { + unsigned p = s[i]; // An offset. + + // Make set. + parent.element(p) = p; + data.element(p).take_as_init(input.element(p)); + + for (unsigned j = 0; j < n_nbhs; ++j) + { + unsigned n = p + dp[j]; + if (!deja_vu.element(n)) + continue; + + unsigned r = find_root_fastest(parent, n); + if (r != p) + { + if (input.element(r) == input.element(p) + || (activity.element(r) + && (data.element(r) < lambda))) + { + data.element(p).take(data.element(r)); + parent.element(r) = p; + if (activity.element(r) == false) + activity.element(p) = false; + } + else + activity.element(p) = false; + } + } + + deja_vu.element(p) = true; + } + + } + + // Second pass. + { + for (int i = n_points - 1; i >= 0 ; --i) + { + unsigned p = s[i]; + if (parent.element(p) == p) // p is root. + output.element(p) = input.element(p); + else + output.element(p) = output.element(parent.element(p)); + } + } + + trace::exiting("canvas::morpho::impl::leveling_fastest"); + return output; + } + + } // end of namespace mln::canvas::morpho::impl + + // Dispatch. + namespace internal + { + + // Leveling + template <typename I, typename N, typename A> + mln_concrete(I) + leveling_filter_dispatch(metal::false_, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + p_array < mln_psite(I) > s = + increasing ? + level::sort_psites_increasing(input) : + level::sort_psites_decreasing(input); + return impl::generic::leveling_filter(input, nbh, s, a, lambda); + } + + template <typename I, typename N, typename A> + mln_concrete(I) + leveling_filter_dispatch(metal::true_, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + util::array<unsigned> s = + increasing ? + level::sort_offsets_increasing(input) : + level::sort_offsets_decreasing(input); + return impl::leveling_filter_fastest(input, nbh, s, a, lambda); + } + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + leveling_filter_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, bool increasing) + { + enum + { + test = mlc_equal(mln_trait_image_speed(I), + trait::image::speed::fastest)::value + && mlc_equal(mln_trait_accumulator_when_pix(A), + trait::accumulator::when_pix::use_v)::value + && mln_is_simple_neighborhood(N)::value + }; + return leveling_filter_dispatch(metal::bool_<test>(), + input, nbh, a, lambda, increasing); + } + + } // end of namespace mln::canvas::morpho::internal + + +# endif // ! MLN_INCLUDE_ONLY + + + // Facade. + + template <typename I, typename N, typename A> + inline + mln_concrete(I) + leveling_filter(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, const typename A::result& lambda, + bool increasing) + { + //FIXME: Do we need to check input validity ? + return internal::leveling_filter_dispatch(input, nbh, a, lambda, increasing); + } + + } // end of namespace mln::canvas::morpho + } // end of namespace mln::canvas +} // end of namespace mln + + +#endif // ! MLN_CANVAS_MORPHO_LEVELING_FILTER_HH Index: trunk/milena/sandbox/fred/old/leveling.cc =================================================================== --- trunk/milena/sandbox/fred/old/leveling.cc (revision 0) +++ trunk/milena/sandbox/fred/old/leveling.cc (revision 3415) @@ -0,0 +1,47 @@ + + +#include <mln/core/image/image2d.hh> +#include <mln/io/pgm/all.hh> +#include <mln/util/timer.hh> +#include <mln/core/alias/neighb2d.hh> +#include "mean.hh" +#include "leveling_filter.hh" + +int main(int argc, char** argv) +{ + using namespace mln; + using value::int_u8; + + std::cout << "Leveling filter test" << std::endl; + + typedef mln::image2d<int_u8> I; + I lena; + + float elapsed; + mln::util::timer chrono; + mln::morpho::attribute::mean<I> c; + int lambda = atoi(argv[1]); + + mln::io::pgm::load(lena, "../../img/lena.pgm"); + I out; + + chrono.start(); + out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true); + elapsed = chrono.stop(); + std::cout << "(auto) " << elapsed << "s" << std::endl; + mln::io::pgm::save(out, "auto.pgm"); + + chrono.start(); + out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::true_(), lena, c4(), c, lambda, true); + elapsed = chrono.stop(); + std::cout << "(fast) " << elapsed << "s" << std::endl; + + mln::io::pgm::save(out, "fast.pgm"); + + chrono.start(); + out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::false_(), lena, c4(), c, lambda, true); + elapsed = chrono.stop(); + std::cout << "(slow) " << elapsed << "s" << std::endl; + + mln::io::pgm::save(out, "slow.pgm"); +} Index: trunk/milena/sandbox/fred/old/closing_area.cc =================================================================== --- trunk/milena/sandbox/fred/old/closing_area.cc (revision 0) +++ trunk/milena/sandbox/fred/old/closing_area.cc (revision 3415) @@ -0,0 +1,50 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/// \file tests/morpho/closing_area.cc +/// +/// Test on mln::morpho::closing_area. + +#include <mln/core/image/image2d.hh> +#include <mln/value/int_u8.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/morpho/closing_area.hh> + +int main(int argc, char **argv) +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> lena; + io::pgm::load(lena, "../../img/lena.pgm"); + io::pgm::save(morpho::closing_area(lena, c4(), atoi(argv[1])), "out.pgm"); +} Index: trunk/milena/sandbox/fred/old/value_wrapper.hh =================================================================== --- trunk/milena/sandbox/fred/old/value_wrapper.hh (revision 0) +++ trunk/milena/sandbox/fred/old/value_wrapper.hh (revision 3415) @@ -0,0 +1,188 @@ +// Copyright (C) 2007, 2008, 2009 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_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH +# define MLN_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH + +/// \file mln/morpho/attribute/volume.hh +/// +/// Transform an accumulator to a value (when_pix::use_v) accumulator. + +# include <mln/accu/internal/base.hh> +# include <mln/util/pix.hh> + +# define mln_morpho_attribute_use_v_(T) mln::morpho::attribute::value_wrapper< T > +# define mln_morpho_attribute_use_v(T) mln::morpho::attribute::value_wrapper< T > + +namespace mln +{ + + // Forward declaration. + namespace morpho { + namespace attribute { + template <typename T> class value_wrapper; + } + } + + + // Traits. + + namespace trait + { + + template <typename A> + struct accumulator_< morpho::attribute::value_wrapper<A> > + { + typedef accumulator::has_untake::no has_untake; + typedef accumulator::has_set_value::no has_set_value; + typedef accumulator::has_stop::no has_stop; + typedef accumulator::when_pix::use_v when_pix; + }; + + } // end of namespace mln::trait + + namespace morpho + { + + namespace attribute + { + + /// Value wrapper accumulator meta-class. + /// + /// The parameter \p A is the base accumulator to wrap. + template <typename A> + struct value_wrapper + : public mln::accu::internal::base< typename A::result , value_wrapper<A> > + { + typedef typename A::argument argument; + typedef typename A::result result; + + value_wrapper(); + + /// Manipulators. + /// \{ + void init(); + + void take(const argument& v); + template <typename I> + void take(const util::pix<I>& px); + void take(const value_wrapper<A>& other); + + void take_as_init(const argument& v); + template <typename I> + void take_as_init(const util::pix<I>& px); + /// \} + + /// Get the value of the accumulator. + result to_result() const; + + /// Check whether this accu is able to return a result. + bool is_valid() const; + + protected: + /// Delegatee accumulator. + A accu_; + }; + + +# ifndef MLN_INCLUDE_ONLY + + template <typename A> + value_wrapper<A>::value_wrapper() + : accu_() + { + } + + template <typename A> + void + value_wrapper<A>::init() + { + accu_.init(); + } + + template <typename A> + void + value_wrapper<A>::take(const argument& v) + { + accu_.take(v); + } + + template <typename A> + template <typename I> + void + value_wrapper<A>::take(const util::pix<I>& px) + { + take(px.v()); + } + + template <typename A> + void + value_wrapper<A>::take(const value_wrapper<A>& other) + { + accu_.take(other.accu_); + } + + template <typename A> + void + value_wrapper<A>::take_as_init(const argument& v) + { + accu_.take_as_init(v); + } + + template <typename A> + template <typename I> + void + value_wrapper<A>::take_as_init(const util::pix<I>& px) + { + accu_.take_as_init(px); + } + + template <typename A> + typename value_wrapper<A>::result + value_wrapper<A>::to_result() const + { + return accu_.to_result(); + } + + template <typename A> + bool + value_wrapper<A>::is_valid() const + { + return accu_.is_valid(); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::attribute + + } // end of namespace mln::morpho + +} // end of namespace mln + + +#endif // ! MLN_MORPHO_ATTRIBUTE_VALUE_WRAPPER_HH Index: trunk/milena/sandbox/fred/old/accu_trait.hh =================================================================== --- trunk/milena/sandbox/fred/old/accu_trait.hh (revision 0) +++ trunk/milena/sandbox/fred/old/accu_trait.hh (revision 3415) @@ -0,0 +1,94 @@ +#ifndef MLN_TRAIT_ACCU_HH +# define MLN_TRAIT_ACCU_HH + +# include <string> +# include <mln/trait/undef.hh> + +/// Shortcut to the accumulator property about untake method disponibility +# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake + +/// Shortcut to the accumulator property about setvalue method disponibility +# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue + +/// Shortcut to the accumulator property about stop method disponibility +# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop + +/// Shortcut to the accumulator property about behavior when pixel is given as take() value +/// Used for instance in mln::canvas::morpho::leveling +# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix + +namespace mln { + + namespace trait { + + namespace accu { + + // Basic accumulators properties + + struct has_untake + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_untake::no"; } }; + + struct yes : any { std::string name() const { return "has_untake::yes"; } }; + }; + + struct has_stop + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_stop::yes"; } }; + }; + + struct has_setvalue + { + struct any { protected: any() {}; }; + + struct no : any { std::string name() const { return "has_setvalue::no"; } }; + + struct yes : any { std::string name() const { return "has_setvalue::yes"; } }; + }; + + // Morphological accumulators properties + struct when_pix + { + struct any { protected: any() {}; }; + + struct use_only_v : any { std::string name() const { return "when_pix::use_only_v"; } }; + + struct use_only_p : any { std::string name() const { return "when_pix::use_only_p"; } }; + + struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } }; + + struct use_whatever : any { std::string name() const { return "when_pix::use_whatever"; } }; + + struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } }; + }; + + } // end of namespace mln::trait::accu + + template <typename A> + struct undefined_accu_ + { + // general + typedef undef has_untake; + typedef undef has_stop; + typedef undef has_setvalue; + + // morpho + typedef accu::when_pix::use_pix when_pix; + }; + + template <typename A> + struct accu_ : public undefined_accu_<A> + { + }; + + } // end of namespace mln::trait + +} // end of namespace mln + +#endif /* !MLN_TRAIT_ACCU_HH */ Index: trunk/milena/sandbox/fred/old/algebraic.cc =================================================================== --- trunk/milena/sandbox/fred/old/algebraic.cc (revision 0) +++ trunk/milena/sandbox/fred/old/algebraic.cc (revision 3415) @@ -0,0 +1,406 @@ +// Copyright (C) 2007, 2008, 2009 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_CANVAS_ALGEBRAIC_HH +# define MLN_CANVAS_ALGEBRAIC_HH + +/// \file mln/canvas/algebraic.hh +/// +/// Apply algebraic connected filter to images. +/// +/// \todo Test inputs validity. + +# include <mln/core/concept/image.hh> +# include <mln/data/fill.hh> +# include <mln/literal/zero.hh> +# include <mln/convert/to_upper_window.hh> +# include <mln/extension/adjust_fill.hh> + +# include <mln/level/sort_psites.hh> +# include <mln/level/sort_offsets.hh> +# include <mln/core/alias/neighb2d.hh> + +# include "../edwin/accu_trait.hh" +# include "../edwin/card.hh" + +namespace mln +{ + + namespace canvas + { + + template < typename I, typename N, typename A, typename L> + mln_concrete(I) + algebraic(const Image<I>& input, const Neighborhood<N>& nbh, + Accumulator<A>& a, L lambda, bool increasing); + +# ifndef MLN_INCLUDE_ONLY + + // Implementations. + + namespace impl + { + + namespace generic + { + + template <typename I> + static inline + mln_psite(I) + find_root(I& parent, const mln_psite(I) & x) + { + if (parent(x) == x) + return x; + else + return parent(x) = find_root(parent, parent(x)); + } + + template < typename I, typename N, typename S, typename A, typename L> + mln_concrete(I) + algebraic(const Image<I>& input_, const Neighborhood<N>& nbh_, + const Site_Set<S>& s_, const Accumulator<A>& a_, L lambda) + { + trace::entering("canvas::impl::generic::algebraic"); + + // FIXME: Test?! + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + const S& s = exact(s_); + //const A& a = exact(a_); + (void)a_; + // Local type. + typedef mln_psite(I) P; + + mln_concrete(I) output; + initialize(output, input); + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, bool) activity; + mln_ch_value(I, P) parent; + mln_ch_value(I, A) data; + + // Initialization. + { + initialize(deja_vu, input); + mln::data::fill(deja_vu, false); + initialize(activity, input); + mln::data::fill(activity, true); + initialize(parent, input); + initialize(data, input); +// a.init(); // init required. + } + + // First pass. + { + mln_fwd_piter(S) p(s); // s required. + mln_niter(N) n(nbh, p); + + for_all(p) + { + // Make set. + { + parent(p) = p; + data(p).take_as_init(p); + } + + for_all(n) + if (input.domain().has(n) && deja_vu(n)) + { + //do_union(n, p); + P r = find_root(parent, n); + if (r != p) + { + if (input(r) == input(p) || (activity(r) && (data(r) < lambda))) // Equiv(r, p) + // Either a flat zone or the component of r is still growing. + { + /* FIXME: Same remark as above concerning the + initialization of data(p); instead of + + data(p).take(data(r)); + + we should (or could) have + + unite_data(p, r); + + so as to keep the generic aspect of this canvas + (as long as the set of acceptable types for the + template parameter A is not bound). */ + data(p).take(data(r)); + parent(r) = p; + if (activity(r) == false) + activity(p) = false; + } + else + { + activity(p) = false; + } + } + } + deja_vu(p) = true; + } + } + + // Second pass. + { + mln_bkd_piter(S) p(s); + for_all(p) + if (parent(p) == p) // p is root. + output(p) = input(p); + else + output(p) = output(parent(p)); + } + + trace::exiting("canvas::morpho::impl::generic::algebraic"); + return output; + } + + } // end of namespace mln::canvas::impl::generic + + // Fastest version. + template <typename I> + inline + unsigned + find_root_fastest(I& parent, unsigned x) + { + if (parent.element(x) == x) + return x; + else + return parent.element(x) = find_root_fastest(parent, parent.element(x)); + } + + template < typename I, typename N, typename A, typename L> + mln_concrete(I) + algebraic_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_, + const util::array<unsigned>& s, const Accumulator<A>& a_, L lambda) + { + trace::entering("canvas::impl::algebraic_fastest"); + + // FIXME: Tests? + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + + mln_concrete(I) output; + initialize(output, input); + + // Local type. + typedef mln_psite(I) P; + + // Auxiliary data. + mln_ch_value(I, bool) deja_vu; + mln_ch_value(I, bool) activity; + mln_ch_value(I, unsigned) parent; + mln_ch_value(I, A) data; + + // Initialization. + { + initialize(deja_vu, input); + mln::data::fill(deja_vu, false); + initialize(activity, input); + mln::data::fill(activity, true); + initialize(parent, input); + mln::data::fill(parent, 0); + initialize(data, input); + } + + util::array<int> dp = offsets_wrt(input, nbh); + const unsigned n_nbhs = dp.nelements(); + const unsigned n_points = s.nelements(); + + // First pass. + { + + for (unsigned i = 0; i < n_points; ++i) + { + unsigned p = s[i]; // An offset. + + // Make set. + parent.element(p) = p; + data.element(p).take_as_init(); + + for (unsigned j = 0; j < n_nbhs; ++j) + { + unsigned n = p + dp[j]; + if (!deja_vu.element(n)) + continue; + + unsigned r = find_root_fastest(parent, n); + if (r != p) + { + if (input.element(r) == input.element(p) + || (activity.element(r) + && (data.element(r) < lambda))) + { + data.element(p).take(data.element(r)); + parent.element(r) = p; + if (activity.element(r) == false) + activity.element(p) = false; + } + else + activity.element(p) = false; + } + } + + deja_vu.element(p) = true; + } + + } + + // Second pass. + { + for (int i = n_points - 1; i >= 0 ; --i) + { + unsigned p = s[i]; + if (parent.element(p) == p) // p is root. + output.element(p) = input.element(p); + else + output.element(p) = output.element(parent.element(p)); + } + } + + trace::exiting("canvas::impl::algebraic_fastest"); + return output; + } + + } // end of namespace mln::canvas::impl + + // Dispatch. + namespace internal + { + + // Algebraic + template < typename I, typename N, typename A, typename L> + mln_concrete(I) + algebraic_dispatch(metal::false_, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, L lambda, bool increasing) + { + p_array < mln_psite(I) > s = + increasing ? + level::sort_psites_increasing(input) : + level::sort_psites_decreasing(input); + return impl::generic::algebraic(input, nbh, s, a, lambda); + } + + template < typename I, typename N, typename A, typename L> + mln_concrete(I) + algebraic_dispatch(metal::true_, + const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, L lambda, bool increasing) + { + util::array<unsigned> s = + increasing ? + level::sort_offsets_increasing(input) : + level::sort_offsets_decreasing(input); + return impl::algebraic_fastest(input, nbh, s, a, lambda); + } + + template < typename I, typename N, typename A, typename L> + inline + mln_concrete(I) + algebraic_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, L lambda, bool increasing) + { + enum + { + test = mlc_equal(mln_trait_image_speed(I), + trait::image::speed::fastest)::value + && mlc_equal(mln_trait_accu_when_pix(A), + trait::accu::when_pix::use_whatever)::value + && mln_is_simple_neighborhood(N)::value + }; + return algebraic_dispatch(metal::bool_<test>(), + input, nbh, a, lambda, increasing); + } + + + } // end of namespace mln::canvas::internal + + // Facades. + template < typename I, typename N, typename A, typename L> + inline + mln_concrete(I) + algebraic(const Image<I>& input, const Neighborhood<N>& nbh, + const Accumulator<A>& a, L lambda, bool increasing) + { +// FIXME: Do we need to check input validity ? + return internal::algebraic_dispatch(input, nbh, a, lambda, increasing); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::canvas + +} // end of namespace mln + + +#endif // ! MLN_CANVAS_ALGEBRAIC_HH + +#include <mln/core/image/image2d.hh> +#include <mln/io/pgm/all.hh> +#include <mln/util/timer.hh> + +int main(int argc, char **argv) +{ + using namespace mln; + using value::int_u8; + + std::cout << "Algebraic filter test, reference: closing_area" << std::endl; + + typedef mln::image2d<int_u8> I; + I lena; + + float elapsed; + mln::util::timer chrono; + + mln::io::pgm::load(lena, "../../img/lena.pgm"); + I out; + int lambda = atoi(argv[1]); + + chrono.start(); + out = mln::canvas::algebraic (lena, c4(), mln::morpho::accu::card<I>(), lambda, true); + elapsed = chrono.stop(); + std::cout << "(auto) " << elapsed << "s" << std::endl; + mln::io::pgm::save(out, "auto.pgm"); + + chrono.start(); + out = mln::canvas::internal::algebraic_dispatch(mln::metal::true_(), lena, c4(), mln::morpho::accu::card<I>(), lambda, true); + elapsed = chrono.stop(); + std::cout << "(fast) " << elapsed << "s" << std::endl; + + mln::io::pgm::save(out, "fast.pgm"); + + chrono.start(); + out = mln::canvas::internal::algebraic_dispatch(mln::metal::false_(), lena, c4(), mln::morpho::accu::card<I>(), lambda, true); + elapsed = chrono.stop(); + std::cout << "(slow) " << elapsed << "s" << std::endl; + + mln::io::pgm::save(out, "slow.pgm"); +} \ No newline at end of file Index: trunk/milena/sandbox/fred/old/mean.hh =================================================================== --- trunk/milena/sandbox/fred/old/mean.hh (revision 0) +++ trunk/milena/sandbox/fred/old/mean.hh (revision 3415) @@ -0,0 +1,202 @@ +// Copyright (C) 2007, 2008, 2009 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_MORPHO_ATTRIBUTE_MEAN_HH +# define MLN_MORPHO_ATTRIBUTE_MEAN_HH + +/// \file mln/morpho/attribute/mean.hh +/// +/// Define an accumulator that computes the mean of a +/// component. +/// + +# include <mln/accu/internal/base.hh> +# include <mln/accu/mean.hh> +# include <mln/util/pix.hh> + +namespace mln { + + // Forward declaration. + + namespace morpho { + namespace attribute { + template <typename I> class mean; + } + } + + // Traits + + namespace trait { + template <typename I> + struct accumulator_< morpho::attribute::mean<I> > + { + typedef accumulator::has_untake::no has_untake; + typedef accumulator::has_set_value::yes has_set_value; + typedef accumulator::has_stop::no has_stop; + typedef accumulator::when_pix::use_v when_pix; + }; + } + + + namespace morpho { + + namespace attribute { + + namespace internal { + + template <typename T, typename S> + struct sum_set_value : public mln::accu::sum<T, S> + { + void set_value(const S& s); + }; + + } + + /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean. + /// Valid for leveling algorithm. + template <typename I> + class mean: public mln::accu::internal::base<mln_sum(mln_value(I)), mean<I> > + { + public: + typedef util::pix<I> argument; + typedef mln_value(I) value; + typedef mln_sum(value) result; + + mean(); + + /// Manipulators. + /// \{ + void init(); + void take(const value& v); + void take(const argument& t); + void take(const mean<I>& other); + + void set_value(const result& r); + /// \} + + /// Get the value of the accumulator. + result to_result() const; + + /// Check whether this accu is able to return a result. + /// Always true here. + bool is_valid() const; + + protected: + + accu::count<value> count_; + internal::sum_set_value<value,result> sum_; + }; + +# ifndef MLN_INCLUDE_ONLY + + namespace internal { + + template <typename T, typename S> + void + sum_set_value<T, S>::set_value(const S& s) + { + this->s_ = s; + }; + + } + + template <typename I> + inline + mean<I>::mean() + { + init(); + } + + template <typename I> + inline + void + mean<I>::init() + { + count_.init(); + sum_.init(); + } + + template <typename I> + inline + void + mean<I>::take(const value& t) + { + count_.take(t); + sum_.take(t); + } + + template <typename I> + inline + void + mean<I>::take(const argument& t) + { + take(t.v()); + } + + template <typename I> + inline + void + mean<I>::take(const mean<I>& other) + { + count_.take(other.count_); + sum_.take(other.sum_); + } + + template <typename I> + void + mean<I>::set_value(const result& r) + { + sum_.set_value(r * count_.to_result()); + }; + + template <typename I> + inline + typename mean<I>::result + mean<I>::to_result() const + { + unsigned n = count_.to_result(); + return sum_.to_result() / n; + } + + template <typename I> + inline + bool + mean<I>::is_valid() const + { + return count_.to_result() != 0; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho::attribute + + } // end of namespace mln::morpho + +} // end of namespace mln + +#endif /* ! MLN_MORPHO_ATTRIBUTE_MEAN_HH */