
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Some cleanups in classical filters. * mln/data/memcpy_.hh: Deactivate trace. This internal routine floods the trace file because it can be called in a loop. * mln/linear/gaussian.hh (class): Replace by... (typename): ...this. See sandbox/theo/exec/ for a fastest implementation. * mln/accu/transform_line.hh (transform_line_fastest): New. * mln/morpho/rank_filter.hh (rank_filter_line): New. (rank_filter_dispatch): New overload for rectangle2d. * mln/morpho/includes.hh: Update. * img/BUG_lean_ascii.pgm.gz: New. This file makes io::pgm::load bug. mln/accu/transform_line.hh | 149 ++++++++++++++++++++++++++++++++++++++++++++- mln/data/memcpy_.hh | 12 +-- mln/linear/gaussian.hh | 22 ++++-- mln/morpho/includes.hh | 5 - mln/morpho/rank_filter.hh | 62 ++++++++++++++++-- 5 files changed, 226 insertions(+), 24 deletions(-) Index: mln/data/memcpy_.hh --- mln/data/memcpy_.hh (revision 3553) +++ mln/data/memcpy_.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory -// (LRDE) +// 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 @@ -78,7 +78,7 @@ inline void memcpy__(Pd& dest, const Ps& src, std::size_t n) { - trace::entering("data::impl::memcpy__"); + // trace::entering("data::impl::memcpy__"); typedef mln_image(Pd) Id; typedef mln_image(Ps) Is; @@ -105,7 +105,7 @@ *p_d++ = *p_s++; } - trace::exiting("data::impl::memcpy__"); + // trace::exiting("data::impl::memcpy__"); } } @@ -116,7 +116,7 @@ const Generalized_Pixel<Ps>& src_, std::size_t n) { - trace::entering("data::memcpy_"); + // trace::entering("data::memcpy_"); typedef mln_image(Pd) Id; metal::is_not_const<Id>::check(); @@ -143,7 +143,7 @@ impl::memcpy__(dest, src, n); - trace::exiting("data::memcpy_"); + // trace::exiting("data::memcpy_"); } # endif // ! MLN_INCLUDE_ONLY Index: mln/linear/gaussian.hh --- mln/linear/gaussian.hh (revision 3553) +++ mln/linear/gaussian.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2001, 2002, 2003, 2004, 2008 EPITA Research and +// Copyright (C) 2001, 2002, 2003, 2004, 2008, 2009 EPITA Research and // Laboratory (LRDE) // // This file is part of the Olena Library. This library is free @@ -63,10 +63,16 @@ /// /// \pre output.domain = input.domain /// - template <class I> + template <typename I> mln_concrete(I) gaussian(const Image<I>& input, float sigma); + + template <typename I> + mln_concrete(I) + gaussian(const Image<I>& input, float sigma, int dir); + + # ifndef MLN_INCLUDE_ONLY namespace impl @@ -637,7 +643,7 @@ * \pre input.is_valid * \pre dir < dimension(input) */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian(const Image<I>& input, float sigma, int dir) @@ -669,7 +675,7 @@ * \pre input.is_valid * \pre dir < dimension(input) */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian_1st_derivative(const Image<I>& input, float sigma, int dir) @@ -702,7 +708,7 @@ * \pre input.is_valid * \pre dir < dimension(input) */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian_2nd_derivative(const Image<I>& input, float sigma, int dir) @@ -734,7 +740,7 @@ * * \pre input.is_valid */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian(const Image<I>& input, float sigma) @@ -763,7 +769,7 @@ * * \pre input.is_valid */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian_1st_derivative(const Image<I>& input, float sigma) @@ -791,7 +797,7 @@ * * \pre input.is_valid */ - template <class I> + template <typename I> inline mln_concrete(I) gaussian_2nd_derivative(const Image<I>& input, float sigma) Index: mln/accu/transform_line.hh --- mln/accu/transform_line.hh (revision 3553) +++ mln/accu/transform_line.hh (working copy) @@ -66,8 +66,10 @@ # ifndef MLN_INCLUDE_ONLY + // Tests. + namespace internal { @@ -89,6 +91,10 @@ } // end of namespace mln::accu::internal + + // Implementations. + + namespace impl { @@ -188,10 +194,150 @@ } // end of namespace mln::accu::impl::generic + + + template <typename A, typename I> + inline + mln_ch_value(I, mln_result(A)) + transform_line_fastest(const Accumulator<A>& a_, + const Image<I>& input_, + unsigned length, unsigned dir) + { + trace::entering("accu::impl::transform_line_fastest"); + + const I& input = exact(input_); + A a = exact(a_); + + internal::transform_line_tests(a, input); + + mln_ch_value(I, mln_result(A)) output; + initialize(output, input); + + typedef mln_psite(I) P; + + mln_delta(P) dp(literal::zero); + dp[dir] = 1; + int step = input.delta_index(dp); + + P pmin = input.domain().pmin(), + pmax = input.domain().pmax(); + const def::coord + pmax_dir = pmax[dir], + pmin_dir = pmin[dir]; + + P p = pmin; // Starting point. + def::coord& p_dir = p[dir]; + + do + { + unsigned o_qu, o_qt; + unsigned o_p = input.index_of_point(p); + + // Start the line. + // ---------------- + + a.take_as_init(input.element(o_p)); + o_qu = o_p; + for (unsigned i = 1; i <= length / 2; ++i) + { + o_qu -= step; + a.take(input.element(o_qu)); + } + o_qt = o_p; + for (unsigned i = 1; i <= length / 2; ++i) + { + o_qt += step; + a.take(input.element(o_qt)); + } + output.element(o_p) = a.to_result(); + + // Browse the line. + // ---------------- + + while (p_dir < pmax_dir) + { + ++p_dir; + + o_p += step; + o_qt += step; + o_qu += step; + + a.take(input.element(o_qt)); + a.untake(input.element(o_qu)); + + output.element(o_p) = a.to_result(); + } + + p_dir = pmin_dir; + + // Go to the next line. + // -------------------- + + for (int c = P::dim - 1; c >= 0; --c) + { + if (c == int(dir)) + continue; + if (p[c] != pmax[c]) + { + ++p[c]; + break; + } + p[c] = pmin[c]; + } + + } while (p != pmin); + + trace::exiting("accu::impl::transform_line_fastest"); + return output; + } + + } // end of namespace mln::accu::impl + + // Dispatch. + + + namespace internal + { + + template <typename A, typename I> + inline + mln_ch_value(I, mln_result(A)) + transform_line_dispatch(trait::image::speed::any, + const Accumulator<A>& a, + const Image<I>& input, + unsigned length, unsigned dir) + { + return impl::generic::transform_line(a, + input, + length, dir); + } + +// template <typename A, typename I> +// inline +// mln_ch_value(I, mln_result(A)) +// transform_line_dispatch(trait::image::speed::fastest, +// const Accumulator<A>& a, +// const Image<I>& input, +// unsigned length, unsigned dir) +// { +// return impl::transform_line_fastest(a, +// input, +// length, dir); +// } + + + } // end of namespace mln::accu::internal + + + + + // Facades. + + template <typename A, typename I> inline mln_ch_value(I, mln_result(A)) @@ -205,7 +351,8 @@ extension::adjust(input, length / 2); mln_ch_value(I, mln_result(A)) output; - output = impl::generic::transform_line(a, input, length, dir); + output = internal::transform_line_dispatch(mln_trait_image_speed(I)(), + a, input, length, dir); trace::exiting("accu::transform_line"); return output; Index: mln/morpho/rank_filter.hh --- mln/morpho/rank_filter.hh (revision 3553) +++ mln/morpho/rank_filter.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory -// (LRDE) +// 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 @@ -31,11 +31,16 @@ /// \file mln/morpho/rank_filter.hh /// -/// Morphological rank_filter. +/// Morphological rank filter. +/// +/// \todo Rely on the same mechanism as erosion/dilation. # include <mln/morpho/includes.hh> +# include <mln/accu/transform_line.hh> # include <mln/convert/to_p_array.hh> + + namespace mln { @@ -51,6 +56,8 @@ # ifndef MLN_INCLUDE_ONLY + // Tests. + namespace internal { @@ -73,6 +80,10 @@ } // end of namespace mln::morpho::internal + + // Implementations. + + namespace impl { @@ -119,9 +130,27 @@ template <typename I, typename W> inline mln_concrete(I) + rank_filter_line(const Image<I>& input, const Window<W>& win, unsigned k, unsigned dir) + { + trace::entering("morpho::impl::rank_filter_line"); + + internal::rank_filter_tests(input, win, k); + + accu::rank<mln_value(I)> accu(k); + extension::adjust_fill(input, geom::delta(win) + 1, accu); + mln_concrete(I) output = accu::transform_line(accu, input, exact(win).length(), dir); + + trace::exiting("morpho::impl::rank_filter_line"); + return output; + } + + + template <typename I, typename W> + inline + mln_concrete(I) rank_filter_directional(const Image<I>& input, const Window<W>& win, unsigned k, unsigned dir) { - trace::entering("morpho::impl::generic::rank_filter_directional"); + trace::entering("morpho::impl::rank_filter_directional"); internal::rank_filter_tests(input, win, k); @@ -129,13 +158,18 @@ extension::adjust_fill(input, geom::delta(win) + 1, accu); mln_concrete(I) output = accu::transform_directional(accu, input, win, dir); - trace::exiting("morpho::impl::generic::rank_filter_directional"); + trace::exiting("morpho::impl::rank_filter_directional"); return output; } + } // end of namespace mln::morpho::impl + + // Dispatch. + + namespace internal { @@ -144,10 +178,22 @@ mln_concrete(I) rank_filter_dispatch(const Image<I>& input, const win::line<M, i, C> & win, unsigned k) { - return impl::rank_filter_directional(input, win, k, i); + return impl::rank_filter_line(input, win, k, i); } - + template <typename I> + inline + mln_concrete(I) + rank_filter_dispatch(const Image<I>& input, const win::rectangle2d& win, unsigned k) + { + if (win.height() <= 3 && win.width() <= 3) + return impl::generic::rank_filter(input, win, k); + else + if (win.height() < win.width()) + return impl::rank_filter_directional(input, win, k, 1); + else + return impl::rank_filter_directional(input, win, k, 0); + } template <typename I, typename W> inline @@ -163,12 +209,14 @@ // Facades. + template <typename I, typename W> inline mln_concrete(I) rank_filter(const Image<I>& input, const Window<W>& win, unsigned k) { trace::entering("morpho::rank_filter"); + mln_precondition(exact(input).is_valid()); mln_precondition(! exact(win).is_empty()); Index: mln/morpho/includes.hh --- mln/morpho/includes.hh (revision 3553) +++ mln/morpho/includes.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory -// (LRDE) +// 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 @@ -49,6 +49,7 @@ # include <mln/accu/transform_directional.hh> # include <mln/accu/transform_diagonal.hh> +# include <mln/accu/transform_line.hh> # include <mln/accu/transform_snake.hh> # include <mln/fun/v2v/saturate.hh> Index: img/BUG_lean_ascii.pgm.gz Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: img/BUG_lean_ascii.pgm.gz ___________________________________________________________________ Added: svn:mime-type + application/octet-stream