https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Migrate generic code from morpho erosion to new files in accu.
* mln/morpho/erosion.spe.hh
(erosion_arbitrary_2d_fastest_functor): Move and rename as...
* mln/accu/snake_2d.hh (snake_2d_fastest_functor): ...this.
(todo): New.
(snake_2d): Move code into (and call it)...
(snake_2d_dispatch): ...these new routines.
* mln/morpho/erosion.spe.hh (dp_directional): Move into...
* mln/accu/transform_directional.hh: ...this new file.
* mln/morpho/erosion.spe.hh: .
(dp_directional, erosion_directional_nd_functor),
(erosion_directional_nd_fastest_functor): Move and rename as...
* mln/accu/transform_directional.hh
(directional_functor, directional_fastest_functor): ...these.
(transform_directional, transform_directional_dispatch): New.
* mln/morpho/erosion.spe.hh (erosion_on_set_fastest): Remove.
It is obsolete since handled by accu::transform, called by...
(generic::erosion_on_set): ...this.
* mln/morpho/includes.hh (include): Update.
* tests/morpho/erosion.cc: Update.
mln/accu/snake_2d.hh | 218 +++++++++++++
mln/accu/transform_directional.hh | 347 +++++++++++++++++++++
mln/morpho/erosion.spe.hh | 602 +-------------------------------------
mln/morpho/includes.hh | 2
tests/morpho/erosion.cc | 45 --
5 files changed, 586 insertions(+), 628 deletions(-)
Index: tests/morpho/erosion.cc
--- tests/morpho/erosion.cc (revision 2879)
+++ tests/morpho/erosion.cc (working copy)
@@ -65,7 +65,9 @@
// trace::quiet = false;
+
// Rectangle
+
{
ref = morpho::impl::generic::erosion_on_function(lena, rec);
}
@@ -77,18 +79,14 @@
}
{
- out = morpho::impl::erosion_arbitrary_2d_fastest(lena, rec);
- bool test = out == ref;
- mln_assertion(test);
- }
-
- {
out = morpho::impl::erosion_arbitrary_2d(lena, rec);
bool test = out == ref;
mln_assertion(test);
}
+
//Hline
+
{
ref = morpho::impl::generic::erosion_on_function(lena, hline);
}
@@ -100,19 +98,14 @@
}
{
- out = morpho::impl::erosion_arbitrary_2d_fastest(lena, hline);
- bool test = out == ref;
- mln_assertion(test);
- }
-
-
- {
out = morpho::impl::erosion_arbitrary_2d(lena, hline);
bool test = out == ref;
mln_assertion(test);
}
+
//Vline
+
{
ref = morpho::impl::generic::erosion_on_function(lena, vline);
}
@@ -123,14 +116,6 @@
mln_assertion(test);
}
-
- {
- out = morpho::impl::erosion_arbitrary_2d_fastest(lena, vline);
- bool test = out == ref;
- mln_assertion(test);
- }
-
-
{
out = morpho::impl::erosion_arbitrary_2d(lena, vline);
bool test = out == ref;
@@ -150,20 +135,13 @@
mln_assertion(test);
}
-
- {
- out = morpho::impl::erosion_arbitrary_2d_fastest(lena, diag2d);
- bool test = out == ref;
- mln_assertion(test);
- }
-
-
{
out = morpho::impl::erosion_arbitrary_2d(lena, diag2d);
bool test = out == ref;
mln_assertion(test);
}
+
//Backdiag2d
{
@@ -176,14 +154,6 @@
mln_assertion(test);
}
-
- {
- out = morpho::impl::erosion_arbitrary_2d_fastest(lena, backdiag2d);
- bool test = out == ref;
- mln_assertion(test);
- }
-
-
{
out = morpho::impl::erosion_arbitrary_2d(lena, backdiag2d);
bool test = out == ref;
@@ -193,6 +163,7 @@
// Octagon
+
{
ref = morpho::impl::generic::erosion_on_function(lena, oct);
io::pgm::save(ref, "out_oct_ref.pgm");
Index: mln/accu/snake_2d.hh
--- mln/accu/snake_2d.hh (revision 2879)
+++ mln/accu/snake_2d.hh (working copy)
@@ -32,13 +32,20 @@
///
/// Run an accumulator in a snake-like browsing.
///
+/// \todo Rename as transform_snake_2d.
+///
/// \todo Make it n-D.
+///
+/// \todo Split dispatch and impl.
+///
+/// \todo Pass the accumulator to the function-object.
#include <mln/core/concept/image.hh>
#include <mln/core/concept/meta_accumulator.hh>
#include <mln/core/alias/window2d.hh>
#include <mln/win/diff.hh>
#include <mln/win/shift.hh>
+#include <mln/geom/delta.hh>
#include <mln/extension/adjust.hh>
#include <mln/canvas/browsing/snake_generic.hh>
@@ -83,6 +90,8 @@
}
+ // Functor.
+
template <typename I, typename W, typename A>
struct snake_2d_functor
{
@@ -232,45 +241,234 @@
};
+
+ // Functor (fastest version).
+
+ template <typename I, typename W, typename A>
+ struct snake_2d_fastest_functor
+ {
+ typedef snake_2d_fastest_functor<I,W,A> self;
+ typedef void (self::*move_fun)();
+ typedef mln_deduce(I, psite, delta) dpsite;
+
+ const I& input;
+ const W& win;
+ mln_concrete(I) output;
+ A accu;
+
+ mln_psite(I) p;
+
+ window2d
+ win_left_fwd,
+ win_right_fwd,
+ win_left_bkd,
+ win_right_bkd,
+ win_bot_up,
+ win_top_up,
+ win_bot_down,
+ win_top_down;
+
+ mln_qixter(const I, window2d)
+ q_l_fwd,
+ q_r_fwd,
+ q_l_bkd,
+ q_r_bkd,
+ q_top_up,
+ q_bot_up,
+ q_top_down,
+ q_bot_down;
+
+
+ std::vector<move_fun> moves;
+ std::vector<dpsite> dps;
+
+ snake_2d_fastest_functor(const I& input, const W& win)
+ : input(input),
+ win(win),
+ accu(),
+
+ win_left_fwd(win::shift(win, mln::left) - win),
+ win_right_fwd(win - win::shift(win, mln::left)),
+ win_left_bkd(win::shift(win_left_fwd, mln::right)),
+ win_right_bkd(win::shift(win_right_fwd, mln::right)),
+
+ win_bot_up(win::shift(win, mln::down) - win),
+ win_top_up(win - win::shift(win, mln::down)),
+ win_bot_down(win::shift(win_bot_up, mln::up)),
+ win_top_down(win::shift(win_top_up, mln::up)),
+
+ q_l_fwd(input, win_left_fwd, p),
+ q_r_fwd(input, win_right_fwd, p),
+ q_l_bkd(input, win_left_bkd, p),
+ q_r_bkd(input, win_right_bkd, p),
+
+ q_top_up(input, win_top_up, p),
+ q_bot_up(input, win_bot_up, p),
+ q_top_down(input, win_top_down, p),
+ q_bot_down(input, win_bot_down, p),
+
+ moves(3),
+ dps(3)
+ {
+ if (win_bot_up.size() + win_top_up.size() +
+ win_bot_down.size() + win_top_down.size() <
+ win_left_fwd.size() + win_right_fwd.size() +
+ win_left_bkd.size() + win_right_bkd.size())
+ {
+ // Vertical snake
+ dps[0] = mln::right;
+ dps[1] = mln::down;
+ dps[2] = mln::up;
+ moves[0] = &self::right;
+ moves[1] = &self::down;
+ moves[2] = &self::up;
+ }
+ else
+ {
+ // Horizontal snake
+ dps[0] = mln::down;
+ dps[1] = mln::right;
+ dps[2] = mln::left;
+ moves[0] = &self::down;
+ moves[1] = &self::right;
+ moves[2] = &self::left;
+ }
+ }
+
+ void init()
+ {
+ // extension::adjust_fill is performed in the routine
+ // because it has to be done before the initialization of
+ // the fast iterators (q_*).
+ initialize(output, input);
+ accu.init();
+ p = input.domain().pmin() - dps[0];
+ mln_qixter(const I, W) q(input, win, p);
+ for_all(q)
+ accu.take(q.val());
+ p = input.domain().pmin();
+ }
+
+ void right()
+ {
+ for_all(q_l_fwd)
+ accu.untake(q_l_fwd.val());
+ for_all(q_r_fwd)
+ accu.take(q_r_fwd.val());
+ output(p) = accu;
+ }
+
+ void left()
+ {
+ for_all(q_r_bkd)
+ accu.untake(q_r_bkd.val());
+ for_all(q_l_bkd)
+ accu.take(q_l_bkd.val());
+ output(p) = accu;
+ }
+
+ void down()
+ {
+ for_all(q_top_down)
+ accu.untake(q_top_down.val());
+ for_all(q_bot_down)
+ accu.take(q_bot_down.val());
+ output(p) = accu;
+ }
+
+ void up()
+ {
+ for_all(q_bot_up)
+ accu.untake(q_bot_up.val());
+ for_all(q_top_up)
+ accu.take(q_top_up.val());
+ output(p) = accu;
+ }
+
+ };
+
+
+ // Both dispatch and implementation (hum...)
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ snake_2d_dispatch(trait::image::speed::any,
+ const Accumulator<A>& /* FIXME a */,
+ const Image<I>& input, const Window<W>& win)
+ {
+ typedef snake_2d_functor<I, W, A> F;
+ F f(exact(input), exact(win)); // FIXME: Pass a to f.
+ canvas::browsing::snake_generic(f);
+ return f.output;
+ }
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ snake_2d_dispatch(trait::image::speed::fastest,
+ const Accumulator<A>& /* FIXME a*/,
+ const Image<I>& input, const Window<W>& win)
+ {
+ typedef snake_2d_fastest_functor<I, W, A> F;
+ F f(exact(input), exact(win)); // FIXME: Pass a to f.
+ canvas::browsing::snake_generic(f);
+ return f.output;
+ }
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ snake_2d_dispatch(const Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win)
+ {
+ return snake_2d_dispatch(mln_trait_image_speed(I)(),
+ a, input, win);
+ }
+
} // end of namespace mln::accu::internal
+
template <typename A, typename I, typename W>
inline
mln_ch_value(I, mln_result(A))
- snake_2d(const Accumulator<A>&, const Image<I>& input, const
Window<W>& win)
+ snake_2d(const Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win)
{
trace::entering("accu::snake_2d");
internal::snake_2d_tests(input, win);
- extension::adjust(input, win);
- internal::snake_2d_functor<I, W, A> f(input, win);
- canvas::browsing::snake_generic(f);
+ extension::adjust(input, geom::delta(win) + 1);
+ mln_ch_value(I, mln_result(A)) output;
+ output = internal::snake_2d_dispatch(a, input, win);
trace::exiting("accu::snake_2d");
- return f.output;
+ return output;
}
template <typename A, typename I, typename W>
inline
mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
- snake_2d(const Meta_Accumulator<A>&, const Image<I>& input,
const Window<W>& win)
+ snake_2d(const Meta_Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win)
{
trace::entering("accu::snake_2d");
internal::snake_2d_tests(input, win);
typedef mln_accu_with(A, mln_value(I)) A_;
+ A_ a_ = accu::unmeta(exact(a), mln_value(I)());
- extension::adjust(input, win);
- internal::snake_2d_functor<I, W, A_> f(input, win);
- canvas::browsing::snake_generic(f);
+ extension::adjust(input, geom::delta(win) + 1);
+ mln_ch_value(I, mln_result(A_)) output;
+ output = internal::snake_2d_dispatch(a_, input, win);
trace::exiting("accu::snake_2d");
- return f.output;
+ return output;
}
Index: mln/accu/transform_directional.hh
--- mln/accu/transform_directional.hh (revision 0)
+++ mln/accu/transform_directional.hh (revision 0)
@@ -0,0 +1,347 @@
+// Copyright (C) 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.
+
+#ifndef MLN_ACCU_TRANSFORM_DIRECTIONAL_HH
+# define MLN_ACCU_TRANSFORM_DIRECTIONAL_HH
+
+/// \file mln/accu/transform_directional.hh
+///
+/// Run an accumulator over a particular direction.
+///
+/// \todo Split dispatch and impl.
+///
+/// \todo Pass the accumulator to the function-object.
+
+
+#include <mln/core/concept/image.hh>
+#include <mln/core/concept/meta_accumulator.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/win/diff.hh>
+#include <mln/win/shift.hh>
+#include <mln/geom/delta.hh>
+#include <mln/literal/zero.hh>
+#include <mln/extension/adjust.hh>
+#include <mln/canvas/browsing/directional.hh>
+
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+
+ template <typename A, typename I, typename W>
+ mln_ch_value(I, mln_result(A))
+ transform_directional(const Accumulator<A>&,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir);
+
+
+ template <typename A, typename I, typename W>
+ mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
+ transform_directional(const Meta_Accumulator<A>&,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace internal
+ {
+
+
+ // Tests.
+
+
+ template <typename I, typename W>
+ void transform_directional_tests(const Image<I>& input_, const
Window<W>& win_)
+ {
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+
+ mln_precondition(input.has_data());
+ mln_precondition(! win.is_empty());
+ // mln_precondition(! win.is_valid());
+
+ (void) input;
+ (void) win;
+ }
+
+
+
+ // Utility.
+
+
+ template <typename Dp>
+ Dp dp_directional(int dir)
+ {
+ Dp dp = literal::zero;
+ dp[dir] = 1;
+ return dp;
+ }
+
+
+
+ // Functor.
+
+
+ template <typename I_, typename W, typename A>
+ struct directional_functor
+ {
+ typedef I_ I;
+ typedef mln_deduce(I, psite, delta) dpsite;
+
+ const I& input;
+ const W& win;
+ mln_concrete(I) output;
+ A accu;
+ enum { dim = I::site::dim };
+
+ mln_psite(I) p;
+ unsigned dir;
+
+ window2d
+ win_left,
+ win_right;
+
+ mln_qiter(window2d)
+ q_l,
+ q_r;
+
+ directional_functor(const I& input, const W& win, int dir)
+ : input(input),
+ win(win),
+ accu(),
+ dir(dir),
+ win_left(win::shift(win, -dp_directional<dpsite>(dir)) - win),
+ win_right(win - win::shift(win, -dp_directional<dpsite>(dir))),
+ q_l(win_left, p),
+ q_r(win_right, p)
+ {
+
+ }
+
+ void init()
+ {
+ initialize(output, input);
+ }
+
+ void init_run()
+ {
+ accu.init();
+ p[dir]--;
+ mln_qiter(W) q(win, p);
+ for_all(q) if (input.has(q))
+ accu.take(input(q));
+ p[dir]++;
+ }
+
+ void next()
+ {
+ for_all(q_l) if (input.has(q_l))
+ accu.untake(input(q_l));
+ for_all(q_r) if (input.has(q_r))
+ accu.take(input(q_r));
+ output(p) = accu;
+ }
+
+ void final()
+ {
+ }
+
+ };
+
+
+
+ // Functor (fastest version).
+
+
+ template <typename I_, typename W, typename A>
+ struct directional_fastest_functor
+ {
+ typedef I_ I;
+ typedef mln_deduce(I, psite, delta) dpsite;
+
+ const I& input;
+ const W& win;
+ mln_concrete(I) output;
+ A accu;
+
+ mln_psite(I) p;
+ enum { dim = I::site::dim };
+ unsigned dir;
+
+ window2d win_left, win_right;
+
+ mln_qixter(const I, window2d) q_l, q_r;
+
+ directional_fastest_functor(const I& input, const W& win, unsigned dir)
+ : input(input),
+ win(win),
+ accu(),
+ dir(dir),
+ win_left(win::shift(win, -dp_directional<dpsite>(dir)) - win),
+ win_right(win - win::shift(win, -dp_directional<dpsite>(dir))),
+ q_l(input, win_left, p),
+ q_r(input, win_right, p)
+ {
+ }
+
+ void init()
+ {
+ initialize(output, input);
+ }
+
+ void next()
+ {
+ for_all(q_l)
+ accu.untake(q_l.val());
+ for_all(q_r)
+ accu.take(q_r.val());
+ output(p) = accu;
+ }
+
+
+ void init_run()
+ {
+ accu.init();
+ p[dir]--;
+ mln_qixter(const I, W) q(input, win, p);
+ for_all(q)
+ accu.take(q.val());
+ p[dir]++;
+ }
+
+ void final()
+ {
+ }
+
+ };
+
+
+
+
+ // Both dispatch and implementation (hum...)
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_directional_dispatch(trait::image::speed::any,
+ const Accumulator<A>& /* FIXME a */,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir)
+ {
+ typedef directional_functor<I, W, A> F;
+ F f(exact(input), exact(win), dir); // FIXME: Pass a to f.
+ canvas::browsing::directional(f);
+ return f.output;
+ }
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_directional_dispatch(trait::image::speed::fastest,
+ const Accumulator<A>& /* FIXME a*/,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir)
+ {
+ typedef directional_fastest_functor<I, W, A> F;
+ F f(exact(input), exact(win), dir); // FIXME: Pass a to f.
+ canvas::browsing::directional(f);
+ return f.output;
+ }
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_directional_dispatch(const Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir)
+ {
+ return transform_directional_dispatch(mln_trait_image_speed(I)(),
+ a, input, win, dir);
+ }
+
+ } // end of namespace mln::accu::internal
+
+
+
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_result(A))
+ transform_directional(const Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir)
+ {
+ trace::entering("accu::transform_directional");
+
+ internal::transform_directional_tests(input, win);
+
+ extension::adjust(input, geom::delta(win) + 1);
+ mln_ch_value(I, mln_result(A)) output;
+ output = internal::transform_directional_dispatch(a, input, win, dir);
+
+ trace::exiting("accu::transform_directional");
+ return output;
+ }
+
+
+ template <typename A, typename I, typename W>
+ inline
+ mln_ch_value(I, mln_accu_with(A, mln_value(I))::result)
+ transform_directional(const Meta_Accumulator<A>& a,
+ const Image<I>& input, const Window<W>& win,
+ unsigned dir)
+ {
+ trace::entering("accu::transform_directional");
+
+ internal::transform_directional_tests(input, win);
+
+ typedef mln_accu_with(A, mln_value(I)) A_;
+ A_ a_ = accu::unmeta(exact(a), mln_value(I)());
+
+ extension::adjust(input, geom::delta(win) + 1);
+ mln_ch_value(I, mln_result(A_)) output;
+ output = internal::transform_directional_dispatch(a_, input, win, dir);
+
+ trace::exiting("accu::transform_directional");
+ return output;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_TRANSFORM_DIRECTIONAL_HH
Index: mln/morpho/erosion.spe.hh
--- mln/morpho/erosion.spe.hh (revision 2879)
+++ mln/morpho/erosion.spe.hh (working copy)
@@ -95,37 +95,8 @@
erosion_on_set(const Image<I>& input_, const Window<W>& win_);
}
- template <typename I, typename W>
- mln_concrete(I)
- erosion_on_set_fastest(const Image<I>& input_, const Window<W>&
win_)
- {
- trace::entering("morpho::impl::erosion_on_set_fastest");
-
- typedef mln_concrete(I) O;
- const I& input = exact(input_);
- const W& win = exact(win_);
-
- extension::adjust_fill(input, win, true);
-
- O output;
- initialize(output, input);
-
- 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)
- {
- for_all(q)
- if (q.val() == false)
- break;
- p_out.val() = ! q.is_valid();
- }
-
- trace::exiting("morpho::impl::erosion_on_set_fastest");
-
- return output;
- }
+ // On set with centered window.
template <typename I, typename W>
mln_concrete(I)
@@ -189,6 +160,7 @@
}
+
template <typename I, typename G, unsigned Dir, typename C>
inline
mln_concrete(I)
@@ -277,313 +249,7 @@
return output;
}
- template <typename I, typename W, typename A>
- struct erosion_arbitrary_2d_fastest_functor
- {
- typedef erosion_arbitrary_2d_fastest_functor<I,W,A> self;
- typedef void (self::*move_fun)();
- typedef mln_deduce(I, psite, delta) dpsite;
-
- const I& input;
- const W& win;
- mln_concrete(I) output;
- A accu;
-
- mln_psite(I) p;
-
- window2d
- win_left_fwd,
- win_right_fwd,
- win_left_bkd,
- win_right_bkd,
- win_bot_up,
- win_top_up,
- win_bot_down,
- win_top_down;
-
- mln_qixter(const I, window2d)
- q_l_fwd,
- q_r_fwd,
- q_l_bkd,
- q_r_bkd,
- q_top_up,
- q_bot_up,
- q_top_down,
- q_bot_down;
-
-
- std::vector<move_fun> moves;
- std::vector<dpsite> dps;
-
- erosion_arbitrary_2d_fastest_functor(const I& input, const W& win)
- : input(input),
- win(win),
- accu(),
-
- win_left_fwd(win::shift(win, mln::left) - win),
- win_right_fwd(win - win::shift(win, mln::left)),
- win_left_bkd(win::shift(win_left_fwd, mln::right)),
- win_right_bkd(win::shift(win_right_fwd, mln::right)),
-
- win_bot_up(win::shift(win, mln::down) - win),
- win_top_up(win - win::shift(win, mln::down)),
- win_bot_down(win::shift(win_bot_up, mln::up)),
- win_top_down(win::shift(win_top_up, mln::up)),
-
- q_l_fwd(input, win_left_fwd, p),
- q_r_fwd(input, win_right_fwd, p),
- q_l_bkd(input, win_left_bkd, p),
- q_r_bkd(input, win_right_bkd, p),
-
- q_top_up(input, win_top_up, p),
- q_bot_up(input, win_bot_up, p),
- q_top_down(input, win_top_down, p),
- q_bot_down(input, win_bot_down, p),
-
- moves(3),
- dps(3)
- {
- if (win_bot_up.size() + win_top_up.size() +
- win_bot_down.size() + win_top_down.size() <
- win_left_fwd.size() + win_right_fwd.size() +
- win_left_bkd.size() + win_right_bkd.size())
- {
- // Vertical snake
- dps[0] = mln::right;
- dps[1] = mln::down;
- dps[2] = mln::up;
- moves[0] = &self::right;
- moves[1] = &self::down;
- moves[2] = &self::up;
- }
- else
- {
- // Horizontal snake
- dps[0] = mln::down;
- dps[1] = mln::right;
- dps[2] = mln::left;
- moves[0] = &self::down;
- moves[1] = &self::right;
- moves[2] = &self::left;
- }
- }
-
- void init()
- {
- // extension::adjust_fill is performed in the routine
- // because it has to be done before the initialization of
- // the fast iterators (q_*).
- initialize(output, input);
- accu.init();
- p = input.domain().pmin() - dps[0];
- mln_qixter(const I, W) q(input, win, p);
- for_all(q)
- accu.take(q.val());
- p = input.domain().pmin();
- }
-
- void right()
- {
- for_all(q_l_fwd)
- accu.untake(q_l_fwd.val());
- for_all(q_r_fwd)
- accu.take(q_r_fwd.val());
- output(p) = accu;
- }
-
- void left()
- {
- for_all(q_r_bkd)
- accu.untake(q_r_bkd.val());
- for_all(q_l_bkd)
- accu.take(q_l_bkd.val());
- output(p) = accu;
- }
-
- void down()
- {
- for_all(q_top_down)
- accu.untake(q_top_down.val());
- for_all(q_bot_down)
- accu.take(q_bot_down.val());
- output(p) = accu;
- }
-
- void up()
- {
- for_all(q_bot_up)
- accu.untake(q_bot_up.val());
- for_all(q_top_up)
- accu.take(q_top_up.val());
- output(p) = accu;
- }
- };
-
- template <typename I, typename W>
- inline
- mln_concrete(I)
- erosion_arbitrary_2d_fastest(const Image<I>& input, const
Window<W>& win)
- {
- trace::entering("morpho::impl:erosion_arbitrary_2d_fastest");
-
- typedef mlc_is(mln_trait_image_kind(I),
- trait::image::kind::binary) is_binary;
- typedef mlc_if(is_binary, accu::land, accu::min_h<mln_value(I)>) A;
-
- extension::adjust_fill(input,
- geom::delta(win) + 1,
- A());
-
- typedef erosion_arbitrary_2d_fastest_functor<I, W, A> F;
- F f(exact(input), exact(win));
- canvas::browsing::snake_generic(f);
-
- trace::exiting("morpho::impl:erosion_arbitrary_2d_fastest");
-
- return f.output;
- }
-
-
- template <typename I, typename W, typename A>
- struct erosion_arbitrary_2d_functor
- {
- typedef erosion_arbitrary_2d_functor<I,W, A> self;
- typedef void (self::*move_fun)();
- typedef mln_deduce(I, psite, delta) dpsite;
-
- const I& input;
- const W& win;
- mln_concrete(I) output;
- A accu;
-
- mln_psite(I) p;
-
- window2d
- win_left_fwd,
- win_right_fwd,
- win_left_bkd,
- win_right_bkd,
- win_bot_up,
- win_top_up,
- win_bot_down,
- win_top_down;
-
- mln_qiter(window2d)
- q_l_fwd,
- q_r_fwd,
- q_l_bkd,
- q_r_bkd,
- q_top_up,
- q_bot_up,
- q_top_down,
- q_bot_down;
-
- std::vector<move_fun> moves;
- std::vector<dpsite> dps;
-
- erosion_arbitrary_2d_functor(const I& input, const W& win)
- : input(input),
- win(win),
- accu(),
-
- win_left_fwd(win::shift(win, mln::left) - win),
- win_right_fwd(win - win::shift(win, mln::left)),
- win_left_bkd(win::shift(win_left_fwd, mln::right)),
- win_right_bkd(win::shift(win_right_fwd, mln::right)),
-
- win_bot_up(win::shift(win, mln::down) - win),
- win_top_up(win - win::shift(win, mln::down)),
- win_bot_down(win::shift(win_bot_up, mln::up)),
- win_top_down(win::shift(win_top_up, mln::up)),
-
- q_l_fwd(win_left_fwd, p),
- q_r_fwd(win_right_fwd, p),
- q_l_bkd(win_left_bkd, p),
- q_r_bkd(win_right_bkd, p),
-
- q_top_up(win_top_up, p),
- q_bot_up(win_bot_up, p),
- q_top_down(win_top_down, p),
- q_bot_down(win_bot_down, p),
-
- moves(3),
- dps(3)
- {
- if (win_bot_up.size() + win_top_up.size() +
- win_bot_down.size() + win_top_down.size() <
- win_left_fwd.size() + win_right_fwd.size() +
- win_left_bkd.size() + win_right_bkd.size())
- {
- // Vertical snake
- dps[0] = mln::right;
- dps[1] = mln::down;
- dps[2] = mln::up;
- moves[0] = &self::right;
- moves[1] = &self::down;
- moves[2] = &self::up;
- }
- else
- {
- // Horizontal snake
- dps[0] = mln::down;
- dps[1] = mln::right;
- dps[2] = mln::left;
- moves[0] = &self::down;
- moves[1] = &self::right;
- moves[2] = &self::left;
- }
- }
-
- void init()
- {
- extension::adjust_fill(input, win, accu);
- initialize(output, input);
- accu.init();
- p = input.domain().pmin() - dps[0];
- mln_qiter(W) q(win, p);
- for_all(q)
- accu.take(input(q));
- p = input.domain().pmin();
- }
-
- void right()
- {
- for_all(q_l_fwd)
- accu.untake(input(q_l_fwd));
- for_all(q_r_fwd)
- accu.take(input(q_r_fwd));
- output(p) = accu;
- }
-
- void left()
- {
- for_all(q_r_bkd)
- accu.untake(input(q_r_bkd));
- for_all(q_l_bkd)
- accu.take(input(q_l_bkd));
- output(p) = accu;
- }
-
- void down()
- {
- for_all(q_top_down)
- accu.untake(input(q_top_down));
- for_all(q_bot_down)
- accu.take(input(q_bot_down));
- output(p) = accu;
- }
-
- void up()
- {
- for_all(q_bot_up)
- accu.untake(input(q_bot_up));
- for_all(q_top_up)
- accu.take(input(q_top_up));
- output(p) = accu;
- }
-
- };
template <typename I, typename W>
inline
@@ -592,203 +258,39 @@
{
trace::entering("morpho::impl:erosion_arbitrary_2d");
- typedef erosion_arbitrary_2d_functor<I, W, accu::min_h<mln_value(I)> > F;
- F f(exact(input), exact(win));
- canvas::browsing::snake_generic(f);
-
- trace::exiting("morpho::impl:erosion_arbitrary_2d");
-
- return f.output;
- }
-
-
- template <typename Dp>
- Dp dp_directional(int dir)
- {
- Dp dp = literal::zero;
- dp[dir] = 1;
- return dp;
- }
-
- template <typename I_, typename W, typename A>
- struct erosion_directional_nd_functor
- {
- typedef I_ I;
- typedef mln_deduce(I, psite, delta) dpsite;
-
- const I& input;
- const W& win;
- mln_concrete(I) output;
- A accu;
- enum { dim = I::site::dim };
-
- mln_psite(I) p;
- unsigned dir;
-
- window2d
- win_left,
- win_right;
-
- mln_qiter(window2d)
- q_l,
- q_r;
-
- erosion_directional_nd_functor(const I& input, const W& win, int dir)
- : input(input),
- win(win),
- accu(),
- dir(dir),
- win_left(win::shift(win, -dp_directional<dpsite>(dir)) - win),
- win_right(win - win::shift(win, -dp_directional<dpsite>(dir))),
- q_l(win_left, p),
- q_r(win_right, p)
- {
-
- }
-
- void init()
- {
- extension::adjust_fill(input, win, accu);
- initialize(output, input);
- }
-
- void init_run()
- {
- accu.init();
- p[dir]--;
- mln_qiter(W) q(win, p);
- for_all(q) if (input.has(q))
- accu.take(input(q));
- p[dir]++;
- }
-
- void next()
- {
- for_all(q_l) if (input.has(q_l))
- accu.untake(input(q_l));
- for_all(q_r) if (input.has(q_r))
- accu.take(input(q_r));
- output(p) = accu;
- }
-
- void final()
- {
- }
-
- };
-
- template <typename I, typename W>
- inline
- mln_concrete(I)
- erosion_directional_nd(const Image<I>& input, const Window<W>&
win, unsigned dir)
- {
- trace::entering("morpho::impl:erosion_directional_nd");
-
- typedef mlc_is(mln_trait_image_kind(I),
- trait::image::kind::binary) is_binary;
+ typedef mlc_is(mln_trait_image_kind(I), trait::image::kind::binary) is_binary;
typedef mlc_if(is_binary, accu::land, accu::min_h<mln_value(I)>) A;
+ A a;
- typedef erosion_directional_nd_functor<I, W, A> F;
- F f(exact(input), exact(win), dir);
- canvas::browsing::directional(f);
-
- trace::exiting("morpho::impl:erosion_directional_nd");
-
- return f.output;
- }
-
-
- template <typename I_, typename W, typename A>
- struct erosion_directional_nd_fastest_functor
- {
- typedef I_ I;
- typedef mln_deduce(I, psite, delta) dpsite;
-
- const I& input;
- const W& win;
- mln_concrete(I) output;
- A accu;
-
- mln_psite(I) p;
- enum { dim = I::site::dim };
- unsigned dir;
-
- window2d win_left, win_right;
-
- mln_qixter(const I, window2d) q_l, q_r;
-
- erosion_directional_nd_fastest_functor(const I& input, const W& win, unsigned
dir)
- : input(input),
- win(win),
- accu(),
- dir(dir),
- win_left(win::shift(win, -dp_directional<dpsite>(dir)) - win),
- win_right(win - win::shift(win, -dp_directional<dpsite>(dir))),
- q_l(input, win_left, p),
- q_r(input, win_right, p)
- {
- }
-
- void init()
- {
- // extension::adjust_fill is performed in the routine
- // because it has to be done before the initialization of
- // the fast iterators (q_l and q_r).
- initialize(output, input);
- }
-
- void next()
- {
- for_all(q_l)
- accu.untake(q_l.val());
- for_all(q_r)
- accu.take(q_r.val());
- output(p) = accu;
- }
-
+ extension::adjust_fill(input, geom::delta(win) + 1, a);
+ mln_concrete(I) output = accu::snake_2d(a, input, win);
- void init_run()
- {
- accu.init();
- p[dir]--;
- mln_qixter(const I, W) q(input, win, p);
- for_all(q)
- accu.take(q.val());
- p[dir]++;
- }
-
- void final()
- {
+ trace::exiting("morpho::impl:erosion_arbitrary_2d");
+ return output;
}
- };
template <typename I, typename W>
inline
mln_concrete(I)
- erosion_directional_nd_fastest(const Image<I>& input, const
Window<W>& win, unsigned dir)
+ erosion_directional(const Image<I>& input, const Window<W>&
win, unsigned dir)
{
- trace::entering("morpho::impl:erosion_directional_nd_fastest");
+ trace::entering("morpho::impl:erosion_directional");
- typedef mlc_is(mln_trait_image_kind(I),
- trait::image::kind::binary) is_binary;
+ typedef mlc_is(mln_trait_image_kind(I), trait::image::kind::binary) is_binary;
typedef mlc_if(is_binary, accu::land, accu::min_h<mln_value(I)>) A;
+ A a;
- extension::adjust_fill(input,
- geom::delta(win) + 1,
- A());
-
- typedef erosion_directional_nd_fastest_functor<I, W, A> F;
- F f(exact(input), exact(win), dir);
- canvas::browsing::directional(f);
-
- trace::exiting("morpho::impl:erosion_directional_nd_fastest");
+ extension::adjust_fill(input, geom::delta(win) + 1, a);
+ mln_concrete(I) output = accu::transform_directional(a, input, win, dir);
- return f.output;
+ trace::exiting("morpho::impl:erosion_directional");
+ return output;
}
+
// Diagonal2d non fastest.
template <typename I_, typename W, typename A>
struct erosion_diagonal2d_functor
@@ -1172,68 +674,6 @@
}
- // dispatch for arbitrary elements
-
- 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)
- {
- trace::entering("morpho::erosion_dispatch_for_arbitrary");
- mln_concrete(I) ima =
- erosion_dispatch_for_arbitrary(mln_trait_image_speed(I)(),
- input, win);
- trace::exiting("morpho::erosion_dispatch_for_arbitrary");
- return ima;
- }
-
-
-
- // dispatch for directional_nd w.r.t. speed
-
- template <typename I, typename W>
- mln_concrete(I)
- erosion_dispatch_for_directional(trait::image::speed::fastest,
- const I& input, const W& win, unsigned dir)
- {
- return impl::erosion_directional_nd_fastest(input, win, dir);
- }
-
- template <typename I, typename W>
- mln_concrete(I)
- erosion_dispatch_for_directional(trait::image::speed::any,
- const I& input, const W& win, unsigned dir)
- {
- return impl::erosion_directional_nd(input, win, dir);
- }
-
- template <typename I, typename W>
- mln_concrete(I)
- erosion_dispatch_for_directional(const I& input, const W& win, unsigned
dir)
- {
- trace::entering("morpho::erosion_dispatch_for_directional");
- mln_concrete(I) ima =
- erosion_dispatch_for_directional(mln_trait_image_speed(I)(),
- input, win, dir);
- trace::exiting("morpho::erosion_dispatch_for_directional");
- return ima;
- }
-
// dispatch for diagonal2d w.r.t. speed
@@ -1305,7 +745,7 @@
erosion_dispatch_wrt_arbitrary_win(metal::true_,
const I& input, const W& win)
{
- return erosion_dispatch_for_arbitrary(input, win);
+ return morpho::impl::erosion_arbitrary_2d(input, win);
}
template <typename I, typename W>
@@ -1351,7 +791,7 @@
erosion_dispatch_wrt_win(const I& input, const win::octagon2d& win)
{
if (win.length() < 5)
- return erosion_dispatch_for_arbitrary(input, win);
+ return morpho::impl::erosion_arbitrary_2d(input, win);
else
return impl::erosion_octagon2d(input, win);
}
@@ -1365,7 +805,7 @@
erosion_dispatch_wrt_win(metal::true_,
const I& input, const win::hline2d& win)
{
- return erosion_dispatch_for_directional(input, win, 1);
+ return impl::erosion_directional(input, win, 1);
}
template <typename I>
@@ -1405,7 +845,7 @@
erosion_dispatch_wrt_win(metal::true_,
const I& input, const win::vline2d& win)
{
- return erosion_dispatch_for_directional(input, win, 0);
+ return impl::erosion_directional(input, win, 0);
}
template <typename I>
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh (revision 2879)
+++ mln/morpho/includes.hh (working copy)
@@ -51,8 +51,10 @@
# include <mln/accu/max_h.hh>
# include <mln/accu/rank.hh>
+# include <mln/accu/snake_2d.hh>
# include <mln/accu/transform.hh>
# include <mln/accu/transform_stop.hh>
+# include <mln/accu/transform_directional.hh>
# include <mln/fun/v2v/saturate.hh>