1051: Update accus and add LoG filter.

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