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