https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)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);