3141: Cleanup level approx median.

https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Cleanup level approx median. * mln/level/approx/median.hh: Upgrade file doc style. (median): Return output. Revamp. (median_): Remove; awkward. * mln/accu/transform_line.hh (comment): Fix. We deal with lines not runs. (transform_line): Fix extension adjust. * mln/morpho/general.spe.hh (general_line): New impl. (general_dispatch_line): Use it. * tests/level/approx/median.cc: Upgrade file doc style. Augment tests. * tests/morpho/general.cc: Augment tests with hline and vline. mln/accu/transform_line.hh | 14 ++-- mln/level/approx/median.hh | 131 +++++++++++++++++++------------------------ mln/morpho/general.spe.hh | 24 +++++++ tests/level/approx/median.cc | 31 ++++------ tests/morpho/general.cc | 16 ++++- 5 files changed, 117 insertions(+), 99 deletions(-) Index: mln/level/approx/median.hh --- mln/level/approx/median.hh (revision 3140) +++ mln/level/approx/median.hh (working copy) @@ -1,4 +1,5 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 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 @@ -28,10 +29,9 @@ #ifndef MLN_LEVEL_APPROX_MEDIAN_HH # define MLN_LEVEL_APPROX_MEDIAN_HH -/*! \file mln/level/approx/median.hh - * - * \brief Approximates of some median filters of an image. - */ +/// \file mln/level/approx/median.hh +/// +/// Approximates of some median filters of an image. # include <mln/level/median.hh> # include <mln/win/rectangle2d.hh> @@ -44,6 +44,7 @@ #include <time.h> + namespace mln { @@ -58,125 +59,109 @@ * * \param[in] input The image to be filtered. * \param[in] win The rectangle. - * \param[in,out] output The output image. * * The approximation is based on a vertical median ran after * an horizontal median. * * \pre \p input and \p output have to be initialized. */ - template <typename I, typename O> - void median(const Image<I>& input, const win::rectangle2d& win, - Image<O>& output); + template <typename I> + mln_concrete(I) + median(const Image<I>& input, const win::rectangle2d& win); + /*! Compute in \p output an approximate of the median filter of * image \p input by the 2D disk \p win. * * \param[in] input The image to be filtered. * \param[in] win The disk. - * \param[in,out] output The output image. * * The approximation is based on a vertical median and * an horizontal median an two diagonal median. * * \pre \p input and \p output have to be initialized. */ - template <typename I, typename O> - void median(const Image<I>& input, const win::disk2d& win, - Image<O>& output); + template <typename I> + mln_concrete(I) + median(const Image<I>& input, const win::disk2d& win); + /*! Compute in \p output an approximate of the median filter of * image \p input by the 2D octagon \p win. * * \param[in] input The image to be filtered. * \param[in] win The octagon. - * \param[in,out] output The output image. * * The approximation is based on a vertical median and * an horizontal median an two diagonal median. * * \pre \p input and \p output have to be initialized. */ - template <typename I, typename O> - void median(const Image<I>& input, const win::octagon2d& win, - Image<O>& output); + template <typename I> + mln_concrete(I) + median(const Image<I>& input, const win::octagon2d& win); + # ifndef MLN_INCLUDE_ONLY - namespace impl - { - template <typename I, typename O> + // Facades. + + + template <typename I> inline - void median_(const I& input, const unsigned length, - O& output) + mln_concrete(I) + median(const Image<I>& input, const win::rectangle2d& win) { - const unsigned len = length / 3 + 1; + trace::entering("level::approx::median"); - O - tmp1(output.domain()), - tmp2(output.domain()); - { - clock_t c = clock(); - level::median(input, win::diag2d(len), tmp1); - std::cout << "diag " << float(clock() - c) / CLOCKS_PER_SEC << std::endl; - } - { - clock_t c = clock(); - level::median(tmp1, win::backdiag2d(len), tmp2); - std::cout << "back " << float(clock() - c) / CLOCKS_PER_SEC << std::endl; - } - { - clock_t c = clock(); - level::median(tmp2, win::hline2d(len), tmp1); - std::cout << "hlin " << float(clock() - c) / CLOCKS_PER_SEC << std::endl; - } - { - clock_t c = clock(); - level::median(tmp1, win::vline2d(len), output); - std::cout << "vlin " << float(clock() - c) / CLOCKS_PER_SEC << std::endl; - } + mln_concrete(I) output; - } + win::hline2d win1(win.width()); + output = level::median(input, win1); - } // end of namespace mln::level::approx::impl + win::vline2d win2(win.height()); + output = level::median(output, win2); + trace::exiting("level::approx::median"); + return output; + } - // Facades. - template <typename I, typename O> + template <typename I> inline - void median(const Image<I>& input_, const win::rectangle2d& win, - Image<O>& output_) + mln_concrete(I) + median(const Image<I>& input, const win::disk2d& win) { - const I& input = exact(input_); - O& output = exact(output_); - mln_assertion(output.domain() == input.domain()); - - O tmp(output.domain()); - level::median(input, win::hline2d(win.width()), tmp); - level::median(tmp, win::vline2d(win.height()), output); - } + trace::entering("level::approx::median"); - template <typename I, typename O> - inline - void median(const Image<I>& input, const win::disk2d& win, - Image<O>& output) - { - mln_assertion(exact(output).domain() == exact(input).domain()); + const unsigned len = win.length() / 3 + 1; + mln_concrete(I) output; + + win::diag2d win1(len); + output = level::median(input, win1); + + win::backdiag2d win2(len); + output = level::median(output, win2); + + win::hline2d win3(len); + output = level::median(input, win3); - impl::median_(exact(input), win.length(), exact(output)); + win::vline2d win4(len); + output = level::median(output, win4); + + trace::exiting("level::approx::median"); + return output; } - template <typename I, typename O> + + template <typename I> inline - void median(const Image<I>& input, const win::octagon2d& win, - Image<O>& output) + mln_concrete(I) + median(const Image<I>& input, const win::octagon2d& win) { - mln_assertion(exact(output).domain() == exact(input).domain()); - - impl::median_(exact(input), win.length(), exact(output)); + return median(input, win::disk2d(win.length())); } # endif // ! MLN_INCLUDE_ONLY Index: mln/accu/transform_line.hh --- mln/accu/transform_line.hh (revision 3140) +++ mln/accu/transform_line.hh (working copy) @@ -129,7 +129,7 @@ do { - // Start the run. + // Start the line. // --------------- qt = p; @@ -146,8 +146,8 @@ if (input.has(p)) output(p) = a.to_result(); - // Browse the run. - // --------------- + // Browse the line. + // ---------------- while (p_dir < pmax_dir) { @@ -165,8 +165,8 @@ p_dir = pmin_dir; - // Go to the next run. - // ------------------- + // Go to the next line. + // -------------------- for (int c = P::dim - 1; c >= 0; --c) { @@ -203,7 +203,7 @@ internal::transform_line_tests(a, input); - extension::adjust(input, length); + extension::adjust(input, length / 2); mln_ch_value(I, mln_result(A)) output; output = impl::generic::transform_line(a, input, length, dir); @@ -226,7 +226,7 @@ internal::transform_line_tests(a_, input); - extension::adjust(input, length); + extension::adjust(input, length / 2); mln_ch_value(I, mln_result(A_)) output; output = impl::generic::transform_line(a_, input, length, dir); Index: mln/morpho/general.spe.hh --- mln/morpho/general.spe.hh (revision 3140) +++ mln/morpho/general.spe.hh (working copy) @@ -40,6 +40,7 @@ # include <mln/win/rectangle2d.hh> # include <mln/accu/transform_directional.hh> +# include <mln/accu/transform_line.hh> # include <mln/accu/transform_snake.hh> # include <mln/accu/transform_stop.hh> # include <mln/accu/transform_diagonal.hh> @@ -238,7 +239,7 @@ extension::adjust_fill(input, geom::delta(win) + 1, op.neutral(input)); mln_concrete(I) output; - output = accu::transform_directional(op.accu_incr(input), input, win, dir); + output = accu::transform_directional(op.accu_incr(input), input, win, dir); // FIXME: Use _line. trace::exiting("morpho::impl:general_directional"); return output; @@ -248,6 +249,25 @@ template <typename Op, typename I, typename W> inline mln_concrete(I) + general_line(const Op& op, const Image<I>& input, const Window<W>& win_) + { + trace::entering("morpho::impl:general_line"); + + const W& win = exact(win_); + + extension::adjust_fill(input, geom::delta(win), op.neutral(input)); + mln_concrete(I) output; + output = accu::transform_line(op.accu_incr(input), input, + win.length(), win.dir); + + trace::exiting("morpho::impl:general_line"); + return output; + } + + + template <typename Op, typename I, typename W> + inline + mln_concrete(I) general_diagonal_2d(const Op& op, const Image<I>& input, const Window<W>& win) { trace::entering("morpho::impl:general_diagonal_2d"); @@ -398,7 +418,7 @@ general_dispatch_line(metal::true_, const Op& op, const I& input, const W& win) { - return impl::general_directional(op, input, win, W::dir); + return impl::general_line(op, input, win); } template <typename Op, typename I, typename W> Index: tests/level/approx/median.cc --- tests/level/approx/median.cc (revision 3140) +++ tests/level/approx/median.cc (working copy) @@ -1,4 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2007, 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 @@ -25,14 +26,11 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/*! \file tests/level/approx/median.cc - * - * \brief Test on mln::level::approx::median. - */ +/// \file tests/level/approx/median.cc +/// +/// Test on mln::level::approx::median. #include <mln/core/image/image2d.hh> -#include <mln/win/rectangle2d.hh> -#include <mln/win/octagon2d.hh> #include <mln/io/pgm/load.hh> #include <mln/io/pgm/save.hh> @@ -48,16 +46,17 @@ using namespace mln; using value::int_u8; - win::rectangle2d rect(51, 51); - win::octagon2d oct(13); - border::thickness = 52; - image2d<int_u8> lena; io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm"); - image2d<int_u8> out(lena.domain()); - // FIXME: Dead code? -// level::approx::median(lena, rect, out); - level::approx::median(lena, oct, out); - io::pgm::save(out, "out.pgm"); + { + win::octagon2d oct(51); + image2d<int_u8> out = level::approx::median(lena, oct); + io::pgm::save(out, "out_oct.pgm"); + } + { + win::rectangle2d rec(51, 51); + image2d<int_u8> out = level::approx::median(lena, rec); + io::pgm::save(out, "out_rec.pgm"); + } } Index: tests/morpho/general.cc --- tests/morpho/general.cc (revision 3140) +++ tests/morpho/general.cc (working copy) @@ -97,14 +97,28 @@ out = morpho::impl::general_directional(dil, lena, rec, 1); mln_assertion(out == ref); - /* // Hline. ref = morpho::impl::generic::general_on_function(ero, lena, hline); + out = morpho::impl::general_directional(ero, lena, hline, 1); + mln_assertion(out == ref); + + out = morpho::impl::general_line(ero, lena, hline); + mln_assertion(out == ref); + + // Vline. ref = morpho::impl::generic::general_on_function(ero, lena, vline); + out = morpho::impl::general_directional(ero, lena, vline, 0); + mln_assertion(out == ref); + + out = morpho::impl::general_line(ero, lena, vline); + mln_assertion(out == ref); + + /* + // Diag2d. ref = morpho::impl::generic::erosion_on_function(lena, diag2d);
participants (1)
-
Thierry Geraud