URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-18 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Merge leveling and algebraic filters into connected filter.
* mln/canvas/morpho/connected_filter.hh: File merging the
two filters.
* sandbox/edwin/filtres/connectes/connected_filter.hh: Add
static tests about accumaltors properties when calling directly
algebraic and leveling filters. Add leveling and algebraic facade.
* sandbox/edwin/filtres/connectes/filter.cc: Fix bugs.
* tests/canvas/morpho/connected_filter.cc: Test file for
connected filters.
---
mln/canvas/morpho/connected_filter.hh | 601 ++++++++++++++++++++
sandbox/edwin/filtres/connectes/connected_filter.hh | 45 +
sandbox/edwin/filtres/connectes/filter.cc | 40 +
tests/canvas/morpho/connected_filter.cc | 75 ++
4 files changed, 755 insertions(+), 6 deletions(-)
Index: trunk/milena/tests/canvas/morpho/connected_filter.cc
===================================================================
--- trunk/milena/tests/canvas/morpho/connected_filter.cc (revision 0)
+++ trunk/milena/tests/canvas/morpho/connected_filter.cc (revision 3382)
@@ -0,0 +1,75 @@
+
+
+#include <mln/core/image/image2d.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/util/timer.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/morpho/attribute/volume.hh>
+#include <mln/morpho/attribute/card.hh>
+#include "connected_filter.hh"
+
+int main(int argc, char** argv)
+{
+ using namespace mln;
+ using value::int_u8;
+
+ std::cout << "Leveling filter test" << std::endl;
+
+ typedef mln::image2d<int_u8> I;
+ I lena;
+
+ float elapsed;
+ mln::util::timer chrono;
+ mln::morpho::attribute::volume<I> c;
+ mln::morpho::attribute::card<I> c2;
+ int lambda = atoi(argv[1]);
+
+ mln::io::pgm::load(lena, "../../../../img/lena.pgm");
+ I out;
+
+ std::cout << "Test algebraic" << std::endl;
+ chrono.start();
+ out = mln::canvas::morpho::connected_filter(lena, c4(), c2, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(auto) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "alg_auto.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::algebraic_filter(lena, c4(), c2, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(fast) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "alg_fast.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::algebraic_filter(lena, c4(), c2, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(slow) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "alg_slow.pgm");
+
+// Try force algebraic dispatch with wrong accu (volume).
+// out = mln::canvas::morpho::algebraic_filter(lena, c4(), c, lambda, true);
+
+ std::cout << "Test leveling" << std::endl;
+ chrono.start();
+ out = mln::canvas::morpho::connected_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(auto) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_auto.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(fast) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_fast.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(slow) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_slow.pgm");
+
+// Try force leveling dispatch with wrong accu (card).
+// mln::canvas::morpho::leveling_filter(lena, c4(), c2, lambda, true);
+
+
+}
Index: trunk/milena/mln/canvas/morpho/connected_filter.hh
===================================================================
--- trunk/milena/mln/canvas/morpho/connected_filter.hh (revision 0)
+++ trunk/milena/mln/canvas/morpho/connected_filter.hh (revision 3382)
@@ -0,0 +1,601 @@
+// Copyright (C) 2007, 2008, 2009 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_CANVAS_MORPHO_CONNECTED_FILTER_HH
+# define MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH
+
+/// \file mln/canvas/morpho/connected_filter.hh
+///
+/// Connected filters dispatch (algebraic & leveling filters).
+///
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/concept/accumulator.hh>
+
+# include <mln/trait/accumulators.hh>
+
+# include <mln/level/sort_psites.hh>
+# include <mln/level/sort_offsets.hh>
+
+
+namespace mln {
+ namespace canvas {
+ namespace morpho {
+
+ // Facade Fwd Declaration
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ connected_filter(const Image<I>& input, const Neighborhood<N>&
nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input, const Neighborhood<N>&
nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ algebraic_filter(const Image<I>& input, const Neighborhood<N>&
nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl {
+
+ template <typename A, typename I>
+ void take_as_init_fastest (trait::accumulator::when_pix::use_none, A& accu,
+ const I& input, const unsigned p)
+ {
+ accu.take_as_init ();
+ }
+
+ template <typename A, typename I, typename P>
+ void take_as_init (trait::accumulator::when_pix::use_p, A& accu,
+ const I& input, const P& p)
+ {
+ accu.take_as_init (p);
+ }
+
+ template <typename A, typename I, typename P>
+ void take_as_init (trait::accumulator::when_pix::use_none, A& accu,
+ const I& input, const P& p)
+ {
+ accu.take_as_init (p);
+ }
+
+ template <typename A, typename I, typename P>
+ void take_as_init (trait::accumulator::when_pix::use_pix, A& accu,
+ const I& input, const P& p)
+ {
+ accu.take_as_init (make::pix(input, p));
+ }
+
+ template <typename A, typename I, typename P>
+ void take_as_init (trait::accumulator::when_pix::use_v, A& accu,
+ const I& input, const P& p)
+ {
+ accu.take_as_init (make::pix(input, p));
+ }
+
+ template <typename A, typename I>
+ void take_as_init_fastest (trait::accumulator::when_pix::use_v, A& accu,
+ const I& input, const unsigned p)
+ {
+ accu.take_as_init (input.element (p));
+ }
+
+
+ template <typename A, typename I, typename P>
+ void take_as_init (A& accu, const I& input, const P& p)
+ {
+ take_as_init (mln_trait_accumulator_when_pix(A)(), accu, input, p);
+ }
+
+ template <typename A, typename I, typename P>
+ void take_as_init_fastest (A& accu, const I& input, const P& p)
+ {
+ take_as_init_fastest (mln_trait_accumulator_when_pix(A)(), accu, input, p);
+ }
+
+
+ namespace generic {
+
+
+ ////////////////////////
+ /// Generic version. ///
+ ////////////////////////
+
+
+ template <typename I>
+ static inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I) & x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+ template <typename I, typename N, typename S, typename A>
+ mln_concrete(I)
+ connected_filter (const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_,
+ const Accumulator<A>& a_,
+ const typename A::result& lambda)
+ {
+ trace::entering("canvas::morpho::impl::generic::connected_filter");
+ // FIXME: Test?!
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
+ (void)a_; // To avoid warning at compilation
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, P) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ initialize(data, input);
+ //a.init(); // init required.
+ }
+
+ // First pass.
+ {
+ mln_fwd_piter(S) p(s); // s required.
+ mln_niter(N) n(nbh, p);
+
+ for_all(p)
+ {
+ // Make set.
+ {
+ parent(p) = p;
+
+ // Check accumulator trait to handle argument type (Pix or Site).
+ take_as_init (data(p), input, p);
+ }
+
+ for_all(n)
+ if (input.domain().has(n) && deja_vu(n))
+ {
+ //do_union(n, p);
+ P r = find_root(parent, n);
+ if (r != p)
+ {
+ if (input(r) == input(p) || (activity(r) && (data(r) < lambda))) //
Equiv(r, p)
+ // Either a flat zone or the component of r is still growing.
+ {
+ /* FIXME: Same remark as above concerning the
+ initialization of data(p); instead of
+
+ data(p).take(data(r));
+
+ we should (or could) have
+
+ unite_data(p, r);
+
+ so as to keep the generic aspect of this canvas
+ (as long as the set of acceptable types for the
+ template parameter A is not bound). */
+
+ data(p).take(data(r));
+ parent(r) = p;
+ if (activity(r) == false)
+ activity(p) = false;
+ }
+ else
+ {
+ activity(p) = false;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ if (parent(p) == p) // p is root.
+ output(p) = input(p);
+ else
+ output(p) = output(parent(p));
+ }
+
+ trace::exiting("canvas::morpho::impl::generic::connected_filter");
+ return output;
+ }
+
+ } // end of namespace mln::canvas::morpho::impl::generic
+
+
+ ////////////////////////
+ /// Fastest version. ///
+ ////////////////////////
+
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x)
+ {
+ if (parent.element(x) == x)
+ return x;
+ else
+ return parent.element(x) = find_root_fastest(parent, parent.element(x));
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ connected_filter_fastest(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const util::array<unsigned>& s,
+ const Accumulator<A>& a_,
+ const typename A::result& lambda)
+ {
+ trace::entering("canvas::morpho::impl::connected_filter_fastest");
+
+ // FIXME: Tests?
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, unsigned) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ mln::data::fill(parent, 0);
+ initialize(data, input);
+ }
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+ const unsigned n_points = s.nelements();
+
+ // First pass.
+ {
+ for (unsigned i = 0; i < n_points; ++i)
+ {
+ unsigned p = s[i]; // An offset.
+
+ // Make set.
+ parent.element(p) = p;
+
+ // Check accumulator trait to handle argument type (Value or None).
+ take_as_init_fastest (data.element(p), input, p);
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (!deja_vu.element(n))
+ continue;
+
+ unsigned r = find_root_fastest(parent, n);
+ if (r != p)
+ {
+ if (input.element(r) == input.element(p)
+ || (activity.element(r)
+ && (data.element(r) < lambda)))
+ {
+ data.element(p).take(data.element(r));
+ parent.element(r) = p;
+ if (activity.element(r) == false)
+ activity.element(p) = false;
+ }
+ else
+ activity.element(p) = false;
+ }
+ }
+
+ deja_vu.element(p) = true;
+ }
+ }
+
+
+ // Second pass.
+ {
+ for (int i = n_points - 1; i >= 0 ; --i)
+ {
+ unsigned p = s[i];
+ if (parent.element(p) == p) // p is root.
+ output.element(p) = input.element(p);
+ else
+ output.element(p) = output.element(parent.element(p));
+ }
+ }
+
+ trace::exiting("canvas::morpho::impl::connected_filter_fastest");
+ return output;
+ }
+
+
+ } // end of namespace mln::canvas::morpho::impl
+
+
+
+
+ // Dispatch.
+
+
+ namespace internal
+ {
+ // Leveling
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter_dispatch(metal::false_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ p_array < mln_psite(I) > s =
+ increasing ?
+ level::sort_psites_increasing(input) :
+ level::sort_psites_decreasing(input);
+ return impl::generic::connected_filter(input, nbh, s, a, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter_dispatch(metal::true_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ util::array<unsigned> s =
+ increasing ?
+ level::sort_offsets_increasing(input) :
+ level::sort_offsets_decreasing(input);
+ return impl::connected_filter_fastest(input, nbh, s, a, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ leveling_filter_dispatch(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ mlc_or(mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_pix),
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_v))::check();
+
+ enum
+ {
+ test = mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value
+ && mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_v)::value
+ && mln_is_simple_neighborhood(N)::value
+ };
+ return leveling_filter_dispatch(metal::bool_<test>(),
+ input, nbh, a, lambda, increasing);
+ }
+
+ // Alegebraic
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_filter_dispatch(metal::false_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ const mln_result(A)& lambda,
+ bool increasing)
+ {
+ p_array<mln_psite(I)> s = increasing ?
+ level::sort_psites_increasing(input) :
+ level::sort_psites_decreasing(input);
+ return impl::generic::connected_filter(input, nbh, s, accu, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_filter_dispatch(metal::true_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ const mln_result(A)& lambda,
+ bool increasing)
+ {
+ util::array<unsigned> s = increasing ?
+ level::sort_offsets_increasing(input) :
+ level::sort_offsets_decreasing(input);
+ return impl::connected_filter_fastest(input, nbh, s, accu, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_filter_dispatch(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ const mln_result(A)& lambda,
+ bool increasing)
+ {
+ mlc_or(mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_none),
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_p))::check();
+
+ enum {
+ test = (mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value &&
+ mln_is_simple_neighborhood(N)::value &&
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_none)::value)
+ };
+ return algebraic_filter_dispatch(metal::bool_<test>(), input, nbh,
+ accu, lambda, increasing);
+ }
+
+
+
+ //connected
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_none,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_p,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_v,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ connected_filter_dispatch(mln::trait::accumulator::when_pix::use_pix,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+ } // end of namespace mln::canvas::morpho::internal
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ // Facade.
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ connected_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return internal::connected_filter_dispatch(mln_trait_accumulator_when_pix(A)(),
+ input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ algebraic_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return internal::algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return internal::leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+
+
+ } // end of namespace mln::canvas::morpho
+ } // end of namespace mln::canvas
+} // end of namespace mln
+
+
+#endif // ! MLN_CANVAS_MORPHO_CONNECTED_FILTER_HH
Index: trunk/milena/sandbox/edwin/filtres/connectes/connected_filter.hh
===================================================================
--- trunk/milena/sandbox/edwin/filtres/connectes/connected_filter.hh (revision 3381)
+++ trunk/milena/sandbox/edwin/filtres/connectes/connected_filter.hh (revision 3382)
@@ -54,6 +54,18 @@
const Accumulator<A>& a, const typename A::result& lambda,
bool increasing);
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input, const Neighborhood<N>&
nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ algebraic_filter(const Image<I>& input, const Neighborhood<N>&
nbh,
+ const Accumulator<A>& a, const typename A::result& lambda,
+ bool increasing);
+
# ifndef MLN_INCLUDE_ONLY
namespace impl {
@@ -409,6 +421,11 @@
const typename A::result& lambda,
bool increasing)
{
+ mlc_or(mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_pix),
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_v))::check();
+
enum
{
test = mlc_equal(mln_trait_image_speed(I),
@@ -463,6 +480,11 @@
const mln_result(A)& lambda,
bool increasing)
{
+ mlc_or(mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_none),
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_p))::check();
+
enum {
test = (mlc_equal(mln_trait_image_speed(I),
trait::image::speed::fastest)::value &&
@@ -547,6 +569,29 @@
input, nbh, a, lambda, increasing);
}
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ algebraic_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return internal::algebraic_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ leveling_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& a,
+ const typename A::result& lambda,
+ bool increasing)
+ {
+ return internal::leveling_filter_dispatch(input, nbh, a, lambda, increasing);
+ }
+
+
} // end of namespace mln::canvas::morpho
} // end of namespace mln::canvas
Index: trunk/milena/sandbox/edwin/filtres/connectes/filter.cc
===================================================================
--- trunk/milena/sandbox/edwin/filtres/connectes/filter.cc (revision 3381)
+++ trunk/milena/sandbox/edwin/filtres/connectes/filter.cc (revision 3382)
@@ -5,6 +5,7 @@
#include <mln/util/timer.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/morpho/attribute/volume.hh>
+#include <mln/morpho/attribute/card.hh>
#include "connected_filter.hh"
int main(int argc, char** argv)
@@ -20,28 +21,55 @@
float elapsed;
mln::util::timer chrono;
mln::morpho::attribute::volume<I> c;
+ mln::morpho::attribute::card<I> c2;
int lambda = atoi(argv[1]);
mln::io::pgm::load(lena, "../../../../img/lena.pgm");
I out;
+ std::cout << "Test algebraic" << std::endl;
chrono.start();
- out = mln::canvas::morpho::connected_filter(lena, c4(), c, lambda, true);
+ out = mln::canvas::morpho::connected_filter(lena, c4(), c2, lambda, true);
elapsed = chrono.stop();
std::cout << "(auto) " << elapsed << "s" <<
std::endl;
- mln::io::pgm::save(out, "auto.pgm");
+ mln::io::pgm::save(out, "alg_auto.pgm");
chrono.start();
- out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::true_(),
lena, c4(), c, lambda, true);
+ out = mln::canvas::morpho::algebraic_filter(lena, c4(), c2, lambda, true);
elapsed = chrono.stop();
std::cout << "(fast) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "alg_fast.pgm");
+
+ chrono.start();
+ out = mln::canvas::morpho::algebraic_filter(lena, c4(), c2, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(slow) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "alg_slow.pgm");
+
+// Try force algebraic dispatch with wrong accu (volume).
+// out = mln::canvas::morpho::algebraic_filter(lena, c4(), c, lambda, true);
+
+ std::cout << "Test leveling" << std::endl;
+ chrono.start();
+ out = mln::canvas::morpho::connected_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(auto) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_auto.pgm");
- mln::io::pgm::save(out, "fast.pgm");
+ chrono.start();
+ out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true);
+ elapsed = chrono.stop();
+ std::cout << "(fast) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_fast.pgm");
chrono.start();
- out = mln::canvas::morpho::internal::leveling_filter_dispatch(mln::metal::false_(),
lena, c4(), c, lambda, true);
+ out = mln::canvas::morpho::leveling_filter(lena, c4(), c, lambda, true);
elapsed = chrono.stop();
std::cout << "(slow) " << elapsed << "s" <<
std::endl;
+ mln::io::pgm::save(out, "lev_slow.pgm");
+
+// Try force leveling dispatch with wrong accu (card).
+// mln::canvas::morpho::leveling_filter(lena, c4(), c2, lambda, true);
+
- mln::io::pgm::save(out, "slow.pgm");
}