URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-10-08 Simon Nivault <simon.nivault(a)lrde.epita.fr>
Refactoring erosion with dispatch mecanism and tracing.
* mln/morpho/erosion.hh: Add fastest image version.
* mln/morpho/erosion.spe.hh: New.
* mln/morpho/includes.hh: Includes min_h and max_h.
---
erosion.hh | 108 +++-----------------
erosion.spe.hh | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
includes.hh | 2
3 files changed, 313 insertions(+), 91 deletions(-)
Index: trunk/milena/mln/morpho/erosion.spe.hh
===================================================================
--- trunk/milena/mln/morpho/erosion.spe.hh (revision 0)
+++ trunk/milena/mln/morpho/erosion.spe.hh (revision 1274)
@@ -0,0 +1,294 @@
+// 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_EROSION_SPE_HH
+# define MLN_MORPHO_EROSION_SPE_HH
+
+/*! \file mln/morpho/erosion.spe.hh
+ *
+ * \brief Specialization for mln::morpho::erosion.
+ */
+
+# ifndef MLN_INCLUDE_ONLY
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ // Fwd decl.
+ template <typename I, typename W, typename O>
+ void erosion(const Image<I>& input, const Window<W>& win,
Image<O>& output);
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+ // Fwd decl.
+ template <typename I, typename W, typename O, typename A>
+ void erosion_on_function(const I& input, const W& win, O& output, A&
min);
+
+ // Fwd decl.
+ template <typename I, typename W, typename O>
+ void erosion_on_set(const I& input, const W& win, O& output);
+ }
+
+
+ template <typename I, typename W, typename O, typename A>
+ void erosion_on_function_fast(const I& input, const W& win, O& output,
A& min)
+ {
+ trace::entering("morpho::impl::erosion_on_function_fast");
+ border::fill(input, mln_max(mln_value(I)));
+
+ mln_pixter(const I) p(input);
+ mln_pixter(O) p_out(output);
+ mln_qixter(const I, W) q(p, win);
+ for_all_2(p, p_out)
+ {
+ min.init();
+ for_all(q)
+ min.take(q.val());
+ p_out.val() = min.to_result();
+ }
+ trace::exiting("morpho::impl::erosion_on_function_fast");
+ }
+
+ template <typename I, typename W, typename O>
+ void erosion_on_set_fast(const I& input, const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_on_set_fast");
+ level::fill(output, input);
+ border::fill(input, true);
+
+ mln_pixter(const I) p(input);
+ mln_pixter(O) p_out(output);
+ mln_qixter(const I, W) q(p, win);
+ for_all_2(p, p_out)
+ if (p.val())
+ for_all(q)
+ if (! q.val())
+ {
+ p_out.val() = false;
+ break;
+ }
+ trace::exiting("morpho::impl::erosion_on_set_fast");
+ }
+
+
+ // Stage 5: dispatch w.r.t. fast property
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void erosion_set_wrt_fast(trait::image::speed::any, const I& input,
+ const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_set_wrt_fast");
+ generic::erosion_on_set(input, win, output);
+ trace::exiting("morpho::impl::erosion_set_wrt_fast");
+ }
+
+ template <typename I, typename W, typename O>
+ void erosion_set_wrt_fast(trait::image::speed::fastest, const I& input,
+ const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_set_wrt_fast");
+ impl::erosion_on_set_fast(input, win, output);
+ trace::exiting("morpho::impl::erosion_set_wrt_fast");
+ }
+
+ template <typename I, typename W, typename O, typename A>
+ void erosion_fun_wrt_fast(trait::image::speed::any, const I& input,
+ const W& win, O& output, A& min)
+ {
+ trace::entering("morpho::impl::erosion_fun_wrt_fast");
+ generic::erosion_on_function(input, win, output, min);
+ trace::exiting("morpho::impl::erosion_fun_wrt_fast");
+ }
+
+ template <typename I, typename W, typename O, typename A>
+ void erosion_fun_wrt_fast(trait::image::speed::fastest, const I& input,
+ const W& win, O& output, A& min)
+ {
+ trace::entering("morpho::impl::erosion_fun_wrt_fast");
+ impl::erosion_on_function_fast(input, win, output, min);
+ trace::exiting("morpho::impl::erosion_fun_wrt_fast");
+ }
+
+ // ^
+ // |
+ // end of stage 5 (dispatch w.r.t. fast property)
+
+ // Stage 4: dispatch w.r.t. data quantification
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void erosion_wrt_data(trait::image::quant::high, const I& input,
+ const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_wrt_data");
+ accu::min_<mln_value(I)> min;
+ impl::erosion_fun_wrt_fast(mln_trait_image_speed(I)(), input,
+ win, output, min);
+ trace::exiting("morpho::impl::erosion_wrt_data");
+ }
+
+ template <typename I, typename W, typename O>
+ void erosion_wrt_data(trait::image::quant::low, const I& input,
+ const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_wrt_data");
+ accu::min_h<mln_vset(I)> min;
+ impl::erosion_fun_wrt_fast(mln_trait_image_speed(I)(), input,
+ win, output, min);
+ trace::exiting("morpho::impl::erosion_wrt_data");
+ }
+
+ // ^
+ // |
+ // end of stage 4 (dispatch w.r.t. the data quantification)
+
+ // Stage 3: dispatch w.r.t. the value type
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void erosion_wrt_value(const I& input, const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_wrt_value");
+
+ if (mlc_is(mln_trait_image_kind(I), trait::image::kind::logic)::value)
+ impl::erosion_set_wrt_fast(mln_trait_image_speed(I)(), input,
+ win, output);
+ // |
+ // `--> call stage 5: dispatch w.r.t. fast property
+ else
+ impl::erosion_wrt_data(mln_trait_image_quant(I)(), input,
+ win, output);
+ // |
+ // `--> call stage 4: dispatch w.r.t. the data quantification
+ trace::exiting("morpho::impl::erosion_wrt_value");
+ }
+
+ // ^
+ // |
+ // end of stage 3 (dispatch w.r.t. the value type)
+
+
+
+ // Stage 2: dispatch w.r.t. the window morphology
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void erosion_wrt_mor(const I& input, const W& win, O& output)
+ {
+ trace::entering("morpho::impl::erosion_wrt_mor");
+ // FIXME : Choose the right algorithm between :
+ impl::erosion_wrt_value(input, win, output);
+ // and :
+ // impl::erosion_incr_wrt_value(input, win, output);
+ trace::exiting("morpho::impl::erosion_wrt_mor");
+ }
+
+ // ^
+ // |
+ // end of stage 2 (dispatch w.r.t. the window morphology)
+
+
+
+ // Stage 1: dispatch w.r.t. the window type.
+ // |
+ // V
+
+ template <typename I, typename W, typename O>
+ void erosion_wrt_win(const Image<I>& input_, const W& win_,
Image<O>& output_)
+ {
+ trace::entering("morpho::impl::erosion_wrt_win");
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+ O& output = exact(output_);
+
+ impl::erosion_wrt_mor(input, win, output);
+ // |
+ // `--> call stage 2: dispatch w.r.t. the data quantification
+ trace::exiting("morpho::impl::erosion_wrt_win");
+ }
+
+# ifdef MLN_CORE_WIN_RECTANGLE2D_HH
+
+ template <typename I, typename O>
+ void erosion_wrt_win(const Image<I>& input, const win::rectangle2d&
win, Image<O>& output)
+ {
+ O temp(exact(output).domain());
+ morpho::erosion(input, win::hline2d(win.width()), temp);
+ morpho::erosion(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 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_BACKDIAG2D_HH
+# endif // MLN_CORE_WIN_DIAG2D_HH
+# endif // MLN_CORE_WIN_OCTAGON2D_HH
+
+ // ^
+ // |
+ // end of stage 1 (dispatch w.r.t. the window type)
+
+
+
+ } // end of namespace mln::morpho::impl
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+#endif // ! MLN_MORPHO_EROSION_SPE_HH
Index: trunk/milena/mln/morpho/includes.hh
===================================================================
--- trunk/milena/mln/morpho/includes.hh (revision 1273)
+++ trunk/milena/mln/morpho/includes.hh (revision 1274)
@@ -40,6 +40,8 @@
# include <mln/accu/min.hh>
# include <mln/accu/max.hh>
+# include <mln/accu/min_h.hh>
+# include <mln/accu/max_h.hh>
# include <mln/level/compare.hh>
# include <mln/level/fill.hh>
Index: trunk/milena/mln/morpho/erosion.hh
===================================================================
--- trunk/milena/mln/morpho/erosion.hh (revision 1273)
+++ trunk/milena/mln/morpho/erosion.hh (revision 1274)
@@ -36,6 +36,9 @@
# include <mln/morpho/includes.hh>
+// Specializations are in:
+# include <mln/morpho/erosion.spe.hh>
+
namespace mln
{
@@ -57,17 +60,15 @@
namespace impl
{
- // On function.
- template <typename I, typename W, typename O>
- void erosion_on_function(const Image<I>& input_, const
Window<W>& win_, Image<O>& output_)
+ namespace generic
{
- const I& input = exact(input_);
- const W& win = exact(win_);
- O& output = exact(output_);
-
- accu::min_<mln_value(I)> min;
+ // On function.
+ template <typename I, typename W, typename O, typename A>
+ void erosion_on_function(const I& input, const W& win, O& output, A&
min)
+ {
+ trace::entering("morpho::impl::generic::erosion_on_function");
mln_piter(I) p(input.domain());
mln_qiter(W) q(win, p);
for_all(p)
@@ -77,18 +78,15 @@
min.take(input(q));
output(p) = min.to_result();
}
+ trace::exiting("morpho::impl::generic::erosion_on_function");
}
-
// On set.
template <typename I, typename W, typename O>
- void erosion_on_set(const Image<I>& input_, const Window<W>&
win_, Image<O>& output_)
+ void erosion_on_set(const I& input, const W& win, O& output)
{
- const I& input = exact(input_);
- const W& win = exact(win_);
- O& output = exact(output_);
-
+ trace::entering("morpho::impl::generic::erosion_on_set");
level::fill(output, input);
mln_piter(I) p(input.domain());
@@ -101,94 +99,21 @@
output(p) = false;
break;
}
+ trace::exiting("morpho::impl::generic::erosion_on_set");
}
-
-
- // ...
-
-
-
- // 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 erosion_wrt_value(trait::image::kind::logic, // binary => morphology on
sets
- const Image<I>& input, const Window<W>& win,
Image<O>& output)
- {
- return impl::erosion_on_set(exact(input), exact(win), output);
- }
-
- template <typename K, typename I, typename W, typename O>
- void erosion_wrt_value(K, // otherwise => morphology on functions
- const Image<I>& input, const Window<W>& win,
Image<O>& output)
- {
- return impl::erosion_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 erosion_wrt_win(const Image<I>& input, const Window<W>&
win, Image<O>& output)
- {
- erosion_wrt_value(mln_trait_image_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 erosion_wrt_win(const Image<I>& input, const win::rectangle2d&
win, Image<O>& output)
- {
- O temp(exact(output).domain());
- morpho::erosion(input, win::hline2d(win.width()), temp);
- morpho::erosion(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 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_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::generic
} // end of namespace mln::morpho::impl
+
// Facade.
template <typename I, typename W, typename O>
void erosion(const Image<I>& input, const Window<W>& win,
Image<O>& output)
{
+ trace::entering("morpho::erosion");
mln_precondition(exact(output).domain() == exact(input).domain());
mln_precondition(! exact(win).is_empty());
@@ -196,6 +121,7 @@
if (exact(win).is_centered())
mln_postcondition(output <= input);
+ trace::exiting("morpho::erosion");
}
# endif // ! MLN_INCLUDE_ONLY