
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add new morphological elementary operators. * tests/morpho/elementary/gradient.cc: New. * tests/morpho/elementary/closing.cc: New. * tests/morpho/elementary/gradient_external.cc: New. * tests/morpho/elementary/opening.cc: New. * tests/morpho/gradient_elementary.cc: Remove; obsolete. * tests/morpho/Makefile.am: Update. * mln/accu/min_max.hh (meta::min_max): Disambiguate. * mln/morpho/elementary/like_ero_fun.hh (f_accu): Make it consistent with others. * mln/morpho/elementary/dilation.hh (postcondition): New. * mln/morpho/dilation_elementary.hh: Remove; obsolete. * mln/morpho/elementary/gradient_internal.hh (val): Fix. (postcondition): New. * mln/morpho/elementary/gradient.hh: New. * mln/morpho/gradient_elementary.hh: Remove; obsolete. * mln/morpho/elementary/erosion.hh (postcondition): New. * mln/morpho/elementary/closing.hh: New. * mln/morpho/elementary/gradient_external.hh: New. * mln/morpho/elementary/opening.hh: New. mln/accu/min_max.hh | 2 mln/morpho/elementary/closing.hh | 44 ++++---- mln/morpho/elementary/dilation.hh | 1 mln/morpho/elementary/erosion.hh | 1 mln/morpho/elementary/gradient.hh | 141 ++++++++++++++++++++------- mln/morpho/elementary/gradient_external.hh | 36 +++--- mln/morpho/elementary/gradient_internal.hh | 3 mln/morpho/elementary/like_ero_fun.hh | 2 mln/morpho/elementary/opening.hh | 46 ++++---- tests/morpho/Makefile.am | 2 tests/morpho/elementary/closing.cc | 18 +-- tests/morpho/elementary/gradient.cc | 10 - tests/morpho/elementary/gradient_external.cc | 10 - tests/morpho/elementary/opening.cc | 18 +-- 14 files changed, 209 insertions(+), 125 deletions(-) Index: tests/morpho/elementary/gradient.cc --- tests/morpho/elementary/gradient.cc (revision 2713) +++ tests/morpho/elementary/gradient.cc (working copy) @@ -25,9 +25,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/morpho/elementary/gradient_internal.cc +/*! \file tests/morpho/elementary/gradient.cc * - * \brief Test on mln::morpho::elementary::gradient_internal. + * \brief Test on mln::morpho::elementary::gradient. */ #include <mln/core/image/image2d.hh> @@ -39,7 +39,7 @@ #include <mln/debug/iota.hh> #include <mln/debug/println.hh> -#include <mln/morpho/elementary/gradient_internal.hh> +#include <mln/morpho/elementary/gradient.hh> int main() @@ -57,7 +57,7 @@ { mln_VAR(gra, - morpho::elementary::gradient_internal(ima | b, c4())); + morpho::elementary::gradient(ima | b, c4())); debug::println(gra); } @@ -66,7 +66,7 @@ debug::println(msk); { mln_VAR(gra, - morpho::elementary::gradient_internal(msk | b, c4())); + morpho::elementary::gradient(msk | b, c4())); debug::println(gra); } Index: tests/morpho/elementary/closing.cc --- tests/morpho/elementary/closing.cc (revision 2713) +++ tests/morpho/elementary/closing.cc (working copy) @@ -25,9 +25,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/morpho/elementary/erosion.cc +/*! \file tests/morpho/elementary/closing.cc * - * \brief Test on mln::morpho::elementary::erosion. + * \brief Test on mln::morpho::elementary::closing. */ #include <mln/core/image/image2d.hh> @@ -37,7 +37,7 @@ #include <mln/debug/iota.hh> #include <mln/debug/println.hh> -#include <mln/morpho/elementary/erosion.hh> +#include <mln/morpho/elementary/closing.hh> int main() @@ -51,18 +51,18 @@ debug::iota(ima); debug::println(ima); { - image2d<int_u8> ero = morpho::elementary::erosion(ima, c4()); - mln_assertion(ero.border() == 1); - debug::println(ero); + image2d<int_u8> clo = morpho::elementary::closing(ima, c4()); + mln_assertion(clo.border() == 1); + debug::println(clo); } image2d<bool> msk(3, 3, 0); level::fill(msk, pw::value(ima) >= pw::cst(5)); debug::println(msk); { - image2d<bool> ero = morpho::elementary::erosion(msk, c4()); - mln_assertion(ero.border() == 1); - debug::println(ero); + image2d<bool> clo = morpho::elementary::closing(msk, c4()); + mln_assertion(clo.border() == 1); + debug::println(clo); } } Index: tests/morpho/elementary/gradient_external.cc --- tests/morpho/elementary/gradient_external.cc (revision 2713) +++ tests/morpho/elementary/gradient_external.cc (working copy) @@ -25,9 +25,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/morpho/elementary/gradient_internal.cc +/*! \file tests/morpho/elementary/gradient_external.cc * - * \brief Test on mln::morpho::elementary::gradient_internal. + * \brief Test on mln::morpho::elementary::gradient_external. */ #include <mln/core/image/image2d.hh> @@ -39,7 +39,7 @@ #include <mln/debug/iota.hh> #include <mln/debug/println.hh> -#include <mln/morpho/elementary/gradient_internal.hh> +#include <mln/morpho/elementary/gradient_external.hh> int main() @@ -57,7 +57,7 @@ { mln_VAR(gra, - morpho::elementary::gradient_internal(ima | b, c4())); + morpho::elementary::gradient_external(ima | b, c4())); debug::println(gra); } @@ -66,7 +66,7 @@ debug::println(msk); { mln_VAR(gra, - morpho::elementary::gradient_internal(msk | b, c4())); + morpho::elementary::gradient_external(msk | b, c4())); debug::println(gra); } Index: tests/morpho/elementary/opening.cc --- tests/morpho/elementary/opening.cc (revision 2713) +++ tests/morpho/elementary/opening.cc (working copy) @@ -25,9 +25,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/morpho/elementary/erosion.cc +/*! \file tests/morpho/elementary/opening.cc * - * \brief Test on mln::morpho::elementary::erosion. + * \brief Test on mln::morpho::elementary::opening. */ #include <mln/core/image/image2d.hh> @@ -37,7 +37,7 @@ #include <mln/debug/iota.hh> #include <mln/debug/println.hh> -#include <mln/morpho/elementary/erosion.hh> +#include <mln/morpho/elementary/opening.hh> int main() @@ -51,18 +51,18 @@ debug::iota(ima); debug::println(ima); { - image2d<int_u8> ero = morpho::elementary::erosion(ima, c4()); - mln_assertion(ero.border() == 1); - debug::println(ero); + image2d<int_u8> ope = morpho::elementary::opening(ima, c4()); + mln_assertion(ope.border() == 1); + debug::println(ope); } image2d<bool> msk(3, 3, 0); level::fill(msk, pw::value(ima) >= pw::cst(5)); debug::println(msk); { - image2d<bool> ero = morpho::elementary::erosion(msk, c4()); - mln_assertion(ero.border() == 1); - debug::println(ero); + image2d<bool> ope = morpho::elementary::opening(msk, c4()); + mln_assertion(ope.border() == 1); + debug::println(ope); } } Index: tests/morpho/Makefile.am --- tests/morpho/Makefile.am (revision 2714) +++ tests/morpho/Makefile.am (working copy) @@ -16,7 +16,6 @@ erosion \ erosion_min_h \ gradient \ - gradient_elementary \ graph_image_morpho \ graph_image_wst \ hit_or_miss \ @@ -51,7 +50,6 @@ contrast_SOURCES = contrast.cc gradient_SOURCES = gradient.cc -gradient_elementary_SOURCES = gradient_elementary.cc hit_or_miss_SOURCES = hit_or_miss.cc laplacian_SOURCES = laplacian.cc thinning_SOURCES = thinning.cc Index: mln/accu/min_max.hh --- mln/accu/min_max.hh (revision 2714) +++ mln/accu/min_max.hh (working copy) @@ -67,7 +67,7 @@ { // FIXME: Doc! - typedef pair<min,max> min_max; + typedef meta::pair<meta::min,meta::max> min_max; } // end of namespace mln::accu::meta Index: mln/morpho/elementary/like_ero_fun.hh --- mln/morpho/elementary/like_ero_fun.hh (revision 2714) +++ mln/morpho/elementary/like_ero_fun.hh (working copy) @@ -63,7 +63,7 @@ template <typename V, typename A> V operator()(const V& input_p, const A& a) const { - return a; + return a.to_result(); } }; Index: mln/morpho/elementary/dilation.hh --- mln/morpho/elementary/dilation.hh (revision 2714) +++ mln/morpho/elementary/dilation.hh (working copy) @@ -104,6 +104,7 @@ mln_concrete(I) output = internal::dilation_dispatch(input, nbh); + mln_postcondition(output >= input); trace::exiting("morpho::elementary::dilation"); return output; } Index: mln/morpho/elementary/gradient_internal.hh --- mln/morpho/elementary/gradient_internal.hh (revision 2714) +++ mln/morpho/elementary/gradient_internal.hh (working copy) @@ -82,7 +82,7 @@ { bool val[] = { - 0, // ext_value + 1, // ext_value 0, // do_clone 1, // on_input_p 0, // on_input_n @@ -115,6 +115,7 @@ mln_concrete(I) output = internal::gradient_internal_dispatch(input, nbh); + mln_postcondition(output <= input); trace::exiting("morpho::elementary::gradient_internal"); return output; } Index: mln/morpho/elementary/gradient.hh --- mln/morpho/elementary/gradient.hh (revision 2713) +++ mln/morpho/elementary/gradient.hh (working copy) @@ -25,15 +25,15 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH -# define MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH +#ifndef MLN_MORPHO_ELEMENTARY_GRADIENT_HH +# define MLN_MORPHO_ELEMENTARY_GRADIENT_HH -/// \file mln/morpho/elementary/gradient_internal.hh +/// \file mln/morpho/elementary/gradient.hh /// -/// \todo Fix the extension issue (see todo in like_ero_fun and _set). +/// \todo Add fastest versions (be careful about extension values...) -# include <mln/morpho/elementary/like_ero_fun.hh> -# include <mln/morpho/elementary/like_ero_set.hh> +# include <mln/morpho/includes.hh> +# include <mln/accu/min_max.hh> namespace mln @@ -48,7 +48,7 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal(const Image<I>& input, const Neighborhood<N>& nbh); + gradient(const Image<I>& input, const Neighborhood<N>& nbh); # ifndef MLN_INCLUDE_ONLY @@ -56,46 +56,121 @@ namespace internal { - struct f_grad_int + template <typename I, typename N> + void + gradient_tests(const Image<I>& input, const Neighborhood<N>& nbh) + { + mln_precondition(exact(input).has_data()); + // mln_precondition(exact(nbh).is_valid()); + } + + } // end of namespace mln::morpho::elementary::tests + + + namespace impl + { + + template <typename I, typename N> + mln_concrete(I) + gradient_on_function(const Image<I>& input_, const Neighborhood<N>& nbh_) + { + trace::entering("morpho::elementary::impl::gradient_on_function"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + internal::gradient_tests(input, nbh); + + accu::min_max<mln_value(I)> a; + + mln_concrete(I) output; + initialize(output, input); + + mln_piter(I) p(input.domain()); + mln_niter(N) n(nbh, p); + for_all(p) + { + a.init(); + for_all(n) if (input.domain().has(n)) + a.take(input(n)); + output(p) = a.second() - a.first(); + } + + trace::exiting("morpho::elementary::impl::gradient_on_function"); + return output; + } + + template <typename I, typename N> + mln_concrete(I) + gradient_on_set(const Image<I>& input_, const Neighborhood<N>& nbh_) + { + trace::entering("morpho::elementary::impl::gradient_on_set"); + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + internal::gradient_tests(input, nbh); + + mln_concrete(I) output; + initialize(output, input); + level::fill(output, false); + + mln_piter(I) p(input.domain()); + mln_niter(N) n(nbh, p); + for_all(p) + if (input(p) == true) { - template <typename V, typename A> - V operator()(const V& input_p, const A& a) const + for_all(n) if (input.domain().has(n)) + if (input(n) == false) { - return input_p - a.to_result(); + output(p) = true; + break; + } + } + else // input(p) == false + { + for_all(n) if (input.domain().has(n)) + if (input(n) == true) + { + output(p) = true; + break; + } } - }; + + trace::exiting("morpho::elementary::impl::gradient_on_set"); + return output; + } + + } // end of namespace mln::morpho::elementary::impl + + + namespace internal + { // Dispatch. template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(trait::image::kind::any, + gradient_dispatch(trait::image::kind::any, + trait::image::speed::any, const Image<I>& input, const Neighborhood<N>& nbh) { - return like_ero_fun(accu::meta::min(), f_grad_int(), input, nbh); + return impl::gradient_on_function(input, nbh); } template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(trait::image::kind::logic, + gradient_dispatch(trait::image::kind::logic, + trait::image::speed::any, const Image<I>& input, const Neighborhood<N>& nbh) { - bool val[] = - { - 0, // ext_value - 0, // do_clone - 1, // on_input_p - 0, // on_input_n - 1, // output_p - }; - return like_ero_set(val, input, nbh); + return impl::gradient_on_set(input, nbh); } template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(const Image<I>& input, const Neighborhood<N>& nbh) + gradient_dispatch(const Image<I>& input, const Neighborhood<N>& nbh) { - return gradient_internal_dispatch(mln_trait_image_kind(I)(), + return gradient_dispatch(mln_trait_image_kind(I)(), + mln_trait_image_speed(I)(), input, nbh); } @@ -106,16 +181,14 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal(const Image<I>& input, const Neighborhood<N>& nbh) + gradient(const Image<I>& input, const Neighborhood<N>& nbh) { - trace::entering("morpho::elementary::gradient_internal"); - - mln_precondition(exact(input).has_data()); - // mln_precondition(exact(nbh).is_valid()); + trace::entering("morpho::elementary::gradient"); - mln_concrete(I) output = internal::gradient_internal_dispatch(input, nbh); + internal::gradient_tests(input, nbh); + mln_concrete(I) output = internal::gradient_dispatch(input, nbh); - trace::exiting("morpho::elementary::gradient_internal"); + trace::exiting("morpho::elementary::gradient"); return output; } @@ -128,4 +201,4 @@ } // end of namespace mln -#endif // ! MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH +#endif // ! MLN_MORPHO_ELEMENTARY_GRADIENT_HH Index: mln/morpho/elementary/erosion.hh --- mln/morpho/elementary/erosion.hh (revision 2714) +++ mln/morpho/elementary/erosion.hh (working copy) @@ -104,6 +104,7 @@ mln_concrete(I) output = internal::erosion_dispatch(input, nbh); + mln_postcondition(output <= input); trace::exiting("morpho::elementary::erosion"); return output; } Index: mln/morpho/elementary/closing.hh --- mln/morpho/elementary/closing.hh (revision 2713) +++ mln/morpho/elementary/closing.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 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 @@ -25,15 +25,16 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MORPHO_CLOSING_HH -# define MLN_MORPHO_CLOSING_HH +#ifndef MLN_MORPHO_ELEMENTARY_CLOSING_HH +# define MLN_MORPHO_ELEMENTARY_CLOSING_HH -/*! \file mln/morpho/closing.hh +/*! \file mln/morpho/elementary/closing.hh * - * \brief Morphological closing. + * \brief Morphological elementary closing. */ -# include <mln/morpho/includes.hh> +# include <mln/morpho/elementary/erosion.hh> +# include <mln/morpho/elementary/dilation.hh> namespace mln @@ -42,36 +43,41 @@ namespace morpho { - /*! Morphological closing. - * - * This operator is e_{-B} o d_B. - */ - template <typename I, typename W> - mln_concrete(I) closing(const Image<I>& input, const Window<W>& win); + namespace elementary + { + + /// Morphological elementary closing. + /// + /// This operator is e o d. + template <typename I, typename N> + mln_concrete(I) closing(const Image<I>& input, const Neighborhood<N>& nbh); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W> + template <typename I, typename N> inline - mln_concrete(I) closing(const Image<I>& input, const Window<W>& win) + mln_concrete(I) closing(const Image<I>& input, const Neighborhood<N>& nbh) { - trace::entering("morpho::closing"); + trace::entering("morpho::elementary::closing"); + mln_precondition(exact(input).has_data()); - mln_precondition(! exact(win).is_empty()); + // mln_precondition(exact(nbh).is_valid()); - mln_concrete(I) output = erosion(dilation(input, win), win::sym(win)); + mln_concrete(I) output = erosion(dilation(input, nbh), nbh); mln_postcondition(output >= input); - trace::exiting("morpho::closing"); + trace::exiting("morpho::elementary::closing"); return output; } # endif // ! MLN_INCLUDE_ONLY + } // end of namespace mln::morpho::elementary + } // end of namespace mln::morpho } // end of namespace mln -#endif // ! MLN_MORPHO_CLOSING_HH +#endif // ! MLN_MORPHO_ELEMENTARY_CLOSING_HH Index: mln/morpho/elementary/gradient_external.hh --- mln/morpho/elementary/gradient_external.hh (revision 2713) +++ mln/morpho/elementary/gradient_external.hh (working copy) @@ -25,10 +25,10 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH -# define MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH +#ifndef MLN_MORPHO_ELEMENTARY_GRADIENT_EXTERNAL_HH +# define MLN_MORPHO_ELEMENTARY_GRADIENT_EXTERNAL_HH -/// \file mln/morpho/elementary/gradient_internal.hh +/// \file mln/morpho/elementary/gradient_external.hh /// /// \todo Fix the extension issue (see todo in like_ero_fun and _set). @@ -48,7 +48,7 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal(const Image<I>& input, const Neighborhood<N>& nbh); + gradient_external(const Image<I>& input, const Neighborhood<N>& nbh); # ifndef MLN_INCLUDE_ONLY @@ -56,12 +56,12 @@ namespace internal { - struct f_grad_int + struct f_grad_ext { template <typename V, typename A> V operator()(const V& input_p, const A& a) const { - return input_p - a.to_result(); + return a.to_result() - input_p; } }; @@ -69,23 +69,23 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(trait::image::kind::any, + gradient_external_dispatch(trait::image::kind::any, const Image<I>& input, const Neighborhood<N>& nbh) { - return like_ero_fun(accu::meta::min(), f_grad_int(), input, nbh); + return like_ero_fun(accu::meta::max(), f_grad_ext(), input, nbh); } template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(trait::image::kind::logic, + gradient_external_dispatch(trait::image::kind::logic, const Image<I>& input, const Neighborhood<N>& nbh) { bool val[] = { 0, // ext_value 0, // do_clone - 1, // on_input_p - 0, // on_input_n + 0, // on_input_p + 1, // on_input_n 1, // output_p }; return like_ero_set(val, input, nbh); @@ -93,9 +93,9 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal_dispatch(const Image<I>& input, const Neighborhood<N>& nbh) + gradient_external_dispatch(const Image<I>& input, const Neighborhood<N>& nbh) { - return gradient_internal_dispatch(mln_trait_image_kind(I)(), + return gradient_external_dispatch(mln_trait_image_kind(I)(), input, nbh); } @@ -106,16 +106,16 @@ template <typename I, typename N> mln_concrete(I) - gradient_internal(const Image<I>& input, const Neighborhood<N>& nbh) + gradient_external(const Image<I>& input, const Neighborhood<N>& nbh) { - trace::entering("morpho::elementary::gradient_internal"); + trace::entering("morpho::elementary::gradient_external"); mln_precondition(exact(input).has_data()); // mln_precondition(exact(nbh).is_valid()); - mln_concrete(I) output = internal::gradient_internal_dispatch(input, nbh); + mln_concrete(I) output = internal::gradient_external_dispatch(input, nbh); - trace::exiting("morpho::elementary::gradient_internal"); + trace::exiting("morpho::elementary::gradient_external"); return output; } @@ -128,4 +128,4 @@ } // end of namespace mln -#endif // ! MLN_MORPHO_ELEMENTARY_GRADIENT_INTERNAL_HH +#endif // ! MLN_MORPHO_ELEMENTARY_GRADIENT_EXTERNAL_HH Index: mln/morpho/elementary/opening.hh --- mln/morpho/elementary/opening.hh (revision 2713) +++ mln/morpho/elementary/opening.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 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 @@ -25,15 +25,16 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MORPHO_OPENING_HH -# define MLN_MORPHO_OPENING_HH +#ifndef MLN_MORPHO_ELEMENTARY_OPENING_HH +# define MLN_MORPHO_ELEMENTARY_OPENING_HH -/*! \file mln/morpho/opening.hh +/*! \file mln/morpho/elementary/opening.hh * - * \brief Morphological opening. + * \brief Morphological elementary opening. */ -# include <mln/morpho/includes.hh> +# include <mln/morpho/elementary/erosion.hh> +# include <mln/morpho/elementary/dilation.hh> namespace mln @@ -42,38 +43,41 @@ namespace morpho { - /*! Morphological opening. - * - * This operator is d_{-B} o e_B. - */ - template <typename I, typename W> - mln_concrete(I) opening(const Image<I>& input, const Window<W>& win); + namespace elementary + { + + /// Morphological elementary opening. + /// + /// This operator is d o e. + template <typename I, typename N> + mln_concrete(I) opening(const Image<I>& input, const Neighborhood<N>& nbh); # ifndef MLN_INCLUDE_ONLY - template <typename I, typename W> + template <typename I, typename N> inline - mln_concrete(I) opening(const Image<I>& input, const Window<W>& win) + mln_concrete(I) opening(const Image<I>& input, const Neighborhood<N>& nbh) { - trace::entering("morpho::opening"); + trace::entering("morpho::elementary::opening"); + mln_precondition(exact(input).has_data()); - mln_precondition(! exact(win).is_empty()); + // mln_precondition(exact(nbh).is_valid()); - mln_concrete(I) output = dilation(erosion(input, win), win::sym(win)); + mln_concrete(I) output = dilation(erosion(input, nbh), nbh); - // FIXME: Is this postcondition always true, even if the - // structuring element is not centered? mln_postcondition(output <= input); - trace::exiting("morpho::opening"); + trace::exiting("morpho::elementary::opening"); return output; } # endif // ! MLN_INCLUDE_ONLY + } // end of namespace mln::morpho::elementary + } // end of namespace mln::morpho } // end of namespace mln -#endif // ! MLN_MORPHO_OPENING_HH +#endif // ! MLN_MORPHO_ELEMENTARY_OPENING_HH