
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add dispatch for morpho erosion. * tests/morpho/temp.erosion.cc: New. * mln/morpho/erosion.spe.hh: Add dispatch. mln/morpho/erosion.spe.hh | 159 +++++++++++++++++++++++++++++++++++++------ tests/morpho/temp.erosion.cc | 116 +++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 22 deletions(-) Index: tests/morpho/temp.erosion.cc --- tests/morpho/temp.erosion.cc (revision 0) +++ tests/morpho/temp.erosion.cc (revision 0) @@ -0,0 +1,116 @@ +// 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/erosion.cc + * + * \brief Test on mln::morpho::erosion. + */ + +#include <mln/core/image/image2d.hh> +#include <mln/win/rectangle2d.hh> +#include <mln/win/octagon2d.hh> +#include <mln/win/diag2d.hh> +#include <mln/win/backdiag2d.hh> +#include <mln/core/alias/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/erosion.hh> + +#include <mln/pw/value.hh> +#include <mln/pw/cst.hh> +#include <mln/fun/ops.hh> + +#include <mln/convert/to_p_array.hh> +#include <mln/convert/to_window.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + unsigned + l_oct = 11, L_oct = 6 * l_oct + 1, + l_rec = 29, L_rec = 2 * l_rec + 1; + + // l_ + // oct rec err + // 0 0 3 + // 0 1 5 + // 1 2 15 + // 1 3 9 + // 2 5 11 + // 3 8 9 + // 5 13 15 + // 8 21 11 + // 11 29 1 + // 25 66 15 + + image2d<int_u8> lena; + io::pgm::load(lena, "./tiny.pgm"); + + trace::quiet = false; + + { + win::rectangle2d rec(L_rec, L_rec); + io::pgm::save(morpho::erosion(lena, rec), + "out1.pgm"); + } + +// { +// win::octagon2d oct(L_oct); +// io::pgm::save(morpho::erosion(lena, oct), +// "out2.pgm"); +// } + +// { +// p_array<point2d> vec = convert::to_p_array(rec, point2d::zero); +// window2d win = convert::to_window(vec); + +// image2d<int_u8> out(lena.domain()); +// level::ero(lena, win, out); +// morpho::erosion(lena, win, out); +// io::pgm::save(out, "out.pgm"); +// } + +// { +// image2d<bool> bin(lena.domain()), out(lena.domain()); +// level::fill(bin, pw::value(lena) > pw::cst(127)); +// morpho::erosion(bin, rec, out); + +// image2d<int_u8> test(lena.domain()); +// image2d<int_u8>::fwd_piter p(lena.domain()); +// for_all(p) +// test(p) = out(p) ? 255 : 0; +// io::pgm::save(test, "test.pgm"); +// } + +} Index: mln/morpho/erosion.spe.hh --- mln/morpho/erosion.spe.hh (revision 2387) +++ mln/morpho/erosion.spe.hh (working copy) @@ -267,7 +267,7 @@ erosion_arbitrary_2d_fastest_functor(const I& input, const W& win) : input(input), win(win), - min(input.values()), + min(), win_left(set::diff(geom::shift(win, left), win)), win_right(set::diff(win, geom::shift(win, left))), win_bot(set::diff(win, geom::shift(win, up))), @@ -328,8 +328,7 @@ trace::entering("morpho::impl:erosion_arbitrary_2d_fastest"); typedef erosion_arbitrary_2d_fastest_functor<I, W> F; - mlc_equal(W, win::octagon2d)::check(); - F f(input, win); + F f(exact(input), exact(win)); canvas::browsing::snake_fwd(f); trace::exiting("morpho::impl:erosion_arbitrary_2d_fastest"); @@ -363,7 +362,7 @@ erosion_arbitrary_2d_functor(const I& input, const W& win) : input(input), win(win), - min(input.values()), + min(), win_left(set::diff(geom::shift(win, left), win)), win_right(set::diff(win, geom::shift(win, left))), win_bot(set::diff(win, geom::shift(win, up))), @@ -424,8 +423,7 @@ trace::entering("morpho::impl:erosion_arbitrary_2d"); typedef erosion_arbitrary_2d_functor<I, W> F; - mlc_equal(W, win::octagon2d)::check(); - F f(input, win); + F f(exact(input), exact(win)); canvas::browsing::snake_fwd(f); trace::exiting("morpho::impl:erosion_arbitrary_2d"); @@ -438,30 +436,147 @@ namespace internal { + + // dispatch for the generic version + template <typename I, typename W> mln_concrete(I) - erosion_dispatch(const Image<I>& input, const Window<W>& win) + erosion_dispatch_for_generic(trait::image::kind::logic, // On sets. + trait::image::speed::fastest, + const I& input, const W& win) { - if (mlc_equal(mln_trait_image_kind(I)(), - trait::image::kind::logic)::value == true) -/* FIXME: Temporarily disabled, since this dynamic dispatch triggers - errors when class I has no pixter associated type(s). */ -#if 0 - if (mlc_equal(mln_trait_image_speed(I)(), - trait::image::speed::fastest)::value == true) + if (win.is_centered()) + return impl::erosion_on_set_centered_fastest(input, win); + else return impl::erosion_on_set_fastest(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_generic(trait::image::kind::any, // On functions. + trait::image::speed::fastest, + const I& input, const W& win) + { + return impl::erosion_on_function_fastest(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_generic(trait::image::kind::logic, // On sets. + trait::image::speed::any, + const I& input, const W& win) + { + if (win.is_centered()) + return erosion_on_set_centered(input, win); else -#endif return impl::generic::erosion_on_set(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_generic(trait::image::kind::any, // On functions. + trait::image::speed::any, + const I& input, const W& win) + { + return impl::generic::erosion_on_function(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_generic(const I& input, const W& win) // Entry point. + { + return erosion_dispatch_for_generic(mln_trait_image_kind(I)(), + mln_trait_image_speed(I)(), + input, win); + } + + + // dispatch for arbitrary elements + + template <typename I, typename W> + bool + erosion_chooses_arbitrary(const I& input, const W& win) + { + return + win.size() >= 25 // size is not too small + && + // 2d case only + mlc_equal(mln_trait_image_dimension(I), + trait::image::dimension::two_d)::value + && + // on a grid + mlc_is_a(mln_site(I), + Gpoint)::value + && + // continuous data + mlc_not_equal(mln_trait_image_value_storage(I), + trait::image::value_storage::disrupted)::value; + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_arbitrary(trait::image::speed::fastest, + const I& input, const W& win) + { + return impl::erosion_arbitrary_2d_fastest(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_arbitrary(trait::image::speed::any, + const I& input, const W& win) + { + return impl::erosion_arbitrary_2d(input, win); + } + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_for_arbitrary(const I& input, const W& win) + { + return erosion_dispatch_for_arbitrary(mln_trait_image_speed(I)(), + input, win); + } + + // dispatch w.r.t. win + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch_wrt_win(const I& input, const W& win) + { + if (erosion_chooses_arbitrary(input, win)) + return erosion_dispatch_for_arbitrary(input, win); else -// FIXME: Likewise. -#if 0 - if (mlc_equal(mln_trait_image_speed(I)(), - trait::image::speed::fastest)::value == true) - return impl::erosion_on_function_fastest(input, win); + return erosion_dispatch_for_generic(input, win); + } + + template <typename I> + mln_concrete(I) + erosion_dispatch_wrt_win(const I& input, const win::rectangle2d& win) + { + if (win.size() <= 9) // FIXME: Hard-coded! + return erosion_dispatch_for_generic(input, win); else -#endif - return impl::generic::erosion_on_function(input, win); + return impl::erosion_rectangle2d(input, win); + } + + template <typename I> + mln_concrete(I) + erosion_dispatch_wrt_win(const I& input, const win::octagon2d& win) + { + if (win.size() <= 9) // FIXME: Hard-coded! + return erosion_dispatch_for_generic(input, win); + else + return impl::erosion_octagon2d(input, win); + } + + + // The dispatch entry point. + + template <typename I, typename W> + mln_concrete(I) + erosion_dispatch(const Image<I>& input, const Window<W>& win) + { + return erosion_dispatch_wrt_win(exact(input), exact(win)); } } // end of namespace mln::morpho::internal