https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)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