https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update accus and add LoG filter.
* mln/core/concept/accumulator.hh (merge): New.
* mln/core/concept/doc/accumulator.hh
(take): New; overload.
* mln/accu/bbox.hh,
* mln/accu/count.hh,
* mln/accu/histo.hh,
* mln/accu/max.hh,
* mln/accu/mean.hh,
* mln/accu/min.hh,
* mln/accu/sum.hh (operator+=): Rename as...
(take): ...this.
(conversion): Remove operator; too risky.
Update.
* mln/estim/mean.hh: Update.
* mln/level/fast_median.hh: Update.
* mln/level/median.hh: Update.
* mln/level/naive/median.hh: Update.
* mln/morpho/erosion.hh: Update.
* mln/border/duplicate.hh,
* mln/border/fill.hh,
* mln/border/mirror.hh,
* mln/border/resize.hh: Add fixme.
* mln/io/load_pgm,
* mln/io/save_pgm: Fix for g++-2.95.
* mln/linear/convolve.hh: Use border.
* tests/convolve.cc: Update.
* mln/accu/min_max.hh: New.
* mln/estim/min_max.hh: New.
* mln/fun/v2v/linear.hh: New.
* mln/level/stretch.hh: New.
* mln/linear/log.hh: New.
* mln/value/props.hh (epsilon): New.
* tests/linear_log.cc: New.
mln/accu/bbox.hh | 33 ++++++--
mln/accu/count.hh | 28 ++----
mln/accu/histo.hh | 10 ++
mln/accu/max.hh | 16 ++-
mln/accu/mean.hh | 34 +++-----
mln/accu/median.hh | 29 +++++--
mln/accu/min.hh | 21 ++---
mln/accu/min_max.hh | 147 ++++++++++++++++++++++++++++++++++++
mln/accu/sum.hh | 30 ++-----
mln/border/duplicate.hh | 5 -
mln/border/fill.hh | 5 -
mln/border/mirror.hh | 5 -
mln/border/resize.hh | 7 +
mln/core/concept/accumulator.hh | 25 ++++++
mln/core/concept/doc/accumulator.hh | 3
mln/estim/mean.hh | 3
mln/estim/min_max.hh | 78 +++++++++++++++++++
mln/fun/v2v/linear.hh | 93 ++++++++++++++++++++++
mln/io/load_pgm.hh | 26 +++++-
mln/io/save_pgm.hh | 29 +++++--
mln/level/fast_median.hh | 6 -
mln/level/median.hh | 12 +-
mln/level/naive/median.hh | 2
mln/level/stretch.hh | 100 ++++++++++++++++++++++++
mln/level/to_enc.hh | 4
mln/linear/convolve.hh | 5 +
mln/linear/log.hh | 74 ++++++++++++++++++
mln/morpho/erosion.hh | 2
mln/value/props.hh | 10 +-
mln/value/stack.hh | 2
tests/convolve.cc | 3
tests/linear_log.cc | 71 +++++++++++++++++
32 files changed, 794 insertions(+), 124 deletions(-)
Index: tests/convolve.cc
--- tests/convolve.cc (revision 1050)
+++ tests/convolve.cc (working copy)
@@ -40,6 +40,7 @@
#include <mln/core/w_window.hh>
#include <mln/make/w_window2d.hh>
+#include <mln/border/thickness.hh>
#include <mln/linear/convolve.hh>
@@ -48,6 +49,8 @@
using namespace mln;
using value::int_u8;
+ border::thickness = 2;
+
image2d_b<int_u8>
lena = io::load_pgm("../img/lena.pgm"),
out(lena.domain());
Index: tests/linear_log.cc
--- tests/linear_log.cc (revision 0)
+++ tests/linear_log.cc (revision 0)
@@ -0,0 +1,71 @@
+// 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.
+
+/*! \file tests/linear_log.cc
+ *
+ * \brief Tests on mln::linear::log.
+ */
+
+#include <mln/core/image2d_b.hh>
+#include <mln/value/int_u8.hh>
+
+#include <mln/io/load_pgm.hh>
+#include <mln/io/save_pgm.hh>
+
+#include <mln/border/thickness.hh>
+#include <mln/linear/log.hh>
+
+#include <mln/estim/min_max.hh>
+#include <mln/level/stretch.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ border::thickness = 2;
+
+ image2d_b<int_u8> lena = io::load_pgm("../img/lena.pgm");
+
+ image2d_b<int> tmp(lena.domain());
+ linear::LoG_5x5(lena, tmp);
+ {
+ int min, max;
+ estim::min_max(tmp, min, max);
+ mln_assertion(min = -929 && max = 1458);
+ }
+
+ image2d_b<int_u8> out(lena.domain());
+ level::stretch(tmp, out);
+ io::save_pgm(out, "out.pgm");
+ {
+ int_u8 min, max;
+ estim::min_max(out, min, max);
+ mln_assertion(min = 0 && max = 255);
+ }
+}
Index: mln/estim/min_max.hh
--- mln/estim/min_max.hh (revision 0)
+++ mln/estim/min_max.hh (revision 0)
@@ -0,0 +1,78 @@
+// 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_ESTIM_MIN_MAX_HH
+# define MLN_ESTIM_MIN_MAX_HH
+
+/*! \file mln/estim/min_max.hh
+ *
+ * \brief Compute the min_max pixel value.
+ */
+
+# include <mln/accu/min_max.hh>
+# include <mln/level/take.hh>
+
+
+namespace mln
+{
+
+ namespace estim
+ {
+
+ /*! \brief Compute the min and max values of the pixels of image \p input.
+ *
+ * \param[in] input The image.
+ * \param[out] min The minimum pixel value of \p input.
+ * \param[out] max The maximum pixel value of \p input.
+ */
+ template <typename I>
+ void min_max(const Image<I>& input,
+ mln_value(I)& min, mln_value(I)& max);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ void min_max(const Image<I>& input,
+ mln_value(I)& min, mln_value(I)& max)
+ {
+ mln_precondition(exact(input).has_data());
+ accu::min_max<mln_value(I)> a;
+ a.init();
+ level::take(a, input);
+ min = a.min();
+ max = a.max();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::estim
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ESTIM_MIN_MAX_HH
Index: mln/estim/mean.hh
--- mln/estim/mean.hh (revision 1050)
+++ mln/estim/mean.hh (working copy)
@@ -56,9 +56,10 @@
template <typename I>
mln_sum(mln_value(I)) mean(const Image<I>& input)
{
+ mln_precondition(exact(input).has_data());
typedef mln_value(I) V;
typedef mln_sum(V) S;
- return level::run(input, accu::mean<V, S>());
+ return level::run(input, accu::mean<V, S>()).to_value();
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/core/concept/doc/accumulator.hh
--- mln/core/concept/doc/accumulator.hh (revision 1050)
+++ mln/core/concept/doc/accumulator.hh (working copy)
@@ -49,6 +49,9 @@
/// Take into account a value \p v (an element).
void take(const value& v);
+
+ /// Take into account another accumulator \p other.
+ void take(const E& other);
};
} // end of namespace mln::doc
Index: mln/core/concept/accumulator.hh
--- mln/core/concept/accumulator.hh (revision 1050)
+++ mln/core/concept/accumulator.hh (working copy)
@@ -54,12 +54,27 @@
typedef value;
void init();
void take(const value& v);
+ void take(const E& other);
*/
protected:
Accumulator();
};
+ /*! \brief Merge two accumulators.
+ *
+ * The parameter \a E is the accumulator exact type.
+ *
+ * \param[in] lhs An accumulator.
+ * \param[in] rhs Another accumulator.
+ * \result A temporary accumulator.
+ *
+ * \see relates mln::Accumulator
+ */
+ template <typename E>
+ E merge(const Accumulator<E>& lhs, const Accumulator<E>& rhs);
+
+
# ifndef MLN_INCLUDE_ONLY
template <typename E>
@@ -70,6 +85,16 @@
m1 = 0;
void (E::*m2)(const value&) = & E::take;
m2 = 0;
+ void (E::*m3)(const E&) = & E::take;
+ m3 = 0;
+ }
+
+ template <typename E>
+ E merge(const Accumulator<E>& lhs, const Accumulator<E>& rhs)
+ {
+ E tmp(exact(lhs));
+ tmp.take(exact(rhs));
+ return tmp;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/fun/v2v/linear.hh
--- mln/fun/v2v/linear.hh (revision 0)
+++ mln/fun/v2v/linear.hh (revision 0)
@@ -0,0 +1,93 @@
+// 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_FUN_V2V_LINEAR_HH
+# define MLN_FUN_V2V_LINEAR_HH
+
+/*! \file mln/fun/v2v/linear.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace v2v
+ {
+
+ /*! Linear function.
+ *
+ * f(v) = a * v + b.
+ *
+ * \c V is the type of input values; \c T is the type used to
+ * compute the result; \c R is the result type.
+ *
+ * By defaut, \c T is \c V and \c R is \c T.
+ */
+ template <typename V, typename T = V, typename R = T>
+ struct linear : public Function_v2v< linear<V,T,R> >
+ {
+ typedef R result;
+ R operator()(const V& v) const;
+
+ linear(T a, T b);
+ T a, b;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V, typename T, typename R>
+ linear<V,T,R>::linear(T a, T b)
+ : a(a),
+ b(b)
+ {
+ }
+
+ template <typename V, typename T, typename R>
+ R
+ linear<V,T,R>::operator()(const V& v) const
+ {
+ return R(a * T(v) + b);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::v2v
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_V2V_LINEAR_HH
Index: mln/morpho/erosion.hh
--- mln/morpho/erosion.hh (revision 1050)
+++ mln/morpho/erosion.hh (working copy)
@@ -70,7 +70,7 @@
min.init();
for_all(q) if (input.has(q))
min.take(input(q));
- output(p) = min;
+ output(p) = min.to_value();
}
}
Index: mln/level/median.hh
--- mln/level/median.hh (revision 1050)
+++ mln/level/median.hh (working copy)
@@ -122,7 +122,7 @@
med.untake(input(q_dm));
for_all(q_dp) if (input.has(q_dp))
med.take(input(q_dp));
- output(p) = med;
+ output(p) = med.to_value();
}
void fwd()
@@ -131,7 +131,7 @@
med.untake(input(q_fm));
for_all(q_fp) if (input.has(q_fp))
med.take(input(q_fp));
- output(p) = med;
+ output(p) = med.to_value();
}
void bkd()
@@ -140,7 +140,7 @@
med.untake(input(q_bm));
for_all(q_bp) if (input.has(q_bp))
med.take(input(q_bp));
- output(p) = med;
+ output(p) = med.to_value();
}
}; // end of median_functor
@@ -192,7 +192,7 @@
for (col = min_col; col <= min_col + half; ++col, ++ct)
{
med.take(input(pt));
- output(p) = med;
+ output(p) = med.to_value();
}
// middle columns (both take and untake)
@@ -201,14 +201,14 @@
{
med.take(input(pt));
med.untake(input(pu));
- output(p) = med;
+ output(p) = med.to_value();
}
// right columns (now just untake old points)
for (; col <= max_col; ++cu, ++col)
{
med.untake(input(pu));
- output(p) = med;
+ output(p) = med.to_value();
}
}
}
Index: mln/level/naive/median.hh
--- mln/level/naive/median.hh (revision 1050)
+++ mln/level/naive/median.hh (working copy)
@@ -85,7 +85,7 @@
med.init();
for_all(q) if (input.has(q))
med.take(input(q));
- output(p) = med;
+ output(p) = med.to_value();
}
}
Index: mln/level/to_enc.hh
--- mln/level/to_enc.hh (revision 1050)
+++ mln/level/to_enc.hh (working copy)
@@ -30,7 +30,7 @@
/*! \file mln/level/to_enc.hh
*
- * \brief Transform with fun::to_enc the contents of an image into
+ * \brief Transform with fun::v2v::enc the contents of an image into
* another one.
*/
@@ -60,7 +60,7 @@
template <typename I, typename O>
void to_enc(const Image<I>& input, Image<O>& output)
{
- mln_precondition(exact(output).domain() >= exact(input).domain());
+ mln_precondition(exact(output).domain() = exact(input).domain());
level::transform(input, fun::v2v::enc< mln_value(I) >(), output);
}
Index: mln/level/fast_median.hh
--- mln/level/fast_median.hh (revision 1050)
+++ mln/level/fast_median.hh (working copy)
@@ -119,7 +119,7 @@
for_all(q_bot)
med.take(*q_bot);
- output(p) = med;
+ output(p) = med.to_value();
if (fwd)
// browse line fwd
@@ -130,7 +130,7 @@
med.untake(*q_fm);
for_all(q_fp)
med.take(*q_fp);
- output(p) = med;
+ output(p) = med.to_value();
}
else
// browse line bkd
@@ -141,7 +141,7 @@
med.untake(*q_bm);
for_all(q_bp)
med.take(*q_bp);
- output(p) = med;
+ output(p) = med.to_value();
}
// change browsing
fwd = ! fwd;
Index: mln/level/stretch.hh
--- mln/level/stretch.hh (revision 0)
+++ mln/level/stretch.hh (revision 0)
@@ -0,0 +1,100 @@
+// 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_LEVEL_STRETCH_HH
+# define MLN_LEVEL_STRETCH_HH
+
+/*! \file mln/level/stretch.hh
+ *
+ * \brief Transform with fun::stretch the contents of an image into
+ * another one.
+ */
+
+# include <mln/estim/min_max.hh>
+# include <mln/value/int_u.hh>
+# include <mln/fun/v2v/linear.hh>
+# include <mln/level/transform.hh>
+
+
+namespace mln
+{
+
+ namespace level
+ {
+
+ /*! Stretch the values of \p input so that they can be stored in \p output.
+ *
+ * \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 stretch(const Image<I>& input, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <unsigned n, typename I, typename O>
+ void stretch(value::int_u<n>,
+ const Image<I>& input, Image<O>& output)
+ {
+ mln_value(I) min_, max_;
+ estim::min_max(input, min_, max_);
+ if (max_ = min_)
+ return; // FIXME
+ float min = float(min_), max = float(max_);
+ const float epsilon = value::props<float>::epsilon;
+ float m = 0.0f - 0.5f + epsilon;
+ float M = mln_max(value::int_u<n>) + 0.5f - epsilon;
+ float a = (M - m) / (max - min);
+ float b = (m * max - M * min) / (max - min);
+ fun::v2v::linear<float, float, int> f(a, b);
+ level::transform(input, f, output);
+ }
+
+ } // end of namespace mln::level::impl
+
+
+ template <typename I, typename O>
+ void stretch(const Image<I>& input, Image<O>& output)
+ {
+ mln_precondition(exact(output).domain() = exact(input).domain());
+ impl::stretch(mln_value(O)(), input, output);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::level
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LEVEL_STRETCH_HH
Index: mln/io/save_pgm.hh
--- mln/io/save_pgm.hh (revision 1050)
+++ mln/io/save_pgm.hh (working copy)
@@ -55,15 +55,32 @@
file << "# olena" << std::endl;
file << ima.ncols() << ' ' << ima.nrows() <<
std::endl;
file << "255" << std::endl;
- point2d p = make::point2d(ima.domain().pmin().row(),
- ima.domain().pmin().col());
- size_t len = ima.ncols() * sizeof(unsigned char);
- for (;
- p.row() <= ima.domain().pmax().row();
- ++p.row())
+ const int
+ min_row = ima.domain().pmin().row(),
+ max_row = ima.domain().pmax().row();
+ point2d p;
+ if (sizeof(value::int_u8) = 1)
{
+ p.col() = ima.domain().pmin().col();
+ size_t len = ima.ncols();
+ for (p.row() = min_row; p.row() <= max_row; ++p.row())
file.write((char*)(& ima(p)), len);
}
+ else
+ {
+ // FIXME: code for g++-2.95 when sizeof(int_u8) = 2!!!
+ const int
+ min_col = ima.domain().pmin().col(),
+ max_col = ima.domain().pmax().col();
+ std::cout << min_row << ' ' << max_row << std::endl;
+ std::cout << min_col << ' ' << max_col << std::endl;
+ for (p.row() = min_row; p.row() <= max_row; ++p.row())
+ for (p.col() = min_col; p.col() <= max_col; ++p.col())
+ {
+ unsigned char c = ima(p);
+ file.write((char*)(&c), 1);
+ }
+ }
}
} // end of namespace mln::io
Index: mln/io/load_pgm.hh
--- mln/io/load_pgm.hh (revision 1050)
+++ mln/io/load_pgm.hh (working copy)
@@ -135,13 +135,30 @@
void load_pgm_raw_2d(std::ifstream& file, I& ima)
{
point2d p = make::point2d(0, ima.domain().pmin().col());
- size_t len = ima.ncols() * sizeof(mln_value(I));
- for (p.row() = ima.domain().pmin().row();
- p.row() <= ima.domain().pmax().row();
- ++p.row())
+ typedef mln_value(I) V;
+ const mln_coord(I)
+ min_row = ima.domain().pmin().row(),
+ max_row = ima.domain().pmax().row();
+ if (sizeof(V) = 1)
{
+ size_t len = ima.ncols() * sizeof(mln_enc(V));
+ for (p.row() = min_row; p.row() <= max_row; ++p.row())
file.read((char*)(& ima(p)), len);
}
+ else
+ {
+ // FIXME: code for g++-2.95 when sizeof(int_u8) = 2!!!
+ const mln_coord(I)
+ min_col = ima.domain().pmin().col(),
+ max_col = ima.domain().pmax().col();
+ for (p.row() = min_row; p.row() <= max_row; ++p.row())
+ for (p.col() = min_col; p.col() <= max_col; ++p.col())
+ {
+ unsigned char c;
+ file.read((char*)(&c), 1);
+ ima(p) = c;
+ }
+ }
}
@@ -160,6 +177,7 @@
char type;
int nrows, ncols;
internal::read_pnm_header('2', '5', file, type, nrows, ncols);
+
image2d_b<value::int_u8> ima(nrows, ncols);
if (type = '5')
internal::load_pgm_raw_2d(file, ima);
Index: mln/linear/log.hh
--- mln/linear/log.hh (revision 0)
+++ mln/linear/log.hh (revision 0)
@@ -0,0 +1,74 @@
+// 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_LINEAR_LOG_HH
+# define MLN_LINEAR_LOG_HH
+
+/*! \file mln/linear/log.hh
+ *
+ * \brief Laplacian of Gaussian.
+ */
+
+# include <mln/linear/convolve.hh>
+# include <mln/make/w_window2d_int.hh>
+
+
+
+namespace mln
+{
+
+ namespace linear
+ {
+
+ template <typename I, typename O>
+ void LoG_5x5(const Image<I>& input, Image<O>& output);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // LoG_5x5 (Cf. Sonka et al., pages 85-86)
+
+ template <typename I, typename O>
+ void LoG_5x5(const Image<I>& input, Image<O>& output)
+ {
+ mln_precondition(exact(output).domain() = exact(input).domain());
+ int ws[] = { 0, 0, -1, 0, 0,
+ 0, -1, -2, -1, 0,
+ -1, -2, 16, -2, -1,
+ 0, -1, -2, -1, 0,
+ 0, 0, -1, 0, 0 };
+ convolve(input, make::w_window2d_int(ws), output);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::linear
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LINEAR_CONVOLVE_HH
Index: mln/linear/convolve.hh
--- mln/linear/convolve.hh (revision 1050)
+++ mln/linear/convolve.hh (working copy)
@@ -35,6 +35,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/weighted_window.hh>
+# include <mln/border/resize.hh>
+# include <mln/border/duplicate.hh>
@@ -86,6 +88,9 @@
const W& win = exact(win_);
O& output = exact(output_);
+ border::resize(input, win.delta());
+ border::duplicate(input);
+
mln_pixter(O) p_out(output);
mln_pixter(const I) p(input);
Index: mln/accu/min.hh
--- mln/accu/min.hh (revision 1050)
+++ mln/accu/min.hh (working copy)
@@ -54,10 +54,11 @@
typedef V value;
min();
+
void take(const value& v);
+ void take(const min<V>& other);
void init();
- operator V() const;
V to_value() const;
protected:
@@ -76,23 +77,25 @@
}
template <typename V>
- void min<V>::take(const value& v)
+ void
+ min<V>::init()
{
- if (v < v_)
- v_ = v;
+ v_ = mln_max(V);
}
template <typename V>
- void
- min<V>::init()
+ void min<V>::take(const value& v)
{
- v_ = mln_max(V);
+ if (v < v_)
+ v_ = v;
}
template <typename V>
- min<V>::operator V() const
+ void
+ min<V>::take(const min<V>& other)
{
- return v_;
+ if (other.v_ < v_)
+ v_ = other.v_;
}
template <typename V>
Index: mln/accu/sum.hh
--- mln/accu/sum.hh (revision 1050)
+++ mln/accu/sum.hh (working copy)
@@ -56,14 +56,13 @@
typedef V value;
sum();
- void take(const value& v);
+
void init();
+ void take(const value& v);
+ void take(const sum<V,S>& other);
- operator S() const;
S to_value() const;
- sum<V,S>& operator+=(const sum<V,S>& rhs);
-
protected:
S sum_;
@@ -80,12 +79,6 @@
}
template <typename V, typename S>
- void sum<V,S>::take(const value& v)
- {
- sum_ += v;
- }
-
- template <typename V, typename S>
void
sum<V,S>::init()
{
@@ -93,24 +86,23 @@
}
template <typename V, typename S>
- sum<V,S>::operator S() const
+ void sum<V,S>::take(const value& v)
{
- return to_value;
+ sum_ += v;
}
template <typename V, typename S>
- S
- sum<V,S>::to_value() const
+ void
+ sum<V,S>::take(const sum<V,S>& other)
{
- return sum_;
+ sum_ += other.sum_;
}
template <typename V, typename S>
- sum<V,S>&
- sum<V,S>::operator+=(const sum<V,S>& rhs)
+ S
+ sum<V,S>::to_value() const
{
- sum_ += rhs.sum_;
- return *this;
+ return sum_;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/accu/max.hh
--- mln/accu/max.hh (revision 1050)
+++ mln/accu/max.hh (working copy)
@@ -54,10 +54,11 @@
typedef V value;
max();
+
void take(const value& v);
+ void take(const max<V>& other);
void init();
- operator V() const;
V to_value() const;
protected:
@@ -76,7 +77,8 @@
}
template <typename V>
- void max<V>::take(const value& v)
+ void
+ max<V>::take(const value& v)
{
if (v > v_)
v_ = v;
@@ -84,15 +86,17 @@
template <typename V>
void
- max<V>::init()
+ max<V>::take(const max<V>& other)
{
- v_ = mln_min(V);
+ if (other.v_ > v_)
+ v_ = other.v_;
}
template <typename V>
- max<V>::operator V() const
+ void
+ max<V>::init()
{
- return v_;
+ v_ = mln_min(V);
}
template <typename V>
Index: mln/accu/histo.hh
--- mln/accu/histo.hh (revision 1050)
+++ mln/accu/histo.hh (working copy)
@@ -59,6 +59,7 @@
typedef mln_value(S) value;
void take(const value& v);
+ void take(const histo<S>& other);
void untake(const value& v);
void init();
@@ -113,6 +114,15 @@
template <typename S>
void
+ histo<S>::take(const histo<S>& other)
+ {
+ for (unsigned i = 0; i < h_.size(); ++i)
+ h_[i] += other.h_[i];
+ sum_ += other.sum_;
+ }
+
+ template <typename S>
+ void
histo<S>::untake(const value& v)
{
mln_precondition(h_[s_.index_of(v)] > 0);
Index: mln/accu/count.hh
--- mln/accu/count.hh (revision 1050)
+++ mln/accu/count.hh (working copy)
@@ -51,14 +51,13 @@
typedef V value;
count();
- void take(const value&);
+
void init();
+ void take(const value&);
+ void take(const count<V>& other);
- operator std::size_t() const;
std::size_t to_value() const;
- count<V>& operator+=(const count<V>& rhs);
-
protected:
std::size_t count_;
@@ -76,22 +75,23 @@
template <typename V>
void
- count<V>::take(const value&)
+ count<V>::init()
{
- ++count_;
+ count_ = 0;
}
template <typename V>
void
- count<V>::init()
+ count<V>::take(const value&)
{
- count_ = 0;
+ ++count_;
}
template <typename V>
- count<V>::operator std::size_t() const
+ void
+ count<V>::take(const count<V>& other)
{
- return to_value();
+ count_ += other.count_;
}
template <typename V>
@@ -101,14 +101,6 @@
return count_;
}
- template <typename V>
- count<V>&
- count<V>::operator+=(const count<V>& rhs)
- {
- count_ += rhs.count_;
- return *this;
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::accu
Index: mln/accu/min_max.hh
--- mln/accu/min_max.hh (revision 0)
+++ mln/accu/min_max.hh (revision 0)
@@ -0,0 +1,147 @@
+// 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_ACCU_MIN_MAX_HH
+# define MLN_ACCU_MIN_MAX_HH
+
+/*! \file mln/accu/min_max.hh
+ *
+ * \brief Define an accumulator that computes a min and a max.
+ */
+
+# include <utility>
+
+# include <mln/accu/min.hh>
+# include <mln/accu/max.hh>
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+
+ /*! Generic min and max accumulator class.
+ *
+ * The parameter \c V is the type of values.
+ */
+ template <typename V>
+ struct min_max : public Accumulator< min_max<V> >
+ {
+ typedef V value;
+
+ min_max();
+
+ void take(const value& v);
+ void take(const min_max<V>& other);
+ void init();
+
+ V min() const;
+ V max() const;
+
+ std::pair<V,V> to_value() const;
+ void values(V& min, V& max) const;
+
+ protected:
+
+ accu::min<V> min_;
+ accu::max<V> max_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ min_max<V>::min_max()
+ {
+ init();
+ }
+
+ template <typename V>
+ void
+ min_max<V>::init()
+ {
+ min_.init();
+ max_.init();
+ }
+
+ template <typename V>
+ void min_max<V>::take(const value& v)
+ {
+ min_.take(v);
+ max_.take(v);
+ }
+
+ template <typename V>
+ void
+ min_max<V>::take(const min_max<V>& other)
+ {
+ min_.take(other.min_);
+ max_.take(other.max_);
+ }
+
+ template <typename V>
+ V
+ min_max<V>::min() const
+ {
+ return min_.to_value();
+ }
+
+ template <typename V>
+ V
+ min_max<V>::max() const
+ {
+ return max_.to_value();
+ }
+
+ template <typename V>
+ std::pair<V,V>
+ min_max<V>::to_value() const
+ {
+ std::pair<V,V> tmp(min_.to_value(),
+ max_.to_value());
+ return tmp;
+ }
+
+ template <typename V>
+ void
+ min_max<V>::values(V& min, V& max) const
+ {
+ min = min_.to_value();
+ max = max_.to_value();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_MIN_MAX_HH
Index: mln/accu/bbox.hh
--- mln/accu/bbox.hh (revision 1050)
+++ mln/accu/bbox.hh (working copy)
@@ -54,10 +54,11 @@
typedef P value;
bbox();
+
void take(const P& p);
+ void take(const bbox<P>& other);
void init();
- operator box_<P>() const;
const box_<P>& to_value() const;
bool is_valid() const;
@@ -79,7 +80,8 @@
}
template <typename P>
- void bbox<P>::take(const P& p)
+ void
+ bbox<P>::take(const P& p)
{
if (! is_valid_)
{
@@ -97,16 +99,33 @@
template <typename P>
void
- bbox<P>::init()
+ bbox<P>::take(const bbox<P>& other)
{
- is_valid_ = false;
+ if (! other.is_valid_)
+ {
+ // no-op
+ return;
+ }
+ if (! this->is_valid_)
+ {
+ // 'other' makes '*this' valid
+ *this = other;
+ return;
+ }
+ // both are valids so:
+ const box_<P>& o_b = other.b_;
+ for (unsigned i = 0; i < P::dim; ++i)
+ if (o_b.pmin()[i] < b_.pmin()[i])
+ b_.pmin()[i] = o_b.pmin()[i];
+ else if (o_b.pmax()[i] > b_.pmax()[i])
+ b_.pmax()[i] = o_b.pmax()[i];
}
template <typename P>
- bbox<P>::operator box_<P>() const
+ void
+ bbox<P>::init()
{
- mln_precondition(is_valid_);
- return b_;
+ is_valid_ = false;
}
template <typename P>
Index: mln/accu/median.hh
--- mln/accu/median.hh (revision 1050)
+++ mln/accu/median.hh (working copy)
@@ -55,13 +55,13 @@
median(const Value_Set<S>& s);
median();
+ void init();
void take(const value& v);
+ void take(const median<S>& other);
void untake(const value& v);
- void init();
unsigned card() const { return h_.sum(); }
- operator mln_value(S) () const;
value to_value() const;
const accu::histo<S>& histo() const;
@@ -119,6 +119,25 @@
template <typename S>
void
+ median<S>::take(const median<S>& other)
+ {
+ // h_
+ h_.take(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 S>
+ void
median<S>::untake(const value& v)
{
mln_precondition(h_(v) != 0);
@@ -203,12 +222,6 @@
}
template <typename S>
- median<S>::operator mln_value(S) () const
- {
- return to_value();
- }
-
- template <typename S>
typename median<S>::value
median<S>::to_value() const
{
Index: mln/accu/mean.hh
--- mln/accu/mean.hh (revision 1050)
+++ mln/accu/mean.hh (working copy)
@@ -60,14 +60,13 @@
typedef V value;
mean();
- void take(const value& v);
+
void init();
+ void take(const value& v);
+ void take(const mean<V,S,M>& other);
- operator M() const;
M to_value() const;
- mean<V,S,M>& operator+=(const mean<V,S,M>& rhs);
-
protected:
accu::count<V> count_;
@@ -85,13 +84,6 @@
}
template <typename V, typename S, typename M>
- void mean<V,S,M>::take(const value& v)
- {
- count_.take(v);
- sum_.take(v);
- }
-
- template <typename V, typename S, typename M>
void
mean<V,S,M>::init()
{
@@ -100,25 +92,25 @@
}
template <typename V, typename S, typename M>
- mean<V,S,M>::operator M() const
+ void mean<V,S,M>::take(const value& v)
{
- return to_value();
+ count_.take(v);
+ sum_.take(v);
}
template <typename V, typename S, typename M>
- M
- mean<V,S,M>::to_value() const
+ void
+ mean<V,S,M>::take(const mean<V,S,M>& other)
{
- return sum_.to_value() / count_.to_value();
+ count_.take(other.count_);
+ sum_.take(other.sum_);
}
template <typename V, typename S, typename M>
- mean<V,S,M>&
- mean<V,S,M>::operator+=(const mean<V,S,M>& rhs)
+ M
+ mean<V,S,M>::to_value() const
{
- count_ += rhs.count_;
- sum_ += rhs.sum_;
- return *this;
+ return sum_.to_value() / count_.to_value();
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/value/props.hh
--- mln/value/props.hh (revision 1050)
+++ mln/value/props.hh (working copy)
@@ -203,8 +203,9 @@
template <>
struct props<float>
{
- static const float min() { return FLT_MIN; }
- static const float max() { return FLT_MAX; }
+ static const float min = FLT_MIN;
+ static const float max = FLT_MAX;
+ static const float epsilon = 0.00001f;
typedef data_kind kind;
static const std::size_t card_ = 0;
typedef float sum;
@@ -213,8 +214,9 @@
template <>
struct props<double>
{
- static const double min() { return DBL_MIN; }
- static const double max() { return DBL_MAX; }
+ static const double min = DBL_MIN;
+ static const double max = DBL_MAX;
+ static const double epsilon = 0.0000001;
typedef data_kind kind;
static const std::size_t card_ = 0;
typedef double sum;
Index: mln/value/stack.hh
--- mln/value/stack.hh (revision 1050)
+++ mln/value/stack.hh (working copy)
@@ -143,11 +143,13 @@
stack_image<2, const I>
stack(const Image<I>& ima1, const Image<I>& ima2);
+
template <typename I>
stack_image<2, I>
stack(Image<I>& ima1, Image<I>& ima2);
+
# ifndef MLN_INCLUDE_ONLY
// stack_image<n, I>
Index: mln/border/resize.hh
--- mln/border/resize.hh (revision 1050)
+++ mln/border/resize.hh (working copy)
@@ -34,6 +34,7 @@
*/
# include <mln/core/concept/image.hh>
+# include <mln/core/internal/fixme.hh>
namespace mln
@@ -65,10 +66,12 @@
void resize(const Fast_Image<I>& ima_, unsigned thickness)
{
const I& ima = exact(ima_);
- mln_precondition(ima_.has_data());
+ mln_precondition(ima.has_data());
if (ima.border() >= thickness)
return;
- mln_invariant(0); // FIXME: NYI
+ internal::fixme();
+ mln_postcondition(ima.border() >= thickness);
+ return;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/border/fill.hh
--- mln/border/fill.hh (revision 1050)
+++ mln/border/fill.hh (working copy)
@@ -34,6 +34,7 @@
*/
# include <mln/core/concept/image.hh>
+# include <mln/core/internal/fixme.hh>
namespace mln
@@ -62,8 +63,8 @@
void fill(const Fast_Image<I>& ima_, const mln_value(I)& v)
{
const I& ima = exact(ima_);
- mln_precondition(ima_.has_data());
- mln_invariant(0); // FIXME: NYI
+ mln_precondition(ima.has_data());
+ internal::fixme();
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/border/duplicate.hh
--- mln/border/duplicate.hh (revision 1050)
+++ mln/border/duplicate.hh (working copy)
@@ -34,6 +34,7 @@
*/
# include <mln/core/concept/image.hh>
+# include <mln/core/internal/fixme.hh>
namespace mln
@@ -61,8 +62,8 @@
void duplicate(const Fast_Image<I>& ima_)
{
const I& ima = exact(ima_);
- mln_precondition(ima_.has_data());
- mln_invariant(0); // FIXME: NYI
+ mln_precondition(ima.has_data());
+ internal::fixme();
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/border/mirror.hh
--- mln/border/mirror.hh (revision 1050)
+++ mln/border/mirror.hh (working copy)
@@ -34,6 +34,7 @@
*/
# include <mln/core/concept/image.hh>
+# include <mln/core/internal/fixme.hh>
namespace mln
@@ -61,8 +62,8 @@
void mirror(const Fast_Image<I>& ima_)
{
const I& ima = exact(ima_);
- mln_precondition(ima_.has_data());
- mln_invariant(0); // FIXME: NYI
+ mln_precondition(ima.has_data());
+ internal::fixme();
}
# endif // ! MLN_INCLUDE_ONLY