https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add morphological complementation.
* tests/morpho_contrast.cc: Augment.
* mln/core/concept/value.hh (cast): New.
* mln/fun/v2v/saturate.hh: Update.
* mln/morpho/minus.hh: Move assertions.
* mln/logical/and.hh,
* mln/logical/and_not.hh,
* mln/logical/or.hh: Fix doc.
* mln/value/int_s.hh (operator=): New.
* mln/value/int_u.hh: Likewise.
* mln/morpho/complementation.hh: New.
* mln/morpho/includes.hh: Update.
* mln/arith/revert.hh: New.
* mln/logical/not.hh: New.
mln/arith/revert.hh | 127 ++++++++++++++++++++++++++++++++++++++++++
mln/core/concept/value.hh | 46 +++++++++++++++
mln/fun/v2v/saturate.hh | 10 +--
mln/logical/and.hh | 2
mln/logical/and_not.hh | 2
mln/logical/not.hh | 120 +++++++++++++++++++++++++++++++++++++++
mln/logical/or.hh | 2
mln/morpho/complementation.hh | 105 ++++++++++++++++++++++++++++++++++
mln/morpho/includes.hh | 1
mln/morpho/minus.hh | 7 --
mln/value/int_s.hh | 13 ++++
mln/value/int_u.hh | 13 ++++
tests/morpho_contrast.cc | 22 ++++++-
13 files changed, 455 insertions(+), 15 deletions(-)
Index: tests/morpho_contrast.cc
--- tests/morpho_contrast.cc (revision 1060)
+++ tests/morpho_contrast.cc (working copy)
@@ -37,7 +37,11 @@
#include <mln/io/save_pgm.hh>
#include <mln/value/int_u8.hh>
+#include <mln/value/int_s.hh>
+
#include <mln/morpho/contrast.hh>
+
+#include <mln/level/fill.hh>
#include <mln/level/saturate.hh>
@@ -53,9 +57,23 @@
lena = io::load_pgm("../img/tiny.pgm"),
out(lena.domain());
- image2d_b<int> tmp(lena.domain());
- morpho::contrast(lena, rect, tmp);
+ image2d_b< value::int_s<10> >
+ in(lena.domain()),
+ tmp(lena.domain());
+
+ level::fill(in, lena);
+ morpho::contrast(in, rect, tmp);
level::saturate(tmp, out);
io::save_pgm(out, "out.pgm");
+
+ {
+ // self-duality test:
+ morpho::complementation_inplace(in);
+ image2d_b< value::int_s<10> > tmp_(lena.domain());
+ morpho::contrast(in, rect, tmp_);
+ morpho::complementation_inplace(tmp_);
+ mln_assertion(tmp_ = tmp);
+ }
+
}
Index: mln/core/concept/value.hh
--- mln/core/concept/value.hh (revision 1060)
+++ mln/core/concept/value.hh (working copy)
@@ -62,6 +62,18 @@
};
+
+ namespace value
+ {
+
+ /// Cast a value \p src from type \c Src to type \c Dest.
+ template <typename Dest, typename Src>
+ Dest cast(const Src& src);
+
+ } // end of namespace mln::value
+
+
+
# ifndef MLN_INCLUDE_ONLY
template <typename E>
@@ -87,6 +99,40 @@
return exact(*this);
}
+
+ namespace value
+ {
+
+ namespace internal
+ {
+
+ template <typename S>
+ const S&
+ cast_(const S& src, ...)
+ {
+ return src;
+ }
+
+ template <typename T, typename S>
+ typename S::equiv
+ cast_(const T& dummy, const Value<S>& src)
+ {
+ return exact(src);
+ }
+
+ } // end of namespace mln::value::internal
+
+
+ template <typename Dest, typename Src>
+ Dest cast(const Src& src)
+ {
+ return internal::cast_(src, src);
+ }
+
+
+ } // end of namespace mln::value
+
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
Index: mln/fun/v2v/saturate.hh
--- mln/fun/v2v/saturate.hh (revision 1060)
+++ mln/fun/v2v/saturate.hh (working copy)
@@ -57,7 +57,7 @@
typedef V result;
template <typename W>
- V operator()(const W& v) const;
+ V operator()(const W& w) const;
protected:
V min_, max_;
@@ -84,13 +84,13 @@
template <typename V>
template <typename W>
V
- saturate<V>::operator()(const W& v) const
+ saturate<V>::operator()(const W& w) const
{
- if (v < min_)
+ if (w < min_)
return min_;
- if (v > max_)
+ if (w > max_)
return max_;
- return v;
+ return mln::value::cast<V>(w);
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh (revision 1060)
+++ mln/morpho/includes.hh (working copy)
@@ -53,6 +53,7 @@
# include <mln/morpho/minus.hh>
# include <mln/morpho/plus.hh>
+# include <mln/morpho/complementation.hh>
#endif // ! MLN_MORPHO_INCLUDES_HH
Index: mln/morpho/minus.hh
--- mln/morpho/minus.hh (revision 1060)
+++ mln/morpho/minus.hh (working copy)
@@ -64,7 +64,9 @@
const Image<I>& lhs, const Image<J>& rhs,
Image<O>& output)
{
+ // FIXME: mln_precondition(rhs <= lhs);
return logical::and_not(lhs, rhs, output);
+ // FIXME: mln_postcondition(output <= lhs);
}
template <typename K, typename I, typename J, typename O>
@@ -85,19 +87,14 @@
{
mln_precondition(exact(rhs).domain() = exact(lhs).domain());
mln_precondition(exact(output).domain() = exact(lhs).domain());
- mln_precondition(rhs <= lhs);
impl::minus_(mln_value_kind(I)(), exact(lhs), exact(rhs), output);
-
- mln_postcondition(output <= lhs);
}
template <typename I, typename J>
void minus_inplace(Image<I>& lhs, const Image<J>& rhs)
{
mln_precondition(exact(rhs).domain() = exact(lhs).domain());
- mln_precondition(rhs <= lhs);
-
morpho::minus(lhs, rhs, lhs); // Calls the previous version.
}
Index: mln/morpho/complementation.hh
--- mln/morpho/complementation.hh (revision 0)
+++ mln/morpho/complementation.hh (revision 0)
@@ -0,0 +1,105 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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_MORPHO_COMPLEMENTATION_HH
+# define MLN_MORPHO_COMPLEMENTATION_HH
+
+# include <mln/level/compare.hh>
+# include <mln/logical/not.hh>
+# include <mln/arith/revert.hh>
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+
+ /*! Morphological complementation: either a logical "not" (if
+ * morpho on sets) or an arithmetical complementation (if morpho
+ * on functions).
+ */
+ template <typename I, typename O>
+ void complementation(const Image<I>& input, Image<O>& output);
+
+
+ /*! Morphological complementation, inplace version: either a
+ * logical "not" (if morpho on sets) or an arithmetical
+ * complementation (if morpho on functions).
+ */
+ template <typename I>
+ void complementation_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I, typename O>
+ void complementation_(value::binary_kind, // binary => morphology on sets
+ const Image<I>& input,
+ Image<O>& output)
+ {
+ return logical::not_(input, output);
+ }
+
+ template <typename K, typename I, typename O>
+ void complementation_(K, // otherwise => morphology on functions
+ const Image<I>& input,
+ Image<O>& output)
+ {
+ return arith::revert(input, output);
+ }
+
+ } // end of namespace mln::morpho::impl
+
+
+ // Facades.
+
+ template <typename I, typename O>
+ void complementation(const Image<I>& input, Image<O>& output)
+ {
+ mln_precondition(exact(output).domain() = exact(input).domain());
+ impl::complementation_(mln_value_kind(I)(), exact(input), output);
+ }
+
+ template <typename I>
+ void complementation_inplace(Image<I>& input)
+ {
+ mln_precondition(exact(input).has_data());
+ morpho::complementation(input, input); // Calls the previous version.
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_COMPLEMENTATION_HH
Index: mln/arith/revert.hh
--- mln/arith/revert.hh (revision 0)
+++ mln/arith/revert.hh (revision 0)
@@ -0,0 +1,127 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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_ARITH_REVERT_HH
+# define MLN_ARITH_REVERT_HH
+
+/*! \file mln/arith/revert.hh
+ *
+ * \brief Point-wise revert (min -> max and max -> min) of images.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+# include <mln/value/props.hh>
+
+// FIXME: Rely instead on mln/fun/v2v/revert.hh.
+// FIXME: Revert on int value 0 does not give 0 (since min != - max; idem for float
etc.)
+
+
+
+namespace mln
+{
+
+ namespace arith
+ {
+
+ /*! Point-wise reversion of image \p input.
+ *
+ * \param[in] input the input image.
+ * \param[out] output The result image.
+ *
+ * \pre \p output.domain = \p input.domain
+ */
+ template <typename I, typename O>
+ void revert(const Image<I>& input, Image<O>& output);
+
+
+ /*! Point-wise in-place reversion of image \p input.
+ *
+ * \param[in,out] input The target image.
+ *
+ * It performs: \n
+ * for all p of input.domain \n
+ * input(p) = min + (max - input(p))
+ */
+ template <typename I>
+ void revert_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I, typename O>
+ void revert_(const Image<I>& input_, Image<O>& output_)
+ {
+ const I& input = exact(input_);
+ O& output = exact(output_);
+ typedef mln_value(I) V;
+ mln_piter(I) p(input.domain());
+ for_all(p)
+ output(p) = mln_min(V) + (mln_max(V) - input(p));
+ }
+
+ template <typename I, typename O>
+ void revert_(const Fast_Image<I>& input, Fast_Image<O>&
output)
+ {
+ typedef mln_value(I) V;
+ mln_pixter(const I) ip(exact(input));
+ mln_pixter(O) op(exact(output));
+ for_all_2(ip, op)
+ op.val() = mln_min(V) + (mln_max(V) - op.val());
+ }
+
+ } // end of namespace mln::arith::impl
+
+
+ // Facades.
+
+ template <typename I, typename O>
+ void revert(const Image<I>& input, Image<O>& output)
+ {
+ mln_precondition(exact(output).domain() = exact(input).domain());
+ impl::revert_(exact(input), exact(output));
+ }
+
+ template <typename I>
+ void revert_inplace(Image<I>& input)
+ {
+ mln_precondition(exact(input).has_data());
+ impl::revert_(exact(input), exact(input));
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::arith
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ARITH_REVERT_HH
Index: mln/logical/and.hh
--- mln/logical/and.hh (revision 1060)
+++ mln/logical/and.hh (working copy)
@@ -61,7 +61,7 @@
* \param[in] lhs First operand image.
* \param[in,out] rhs Second operand image.
*
- * This addition performs: \n
+ * It performs: \n
* for all p of rhs.domain \n
* lhs(p) = lhs(p) and rhs(p)
*
Index: mln/logical/and_not.hh
--- mln/logical/and_not.hh (revision 1060)
+++ mln/logical/and_not.hh (working copy)
@@ -61,7 +61,7 @@
* \param[in] lhs First operand image.
* \param[in,out] rhs Second operand image.
*
- * This addition performs: \n
+ * It performs: \n
* for all p of rhs.domain \n
* lhs(p) = lhs(p) and not rhs(p)
*
Index: mln/logical/or.hh
--- mln/logical/or.hh (revision 1060)
+++ mln/logical/or.hh (working copy)
@@ -61,7 +61,7 @@
* \param[in] lhs First operand image.
* \param[in,out] rhs Second operand image.
*
- * This addition performs: \n
+ * It performs: \n
* for all p of rhs.domain \n
* lhs(p) = lhs(p) or rhs(p)
*
Index: mln/logical/not.hh
--- mln/logical/not.hh (revision 0)
+++ mln/logical/not.hh (revision 0)
@@ -0,0 +1,120 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// 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_LOGICAL_NOT_HH
+# define MLN_LOGICAL_NOT_HH
+
+/*! \file mln/logical/not.hh
+ *
+ * \brief Point-wise "logical not" of a binary image.
+ *
+ * \todo Add static assertion and save one iterator in in-place version.
+ */
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln
+{
+
+ namespace logical
+ {
+
+ /*! Point-wise "logical not" of image \p input.
+ *
+ * \param[in] input the input image.
+ * \param[out] output The result image.
+ *
+ * \pre \p output.domain = \p input.domain
+ */
+ template <typename I, typename O>
+ void not_(const Image<I>& input, Image<O>& output);
+
+
+ /*! Point-wise in-place "logical not" of image \p input.
+ *
+ * \param[in,out] input The target image.
+ *
+ * It performs: \n
+ * for all p of input.domain \n
+ * input(p) = not input(p)
+ */
+ template <typename I>
+ void not_inplace(Image<I>& input);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I, typename O>
+ void not__(const Image<I>& input_, Image<O>& output_)
+ {
+ const I& input = exact(input_);
+ O& output = exact(output_);
+ mln_piter(I) p(input.domain());
+ for_all(p)
+ output(p) = ! input(p);
+ }
+
+ template <typename I, typename O>
+ void not__(const Fast_Image<I>& input, Fast_Image<O>& output)
+ {
+ mln_pixter(const I) ip(exact(input));
+ mln_pixter(O) op(exact(output));
+ for_all_2(ip, op)
+ op.val() = ! ip.val();
+ }
+
+ } // end of namespace mln::logical::impl
+
+
+ // Facades.
+
+ template <typename I, typename O>
+ void not_(const Image<I>& input, Image<O>& output)
+ {
+ mln_precondition(exact(output).domain() = exact(input).domain());
+ impl::not__(exact(input), exact(output));
+ }
+
+ template <typename I>
+ void not_inplace(Image<I>& input)
+ {
+ mln_precondition(exact(input).has_data());
+ impl::not__(exact(input), exact(input));
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::logical
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LOGICAL_NOT_HH
Index: mln/value/int_s.hh
--- mln/value/int_s.hh (revision 1060)
+++ mln/value/int_s.hh (working copy)
@@ -71,6 +71,9 @@
/// Constructor from an integer.
int_s(int i);
+ /// Assignment from an integer.
+ int_s<n>& operator=(int i);
+
/// Negation.
int_s<n> operator-() const;
@@ -135,6 +138,16 @@
}
template <unsigned n>
+ int_s<n>&
+ int_s<n>::operator=(int i)
+ {
+ mln_precondition(i >= mln_min(enc));
+ mln_precondition(i <= mln_max(enc));
+ this->v_ = i;
+ return *this;
+ }
+
+ template <unsigned n>
int_s<n>
int_s<n>::operator-() const
{
Index: mln/value/int_u.hh
--- mln/value/int_u.hh (revision 1060)
+++ mln/value/int_u.hh (working copy)
@@ -71,6 +71,9 @@
/// Constructor from an integer.
int_u(int i);
+ /// Assignment from an integer.
+ int_u<n>& operator=(int i);
+
/// Zero value.
static const int_u<n> zero;
@@ -132,6 +135,16 @@
template <unsigned n>
int_u<n>&
+ int_u<n>::operator=(int i)
+ {
+ mln_precondition(i >= 0);
+ mln_precondition(i <= mln_max(enc));
+ this->v_ = i;
+ return *this;
+ }
+
+ template <unsigned n>
+ int_u<n>&
int_u<n>::operator+=(int i)
{
mln_precondition(long(this->v_) + i >= 0);