* mln/accu/rank_bool.hh: Add untake() and remove unnecessary
attributes.
* mln/morpho/rank_filter.hh: Add rank_filter_directional. It is used
with win::line.
* mln/morpho/rank_filter.hh: Add rank_filter_directional. It is used
with win::line.
* mln/accu/rank.hh: update constructor and add untake(accu::rank).
* tests/accu/rank.cc,
* tests/morpho/rank_filter.cc: fix tests.
* tests/morpho/Makefile.am: add rank_filter test.
---
milena/ChangeLog | 17 +++++
milena/mln/accu/rank.hh | 60 ++++++++++++-------
milena/mln/accu/rank_bool.hh | 43 ++++++++++----
milena/mln/morpho/rank_filter.hh | 115 ++++++++++++++++++++++++++++--------
milena/tests/accu/rank.cc | 22 ++++----
milena/tests/morpho/Makefile.am | 3 +
milena/tests/morpho/rank_filter.cc | 19 ++----
7 files changed, 197 insertions(+), 82 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 2170ada..d149788 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,20 @@
+2008-11-24 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update rank_filter.
+
+ * mln/accu/rank_bool.hh: Add untake() and remove unnecessary
+ attributes.
+
+ * mln/morpho/rank_filter.hh: Add rank_filter_directional. It is used
+ with win::line.
+
+ * mln/accu/rank.hh: update constructor and add untake(accu::rank).
+
+ * tests/accu/rank.cc,
+ * tests/morpho/rank_filter.cc: fix tests.
+
+ * tests/morpho/Makefile.am: add rank_filter test.
+
2008-11-21 Guillaume Lazzara <z(a)lrde.epita.fr>
Add reference files for example outputs used in the tutorial.
diff --git a/milena/mln/accu/rank.hh b/milena/mln/accu/rank.hh
index bdd4df0..bd1999d 100644
--- a/milena/mln/accu/rank.hh
+++ b/milena/mln/accu/rank.hh
@@ -51,16 +51,16 @@ namespace mln
/// Generic rank accumulator class.
- /*!
- * The parameter \c T is the type of values.
- */
+ ///
+ /// The parameter \c T is the type of values.
template <typename T>
struct rank : public mln::accu::internal::base< const T&, rank<T> >
{
typedef T argument;
typedef mln::value::set<T> S;
- rank(unsigned k, unsigned n);
+ rank();
+ explicit rank(unsigned k);
/// Manipulators.
/// \{
@@ -68,6 +68,7 @@ namespace mln
void take(const argument& t);
void take(const rank<T>& other);
void untake(const argument& t);
+ void untake(const rank<T>& other);
/// \}
unsigned card() const { return h_.sum(); }
@@ -82,13 +83,9 @@ namespace mln
/// Give the rank.
unsigned k() const;
- /// Give the total number of elements.
- unsigned n() const;
-
protected:
unsigned k_; // 0 <= k_ < n
- unsigned n_;
mutable accu::histo<T> h_;
const S& s_; // derived from h_
@@ -97,7 +94,7 @@ namespace mln
mutable bool valid_;
mutable unsigned i_; // the median index
- mutable argument t_; // the median value
+ mutable argument t_; // the median value
// Auxiliary methods
void update_() const;
@@ -116,7 +113,7 @@ namespace mln
struct rank : public Meta_Accumulator< rank >
{
- rank(unsigned k_, unsigned n_) : k(k_), n(n_) {}
+ rank(unsigned k_) : k(k_) {}
template <typename T>
struct with
@@ -125,7 +122,6 @@ namespace mln
};
unsigned k;
- unsigned n;
};
} // end of namespace mln::accu::meta
@@ -134,7 +130,7 @@ namespace mln
template <typename T>
rank<T> unmeta(const meta::rank& m, T)
{
- rank<T> a(m.k, m.n);
+ rank<T> a(m.k);
return a;
}
@@ -143,32 +139,32 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
+
template <typename T>
inline
- rank<T>::rank(unsigned k, unsigned n)
- : k_(k),
- n_(n),
- h_(),
+ rank<T>::rank()
+ : h_(),
s_(h_.vset())
{
- mln_assertion(k_ < n_);
init();
}
template <typename T>
inline
- unsigned
- rank<T>::k() const
+ rank<T>::rank(unsigned k)
+ : k_(k),
+ h_(),
+ s_(h_.vset())
{
- return k_;
+ init();
}
template <typename T>
inline
unsigned
- rank<T>::n() const
+ rank<T>::k() const
{
- return n_;
+ return k_;
}
template <typename T>
@@ -227,6 +223,26 @@ namespace mln
template <typename T>
inline
void
+ rank<T>::untake(const rank<T>& other)
+ {
+ // h_
+ h_.untake(other.h_);
+
+ // sum_minus_
+ for (unsigned i = 0; i < i_; ++i)
+ sum_minus_ -= other.h_[i];
+
+ // sum_plus_
+ for (unsigned i = i_ + 1; i < h_.nvalues(); ++i)
+ sum_plus_ -= other.h_[i];
+
+ if (valid_)
+ valid_ = false;
+ }
+
+ template <typename T>
+ inline
+ void
rank<T>::update_() const
{
valid_ = true;
diff --git a/milena/mln/accu/rank_bool.hh b/milena/mln/accu/rank_bool.hh
index f5e9b07..597e078 100644
--- a/milena/mln/accu/rank_bool.hh
+++ b/milena/mln/accu/rank_bool.hh
@@ -56,7 +56,8 @@ namespace mln
{
typedef bool argument;
- rank(unsigned k, unsigned n);
+ rank();
+ rank(unsigned k);
/// Manipulators.
/// \{
@@ -64,6 +65,8 @@ namespace mln
void take_as_init(const argument& t);
void take(const argument& t);
void take(const rank<bool>& other);
+ void untake(const argument& t);
+ void untake(const rank<bool>& other);
/// \}
/// Get the value of the accumulator.
@@ -75,22 +78,24 @@ namespace mln
protected:
unsigned nfalse_;
- unsigned k_; // 0 <= k_ < n
- unsigned n_;
+ unsigned k_; // 0 <= k_
};
# ifndef MLN_INCLUDE_ONLY
inline
- rank<bool>::rank(unsigned k, unsigned n)
- : k_(k),
- n_(n)
+ rank<bool>::rank()
{
- mln_assertion(k_ < n_);
init();
}
+ inline
+ rank<bool>::rank(unsigned k)
+ : k_(k)
+ {
+ init();
+ }
inline
void
@@ -99,20 +104,28 @@ namespace mln
nfalse_ = 0;
}
-
inline
void rank<bool>::take_as_init(const argument& t)
{
nfalse_ = t ? 0 : 1;
}
-
inline
void rank<bool>::take(const argument& t)
{
- nfalse_ += !t;
+ if (t == false)
+ ++nfalse_;
}
+ inline
+ void rank<bool>::untake(const argument& t)
+ {
+ if (t == false)
+ {
+ mln_assertion(nfalse_ > 0);
+ --nfalse_;
+ }
+ }
inline
void
@@ -121,12 +134,18 @@ namespace mln
nfalse_ += other.nfalse_;
}
+ inline
+ void
+ rank<bool>::untake(const rank<bool>& other)
+ {
+ mln_precondition(other.nfalse_ <= nfalse_);
+ nfalse_ -= other.nfalse_;
+ }
inline
bool
rank<bool>::to_result() const
{
- mln_assertion(nfalse_ <= n_);
return k_ >= nfalse_;
}
@@ -134,7 +153,7 @@ namespace mln
bool
rank<bool>::is_valid() const
{
- return nfalse_ <= n_;
+ return true;
}
# endif // ! MLN_INCLUDE_ONLY
diff --git a/milena/mln/morpho/rank_filter.hh b/milena/mln/morpho/rank_filter.hh
index 94a0a27..eb24567 100644
--- a/milena/mln/morpho/rank_filter.hh
+++ b/milena/mln/morpho/rank_filter.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2007, 2008 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 +28,9 @@
#ifndef MLN_MORPHO_RANK_FILTER_HH
# define MLN_MORPHO_RANK_FILTER_HH
-/*! \file mln/morpho/rank_filter.hh
- *
- * \brief Morphological rank_filter.
- */
+/// \file mln/morpho/rank_filter.hh
+///
+/// Morphological rank_filter.
# include <mln/morpho/includes.hh>
# include <mln/convert/to_p_array.hh>
@@ -42,8 +41,7 @@ namespace mln
namespace morpho
{
- /*! Morphological rank_filter.
- */
+ /// Morphological rank_filter.
template <typename I, typename W>
mln_concrete(I)
rank_filter(const Image<I>& input, const Window<W>& win);
@@ -51,47 +49,116 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ template <typename I, typename W>
+ inline
+ void
+ rank_filter_tests(const Image<I>& input_, const Window<W>&
win_, unsigned k)
+ {
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+
+ mln_precondition(input.has_data());
+ mln_precondition(! win.is_empty());
+ (void) input;
+ (void) win;
+ (void) k;
+ }
+
+ } // end of namespace mln::morpho::internal
+
+
namespace impl
{
namespace generic
{
- // On function.
-
template <typename I, typename W>
inline
mln_concrete(I)
- rank_filter_(const I& input, const W& win, unsigned k)
+ rank_filter(const Image<I>& input_, const Window<W>& win_, unsigned
k)
{
- trace::entering("morpho::impl::generic::rank_filter_");
+ trace::entering("morpho::impl::generic::rank_filter");
+
+ internal::rank_filter_tests(input_, win_, k);
+
+ const I& input = exact(input_);
+ const W& win = exact(win_);
mln_concrete(I) output;
initialize(output, input);
- accu::rank<mln_value(I)> accu(k, convert::to_p_array(win,
mln_psite(I)()).nsites());
+ accu::rank<mln_value(I)> accu(k);
+ extension::adjust_fill(input, geom::delta(win) + 1, accu);
mln_piter(I) p(input.domain());
mln_qiter(W) q(win, p);
for_all(p)
- {
- accu.init();
- for_all(q)
- if (input.has(q))
- accu.take(input(q));
-// else
-// accu.take(mln_value(I)(literal::zero));
- output(p) = accu;
- }
-
- trace::exiting("morpho::impl::generic::rank_filter_");
+ {
+ accu.init();
+ for_all(q)
+ if (input.has(q))
+ accu.take(input(q));
+ //else
+ // accu.take(mln_value(I)(literal::zero));
+ output(p) = accu;
+ }
+
+ trace::exiting("morpho::impl::generic::rank_filter");
return output;
}
} // end of namespace mln::morpho::impl::generic
+
+ 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");
+
+ 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_directional(accu, input, win, dir);
+
+ trace::exiting("morpho::impl::generic::rank_filter_directional");
+ return output;
+ }
+
} // end of namespace mln::morpho::impl
+ namespace internal
+ {
+
+ template <typename I, typename M, unsigned i, typename C>
+ inline
+ 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);
+ }
+
+
+
+ template <typename I, typename W>
+ inline
+ mln_concrete(I)
+ rank_filter_dispatch(const Image<I>& input, const Window<W>&
win, unsigned k)
+ {
+ return impl::generic::rank_filter(input, win, k);
+ }
+
+ } // end of namespace mln::morpho::internal
+
+
// Facades.
@@ -104,7 +171,7 @@ namespace mln
mln_precondition(exact(input).has_data());
mln_precondition(! exact(win).is_empty());
- mln_concrete(I) output = impl::generic::rank_filter_(exact(input), exact(win), k);
+ mln_concrete(I) output = internal::rank_filter_dispatch(exact(input), exact(win),
k);
trace::exiting("morpho::rank_filter");
return output;
diff --git a/milena/tests/accu/rank.cc b/milena/tests/accu/rank.cc
index 9c334a9..0e9b6c8 100644
--- a/milena/tests/accu/rank.cc
+++ b/milena/tests/accu/rank.cc
@@ -55,55 +55,55 @@ int main()
using value::int_u8;
{
- accu::meta::rank r(4, 9);
+ accu::meta::rank r(4);
accu::rank<int_u8> a = accu::unmeta(r, int_u8());
- mln_assertion(a.k() == 4 && a.n() == 9);
+ mln_assertion(a.k() == 4);
// Meta_Accumulator<accu::meta::rank>& R = r;
// accu::unmeta(R, int_u8());
}
{
- accu::rank<int_u8> accu(0, 8);
+ accu::rank<int_u8> accu(0);
fill(accu);
mln_assertion(accu.to_result() == 1u);
}
{
- accu::rank<int_u8> accu(1, 8);
+ accu::rank<int_u8> accu(1);
fill(accu);
mln_assertion(accu.to_result() == 2u);
}
{
- accu::rank<int_u8> accu(2, 8);
+ accu::rank<int_u8> accu(2);
fill(accu);
mln_assertion(accu.to_result() == 2u);
}
{
- accu::rank<int_u8> accu(3, 8);
+ accu::rank<int_u8> accu(3);
fill(accu);
mln_assertion(accu.to_result() == 3u);
}
{
- accu::rank<int_u8> accu(4, 8);
+ accu::rank<int_u8> accu(4);
fill(accu);
mln_assertion(accu.to_result() == 4u);
}
{
- accu::rank<int_u8> accu(5, 8);
+ accu::rank<int_u8> accu(5);
fill(accu);
mln_assertion(accu.to_result() == 5u);
}
{
- accu::rank<int_u8> accu(6, 8);
+ accu::rank<int_u8> accu(6);
fill(accu);
mln_assertion(accu.to_result() == 5u);
}
{
- accu::rank<int_u8> accu(7, 8);
+ accu::rank<int_u8> accu(7);
fill(accu);
mln_assertion(accu.to_result() == 5u);
}
{
- accu::rank<bool> accu_bool(1, 5);
+ accu::rank<bool> accu_bool(1);
accu_bool.take(true);
accu_bool.take(true);
accu_bool.take(true);
diff --git a/milena/tests/morpho/Makefile.am b/milena/tests/morpho/Makefile.am
index 734aef5..fd5cc00 100644
--- a/milena/tests/morpho/Makefile.am
+++ b/milena/tests/morpho/Makefile.am
@@ -33,6 +33,7 @@ check_PROGRAMS = \
opening_area \
opening_height \
opening_volume \
+ rank_filter \
skeleton_constrained \
thinning
@@ -70,6 +71,8 @@ complex_image_wst_SOURCES = complex_image_wst.cc
meyer_wst_SOURCES = meyer_wst.cc
+rank_filter_SOURCES = rank_filter.cc
+
skeleton_constrained_SOURCES = skeleton_constrained.cc
combined_SOURCES = combined.cc
diff --git a/milena/tests/morpho/rank_filter.cc b/milena/tests/morpho/rank_filter.cc
index 597dccd..9550876 100644
--- a/milena/tests/morpho/rank_filter.cc
+++ b/milena/tests/morpho/rank_filter.cc
@@ -25,16 +25,12 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/morpho/rank_filter.cc
- *
- * \brief Test on mln::morpho::rank_filter.
- */
+/// \file tests/morpho/rank_filter.cc
+///
+/// Test on mln::morpho::rank_filter.
#include <mln/core/image/image2d.hh>
#include <mln/win/rectangle2d.hh>
-#include <mln/win/octagon2d.hh>
-#include <mln/win/diag2d.hh>
-#include <mln/win/backdiag2d.hh>
#include <mln/core/alias/window2d.hh>
#include <mln/io/pgm/load.hh>
@@ -52,9 +48,6 @@
#include <mln/pw/cst.hh>
#include <mln/fun/ops.hh>
-#include <mln/convert/to_p_array.hh>
-#include <mln/convert/to_window.hh>
-
#include "tests/data.hh"
@@ -70,23 +63,23 @@ int main()
io::pgm::load(lena, MLN_IMG_DIR "/small.pgm");
{
- win::octagon2d oct(31);
image2d<int_u8> out;
out = morpho::rank_filter(lena, rec, 0);
image2d<int_u8> ref(lena.domain());
ref = morpho::erosion(lena, rec);
+
mln_assertion(ref == out);
}
{
- win::octagon2d oct(31);
image2d<int_u8> out;
- out = morpho::rank_filter(lena, rec, 21 * 21 - 1);
+ out = morpho::rank_filter(lena, rec, 21 * 21);
image2d<int_u8> ref(lena.domain());
ref = morpho::dilation(lena, rec);
+
mln_assertion(ref == out);
}
--
1.5.6.5