1059: Add morphological top-hats and contrast.

https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add morphological top-hats and contrast. * tests/morpho_gradient.cc: Fix doc. * mln/geom/pmin_pmax.hh (pmin_pmax): Overload for point set. * mln/geom/bbox.hh: Update. * mln/morpho/includes.hh (include): Add mln/test/positive.hh and mln/arith/plus.hh. * mln/morpho/gradient.hh: Add commentaries. * tests/morpho_contrast.cc: New. * mln/morpho/contrast.hh: New. * mln/morpho/top_hat.hh: New. mln/geom/bbox.hh | 3 - mln/geom/pmin_pmax.hh | 91 ++++++++++++++++++++++++++---- mln/morpho/contrast.hh | 82 +++++++++++++++++++++++++++ mln/morpho/gradient.hh | 21 +++---- mln/morpho/includes.hh | 3 + mln/morpho/top_hat.hh | 138 +++++++++++++++++++++++++++++++++++++++++++++++ tests/morpho_contrast.cc | 61 ++++++++++++++++++++ tests/morpho_gradient.cc | 4 - 8 files changed, 373 insertions(+), 30 deletions(-) Index: tests/morpho_gradient.cc --- tests/morpho_gradient.cc (revision 1058) +++ tests/morpho_gradient.cc (working copy) @@ -25,9 +25,9 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/erosion.cc +/*! \file tests/morpho_gradient.cc * - * \brief Test on mln::morpho::erosion. + * \brief Test on mln::morpho::gradient. */ #include <mln/core/image2d_b.hh> Index: tests/morpho_contrast.cc --- tests/morpho_contrast.cc (revision 0) +++ tests/morpho_contrast.cc (revision 0) @@ -0,0 +1,61 @@ +// 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/morpho_contrast.cc + * + * \brief Test on mln::morpho::contrast. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/core/win/rectangle2d.hh> + +#include <mln/io/load_pgm.hh> +#include <mln/io/save_pgm.hh> + +#include <mln/value/int_u8.hh> +#include <mln/morpho/contrast.hh> +#include <mln/level/saturate.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + win::rectangle2d rect(5, 5); + border::thickness = 2; + + image2d_b<int_u8> + lena = io::load_pgm("../img/tiny.pgm"), + out(lena.domain()); + + image2d_b<int> tmp(lena.domain()); + morpho::contrast(lena, rect, tmp); + + level::saturate(tmp, out); + io::save_pgm(out, "out.pgm"); +} Index: mln/geom/pmin_pmax.hh --- mln/geom/pmin_pmax.hh (revision 1058) +++ mln/geom/pmin_pmax.hh (working copy) @@ -36,6 +36,10 @@ # include <utility> +# include <mln/core/concept/point_set.hh> +# include <mln/core/concept/box.hh> + + namespace mln { @@ -44,6 +48,19 @@ { + /// Compute the minimum and maximum points of point set \p s. + template <typename S> + std::pair<mln_point(S), mln_point(S)> + pmin_pmax(const Point_Set<S>& s); + + + /// Compute the minimum and maximum points, \p pmin and \p max, + /// of point set \p s. + template <typename S> + void + pmin_pmax(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax); + + /// Compute the minimum and maximum points when browsing with /// iterator \p p. template <typename I> @@ -61,40 +78,86 @@ # ifndef MLN_INCLUDE_ONLY + + // Versions with point iterator. + template <typename I> - std::pair<mln_point(I), mln_point(I)> - pmin_pmax(Point_Iterator<I>& p_) + void + pmin_pmax(const Point_Iterator<I>& p_, mln_point(I)& pmin, mln_point(I)& pmax) { - I& p = exact(p_); - - typedef mln_point(I) P; - std::pair<P, P> tmp; - P& pmin = tmp.first; - P& pmax = tmp.second; + I p = exact(p_); // a copy of p_ // init with first point p.start(); + mln_precondition(p.is_valid()); pmin = pmax = p; // update with remaining points + typedef mln_point(I) P; for_all_remaining(p) for (unsigned i = 0; i < P::dim; ++i) if (p[i] < pmin[i]) pmin[i] = p[i]; else if (p[i] > pmax[i]) pmax[i] = p[i]; + } + template <typename I> + std::pair<mln_point(I), mln_point(I)> + pmin_pmax(const Point_Iterator<I>& p) + { + typedef mln_point(I) P; + std::pair<P, P> tmp; + pmin_pmax(p, tmp.first, tmp.second); // calls the previous version return tmp; } - template <typename I> + + // Versions with point set. + + namespace impl + { + + // General case. + + template <typename S> void - pmin_pmax(const Point_Iterator<I>& p, mln_point(I)& pmin, mln_point(I)& pmax) + pmin_pmax_(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax) { - typedef mln_point(I) P; - std::pair<P, P> tmp = pmin_pmax(p); - pmin = tmp.first; - pmax = tmp.second; + mln_piter(S) it(exact(s)); + pmin_pmax(it, pmin, pmax); + } + + // Box. + + template <typename B> + void + pmin_pmax_(const Box<B>& b, mln_point(B)& pmin, mln_point(B)& pmax) + { + pmin = exact(b).pmin(); + pmax = exact(b).pmax(); + } + + } // end of namespace mln::geom::impl + + + template <typename S> + void + pmin_pmax(const Point_Set<S>& s, mln_point(S)& pmin, mln_point(S)& pmax) + { + mln_precondition(exact(s).npoints() != 0); + impl::pmin_pmax_(exact(s), pmin, pmax); + } + + template <typename S> + std::pair<mln_point(S), mln_point(S)> + pmin_pmax(const Point_Set<S>& s) + { + mln_precondition(exact(s).npoints() != 0); + typedef mln_point(S) P; + std::pair<P, P> tmp; + pmin_pmax(p_, tmp.first, tmp.second); // calls the previous version + return tmp; } # endif // ! MLN_INCLUDE_ONLY Index: mln/geom/bbox.hh --- mln/geom/bbox.hh (revision 1058) +++ mln/geom/bbox.hh (working copy) @@ -100,8 +100,7 @@ mln_precondition(pset.npoints() != 0); typedef mln_point(S) P; - mln_piter(S) p(pset); - std::pair<P, P> pp = geom::pmin_pmax(p); + std::pair<P, P> pp = geom::pmin_pmax(pset); box_<P> tmp(pp.first, pp.second); // FIXME: mln_postcondition(tmp <= pset.bbox()); Index: mln/morpho/includes.hh --- mln/morpho/includes.hh (revision 1058) +++ mln/morpho/includes.hh (working copy) @@ -40,11 +40,14 @@ # include <mln/accu/min.hh> # include <mln/accu/max.hh> +# include <mln/arith/plus.hh> # include <mln/arith/minus.hh> # include <mln/level/compare.hh> # include <mln/level/fill.hh> +# include <mln/test/positive.hh> + # include <mln/border/resize.hh> # include <mln/border/fill.hh> Index: mln/morpho/gradient.hh --- mln/morpho/gradient.hh (revision 1058) +++ mln/morpho/gradient.hh (working copy) @@ -31,10 +31,11 @@ /*! \file mln/morpho/gradient.hh * * \brief Morphological gradient. + * + * \todo Save memory. */ # include <mln/morpho/includes.hh> -# include <mln/test/positive.hh> namespace mln @@ -82,11 +83,10 @@ mln_precondition(output.domain() = input.domain()); mln_precondition(! win.is_empty()); + dilation(input, win, output); // output = dilation O temp(input.domain()); - erosion(input, win, temp); - - dilation(input, win, output); - arith::minus_inplace(output, temp); + erosion(input, win, temp); // temp = erosion + arith::minus_inplace(output, temp); // now output = dilation - erosion mln_postcondition(test::positive(output)); } @@ -103,9 +103,8 @@ mln_precondition(! win.is_empty()); O temp(input.domain()); - erosion(input, win, temp); - - arith::minus(input, temp, output); + erosion(input, win, temp); // temp = erosion + arith::minus(input, temp, output); // output = input - erosion mln_postcondition(test::positive(output)); } @@ -121,10 +120,8 @@ mln_precondition(output.domain() = input.domain()); mln_precondition(! win.is_empty()); - O temp(input.domain()); - dilation(input, win, temp); - - arith::minus(temp, input, output); + dilation(input, win, output); // output = dilation + arith::minus_inplace(output, input); // now output = dilation - input mln_postcondition(test::positive(output)); } Index: mln/morpho/contrast.hh --- mln/morpho/contrast.hh (revision 0) +++ mln/morpho/contrast.hh (revision 0) @@ -0,0 +1,82 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_MORPHO_CONTRAST_HH +# define MLN_MORPHO_CONTRAST_HH + +/*! \file mln/morpho/contrast.hh + * + * \brief Morphological contrast operator (based on top-hats). + * + * \todo Save memory. + */ + +# include <mln/morpho/top_hat.hh> + + +namespace mln +{ + + namespace morpho + { + + /*! Morphological contrast operator (based on top-hats). + * + * This operator is Id + wth_B - bth_B. + */ + template <typename I, typename W, typename O> + void contrast(const Image<I>& input, const Window<W>& win, + Image<O>& output); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I, typename W, typename O> + void contrast(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + { + const I& input = exact(input_); + const W& win = exact(win_); + O& output = exact(output_); + + mln_precondition(output.domain() = input.domain()); + mln_precondition(! win.is_empty()); + + top_hat_white(input, win, output); // output = wth + arith::plus_inplace(output, input); // now output = wth + input + O temp(input.domain()); + top_hat_black(input, win, temp); // temp = bth + arith::minus_inplace(output, temp); // now output = wth + input - bth + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho + +} // end of namespace mln + + +#endif // ! MLN_MORPHO_CONTRAST_HH Index: mln/morpho/top_hat.hh --- mln/morpho/top_hat.hh (revision 0) +++ mln/morpho/top_hat.hh (revision 0) @@ -0,0 +1,138 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +#ifndef MLN_MORPHO_TOP_HAT_HH +# define MLN_MORPHO_TOP_HAT_HH + +/*! \file mln/morpho/top_hat.hh + * + * \brief Morphological top-hats. + * + * \todo Save memory. + */ + +# include <mln/morpho/opening.hh> +# include <mln/morpho/closing.hh> + + +namespace mln +{ + + namespace morpho + { + + /*! Morphological white top-hat (for object / light objects). + * + * This operator is Id - ope_B. + */ + template <typename I, typename W, typename O> + void top_hat_white(const Image<I>& input, const Window<W>& win, + Image<O>& output); + + + /*! Morphological black top-hat (for background / dark objects). + * + * This operator is clo_B - Id. + */ + template <typename I, typename W, typename O> + void top_hat_black(const Image<I>& input, const Window<W>& win, + Image<O>& output); + + + /*! Morphological self-complementary top-hat. + * + * This operator is \n + * = top_hat_white + top_hat_black \n + * = (input - opening) + (closing - input) \n + * = closing - opening. \n + */ + template <typename I, typename W, typename O> + void top_hat_self_complementary(const Image<I>& input, const Window<W>& win, + Image<O>& output); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I, typename W, typename O> + void top_hat_white(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + { + const I& input = exact(input_); + const W& win = exact(win_); + O& output = exact(output_); + + mln_precondition(output.domain() = input.domain()); + mln_precondition(! win.is_empty()); + + O temp(input.domain()); + opening(input, win, temp); // temp = opening + arith::minus(input, temp, output); // output = input - opening + + mln_postcondition(test::positive(output)); + } + + template <typename I, typename W, typename O> + void top_hat_black(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + { + const I& input = exact(input_); + const W& win = exact(win_); + O& output = exact(output_); + + mln_precondition(output.domain() = input.domain()); + mln_precondition(! win.is_empty()); + + closing(input, win, output); // output = closing + arith::minus_inplace(output, input); // now output = closing - input + + mln_postcondition(test::positive(output)); + } + + template <typename I, typename W, typename O> + void top_hat_self_complementary(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) + { + const I& input = exact(input_); + const W& win = exact(win_); + O& output = exact(output_); + + mln_precondition(output.domain() = input.domain()); + mln_precondition(! win.is_empty()); + + closing(input, win, output); // output = closing + O temp(input.domain()); + opening(input, win, temp); // temp = opening + arith::minus_inplace(output, temp); // now output = closing - opening + + mln_postcondition(test::positive(output)); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho + +} // end of namespace mln + + +#endif // ! MLN_MORPHO_TOP_HAT_HH
participants (1)
-
Thierry Geraud