milena r1103: Optims for erosion and dilation on octagons

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena ChangeLog: 2007-09-11 Simon Nivault <simon.nivault@lrde.epita.fr> Optims for erosion and dilation on octagons * mln/core/win/octagon2d.hh: Well created. * mln/morpho/dilation.hh: Fill and Optim. * mln/morpho/erosion.hh: Optim. * tests/morpho_dilation.cc: New. * tests/morpho_erosion.cc: Update. * tests/win_octagon2d.cc: New. --- mln/core/win/octagon2d.hh | 35 ++++++++++++-- mln/morpho/dilation.hh | 111 +++++++++++++++++++++++++++++++++++++++++++--- mln/morpho/erosion.hh | 31 +++++++++--- tests/morpho_dilation.cc | 100 +++++++++++++++++++++++++++++++++++++++++ tests/morpho_erosion.cc | 12 ++++ tests/win_octagon2d.cc | 48 +++++++++++++++++++ 6 files changed, 316 insertions(+), 21 deletions(-) Index: trunk/milena/tests/win_octagon2d.cc =================================================================== --- trunk/milena/tests/win_octagon2d.cc (revision 0) +++ trunk/milena/tests/win_octagon2d.cc (revision 1103) @@ -0,0 +1,48 @@ +// Copyright (C) 2007 EPITA Research and Development Laboratory +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/*! \file tests/win_octagon2d.cc + * + * \brief Tests on mln::win::octagon2d. + */ + +#include <mln/core/win/octagon2d.hh> + +#include <mln/convert/to_image.hh> + +#include <mln/debug/println.hh> + +int main() +{ + using namespace mln; + + const unsigned l = 13; + win::octagon2d oct(l); + + debug::println(convert::to_image(oct)); +} + Index: trunk/milena/tests/morpho_erosion.cc =================================================================== --- trunk/milena/tests/morpho_erosion.cc (revision 1102) +++ trunk/milena/tests/morpho_erosion.cc (revision 1103) @@ -32,6 +32,9 @@ #include <mln/core/image2d_b.hh> #include <mln/core/win/rectangle2d.hh> +#include <mln/core/win/octagon2d.hh> +#include <mln/core/win/diag2d.hh> +#include <mln/core/win/backdiag2d.hh> #include <mln/core/window2d.hh> #include <mln/io/pgm/load.hh> @@ -62,7 +65,14 @@ { image2d_b<int_u8> out(lena.domain()); morpho::erosion(lena, rec, out); - io::pgm::save(out, "out.pgm"); + io::pgm::save(out, "out1.pgm"); + } + + { + win::octagon2d oct(31); + image2d_b<int_u8> out(lena.domain()); + morpho::erosion(lena, oct, out); + io::pgm::save(out, "out2.pgm"); } // { Index: trunk/milena/tests/morpho_dilation.cc =================================================================== --- trunk/milena/tests/morpho_dilation.cc (revision 0) +++ trunk/milena/tests/morpho_dilation.cc (revision 1103) @@ -0,0 +1,100 @@ +// 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_dilation.cc + * + * \brief Test on mln::morpho::dilation. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/core/win/rectangle2d.hh> +#include <mln/core/win/octagon2d.hh> +#include <mln/core/win/diag2d.hh> +#include <mln/core/win/backdiag2d.hh> +#include <mln/core/window2d.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include <mln/value/int_u8.hh> +#include <mln/level/fill.hh> +#include <mln/morpho/dilation.hh> + +#include <mln/pw/value.hh> +#include <mln/pw/cst.hh> +#include <mln/fun/ops.hh> + +#include <mln/convert/to_vec_p.hh> +#include <mln/convert/to_window.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + win::rectangle2d rec(21, 21); + border::thickness = 66; + + image2d_b<int_u8> lena = io::pgm::load("../img/lena.pgm"); + +// { +// image2d_b<int_u8> out(lena.domain()); +// morpho::dilation(lena, rec, out); +// io::pgm::save(out, "out1.pgm"); +// } + + { + win::octagon2d oct(31); + image2d_b<int_u8> out(lena.domain()); + morpho::dilation(lena, oct, out); + io::pgm::save(out, "out2.pgm"); + } + +// { +// vec_p<point2d> vec = convert::to_vec_p(rec, point2d::zero); +// window2d win = convert::to_window(vec); + +// image2d_b<int_u8> out(lena.domain()); +// level::ero(lena, win, out); +// morpho::dilation(lena, win, out); +// io::pgm::save(out, "out.pgm"); +// } + +// { +// image2d_b<bool> bin(lena.domain()), out(lena.domain()); +// level::fill(bin, pw::value(lena) > pw::cst(127)); +// morpho::dilation(bin, rec, out); + +// image2d_b<int_u8> test(lena.domain()); +// image2d_b<int_u8>::fwd_piter p(lena.domain()); +// for_all(p) +// test(p) = out(p) ? 255 : 0; +// io::pgm::save(test, "test.pgm"); +// } + +} Index: trunk/milena/mln/core/win/octagon2d.hh =================================================================== --- trunk/milena/mln/core/win/octagon2d.hh (revision 1102) +++ trunk/milena/mln/core/win/octagon2d.hh (revision 1103) @@ -48,8 +48,8 @@ /*! \brief Octagon window defined on the 2D square grid. * * An octagon2d is centered and symmetrical. - * The length l of the octagon is such as l = 2*x + 1 - * where x is odd; + * The length l of the octagon is such as l = 6*x + 1 + * where 0 <= x. * * For instance: \n * o o o \n @@ -59,7 +59,7 @@ * o o o o o o o \n * o o o o o \n * o o o \n - * is defined with length = 7 (x = 3). + * is defined with length = 7 (x = 0). */ struct octagon2d : public Window< octagon2d >, public internal::dpoints_base_< dpoint2d, octagon2d > @@ -88,7 +88,7 @@ * * \param[in] lenght Length, of the octagon. * - * \pre \p length is such as length = 2*x + 1 where x is odd. + * \pre \p length is such as length = 6*x + 1 where x >= 0. */ octagon2d(unsigned length); @@ -140,8 +140,31 @@ octagon2d::octagon2d(unsigned length) : length_(length) { - mln_precondition(length % 2 == 1 && (length / 2) % 2 == 1); - insert(dpoint2d::zero); // FIXME : Do the right insert. + mln_precondition(length % 6 == 1); + const int y = length / 6; + const int x = y * 2; + const int z = y + x; + insert(dpoint2d::zero); + for (int a = 1; a <= x; ++a) + for (int b = 0; b <= x; ++b) + { + insert(make::dpoint2d(a, b)); + insert(make::dpoint2d(-b, a)); + insert(make::dpoint2d(b, -a)); + insert(make::dpoint2d(-a, -b)); + } + for (int a = x + 1; a <= z; ++a) + for (int b = -2 * x + a; b <= 2 * x - a; ++b) + { + insert(make::dpoint2d(a, b)); + insert(make::dpoint2d(a, -b)); + insert(make::dpoint2d(-a, b)); + insert(make::dpoint2d(-a, -b)); + insert(make::dpoint2d(b, a)); + insert(make::dpoint2d(b, -a)); + insert(make::dpoint2d(-b, a)); + insert(make::dpoint2d(-b, -a)); + } } bool octagon2d::is_centered() const Index: trunk/milena/mln/morpho/dilation.hh =================================================================== --- trunk/milena/mln/morpho/dilation.hh (revision 1102) +++ trunk/milena/mln/morpho/dilation.hh (revision 1103) @@ -32,17 +32,11 @@ * * \brief Morphological dilation. * - * \todo Mimic erosion.hh when completed. */ # include <mln/morpho/includes.hh> - -// todo simon -// this file should be like erosion - - namespace mln { @@ -50,6 +44,9 @@ { /*! Morphological dilation. + * + * \todo Overload dilation_wrt_win for hline and vline and for fast + * images. */ template <typename I, typename W, typename O> void dilation(const Image<I>& input, const Window<W>& win, Image<O>& output); @@ -60,6 +57,8 @@ namespace impl { + // On function. + template <typename I, typename W, typename O> void dilation_on_function(const Image<I>& input_, const Window<W>& win_, Image<O>& output_) { @@ -80,6 +79,104 @@ } } + // On set. + + template <typename I, typename W, typename O> + void dilation_on_set(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_); + + level::fill(output, input); + + mln_piter(I) p(input.domain()); + mln_qiter(W) q(win, p); + for_all(p) + if (input(p)) + for_all(q) if (input.has(q)) + if (! input(q)) + { + output(p) = true; + break; + } + } + + + // ... + + + // FIXME: Stage 3: dispatch w.r.t. fast property + + + // Stage 2: dispatch w.r.t. the value kind. + + template <typename I, typename W, typename O> + void dilation_wrt_value(value::binary_kind, // binary => morphology on sets + const Image<I>& input, const Window<W>& win, Image<O>& output) + { + return impl::dilation_on_set(exact(input), exact(win), output); + } + + template <typename K, typename I, typename W, typename O> + void dilation_wrt_value(K, // otherwise => morphology on functions + const Image<I>& input, const Window<W>& win, Image<O>& output) + { + return impl::dilation_on_function(exact(input), exact(win), output); + } + + + + // Stage 1: dispatch w.r.t. the window type. + // | + // V + + template <typename I, typename W, typename O> + void dilation_wrt_win(const Image<I>& input, const Window<W>& win, Image<O>& output) + { + dilation_wrt_value(mln_value_kind(I)(), exact(input), exact(win), output); + // | + // --> call stage 2: dispatch w.r.t. the value kind + } + +# ifdef MLN_CORE_WIN_RECTANGLE2D_HH + + template <typename I, typename O> + void dilation_wrt_win(const Image<I>& input, const win::rectangle2d& win, Image<O>& output) + { + O temp(exact(output).domain()); + morpho::dilation(input, win::hline2d(win.width()), temp); + morpho::dilation(temp, win::vline2d(win.height()), output); + } + +# endif // MLN_CORE_WIN_RECTANGLE2D_HH + + +# ifdef MLN_CORE_WIN_OCTAGON2D_HH +# ifdef MLN_CORE_WIN_DIAG2D_HH +# ifdef MLN_CORE_WIN_BACKDIAG2D_HH + + template <typename I, typename O> + void dilation_wrt_win(const Image<I>& input, const win::octagon2d& win, Image<O>& output) + { + const unsigned len = win.length() / 3 + 1; + + O temp1(exact(output).domain()); + O temp2(exact(output).domain()); + morpho::dilation(input, win::hline2d(len), temp1); + morpho::dilation(temp1, win::vline2d(len), temp2); + morpho::dilation(temp2, win::diag2d(len), temp1); + morpho::dilation(temp1, win::backdiag2d(len), output); + } + +# endif // MLN_CORE_WIN_BACKDIAG2D_HH +# endif // MLN_CORE_WIN_DIAG2D_HH +# endif // MLN_CORE_WIN_OCTAGON2D_HH + + // ^ + // | + // end of stage1 (dispatch w.r.t. the window type) + } // end of namespace mln::morpho::impl @@ -91,7 +188,7 @@ mln_precondition(exact(output).domain() == exact(input).domain()); mln_precondition(! exact(win).is_empty()); - impl::dilation_on_function(input, win, output); + impl::dilation_wrt_win(input, exact(win), output); if (exact(win).is_centered()) mln_postcondition(output >= input); Index: trunk/milena/mln/morpho/erosion.hh =================================================================== --- trunk/milena/mln/morpho/erosion.hh (revision 1102) +++ trunk/milena/mln/morpho/erosion.hh (revision 1103) @@ -28,6 +28,12 @@ #ifndef MLN_MORPHO_EROSION_HH # define MLN_MORPHO_EROSION_HH +/*! \file mln/morpho/erosion.hh + * + * \brief Morphological erosion. + * + */ + # include <mln/morpho/includes.hh> @@ -149,15 +155,26 @@ # endif // MLN_CORE_WIN_RECTANGLE2D_HH -// ifdef MLN_CORE_WIN_RECTANGLE2D_HH +# ifdef MLN_CORE_WIN_OCTAGON2D_HH +# ifdef MLN_CORE_WIN_DIAG2D_HH +# ifdef MLN_CORE_WIN_BACKDIAG2D_HH -// template <typename I, typename O> -// void erosion_wrt_win(const Image<I>& input, const win::octagon2d& win, Image<O>& output) -// { -// todo simon -// } + template <typename I, typename O> + void erosion_wrt_win(const Image<I>& input, const win::octagon2d& win, Image<O>& output) + { + const unsigned len = win.length() / 3 + 1; + + O temp1(exact(output).domain()); + O temp2(exact(output).domain()); + morpho::erosion(input, win::hline2d(len), temp1); + morpho::erosion(temp1, win::vline2d(len), temp2); + morpho::erosion(temp2, win::diag2d(len), temp1); + morpho::erosion(temp1, win::backdiag2d(len), output); + } -// endif MLN_CORE_WIN_RECTANGLE2D_HH +# endif // MLN_CORE_WIN_BACKDIAG2D_HH +# endif // MLN_CORE_WIN_DIAG2D_HH +# endif // MLN_CORE_WIN_OCTAGON2D_HH // ^ // |
participants (1)
-
Simon Nivault