1052: Add some linear filters and augment related tools.

https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add some linear filters and augment related tools. * mln/linear/convolve.hh: Add doc. * mln/linear/log.hh (LoG_7x7, LoG_13x13, LoG_17x17): New. * mln/linear/lap.hh: New. * tests/linear_lap.cc: New. * mln/convert/to_dpoint.hh: Add postcondition. * mln/convert/to_w_window.hh: New. * mln/core/w_window2d_float.hh: New. * mln/make/w_window.hh: New. * mln/make/w_window2d_int.hh: Remove; useless. * mln/core/concept/doc/weighted_window.hh: Augment doc. (weight, window): Rename as... (w, win): ...these. (weight, window): New associated types. * mln/core/concept/weighted_window.hh: Update. * mln/core/window.hh (window_): Rename as... (window): ...this. * mln/core/w_window.hh (w_window_): Rename as... (w_window): ...this. (insert): Swap args; add precondition. Update. * mln/convert/to_image.hh, * mln/convert/to_window.hh, * mln/geom/pmin_pmax.hh, * mln/geom/bbox.hh: New overload. * mln/core/window2d.hh, * mln/core/w_window2d_int.hh, * mln/linear/convolve.hh, * mln/make/w_window2d.hh, * tests/convolve.cc, * tests/pixter_dpoint2d.cc, * tests/w_window2d_int.cc: Update. mln/convert/to_dpoint.hh | 8 +- mln/convert/to_image.hh | 21 +++++ mln/convert/to_w_window.hh | 76 +++++++++++++++++++++ mln/convert/to_window.hh | 29 +++++++- mln/core/concept/doc/weighted_window.hh | 16 ++++ mln/core/concept/weighted_window.hh | 17 +++- mln/core/macros.hh | 10 ++ mln/core/w_window.hh | 114 +++++++++++++++++++++----------- mln/core/w_window2d_float.hh | 56 +++++++++++++++ mln/core/w_window2d_int.hh | 4 - mln/core/window.hh | 46 ++++++------ mln/core/window2d.hh | 2 mln/estim/min_max.hh | 2 mln/geom/bbox.hh | 17 ++++ mln/geom/pmin_pmax.hh | 17 ++++ mln/linear/convolve.hh | 27 ++++--- mln/linear/lap.hh | 113 +++++++++++++++++++++++++++++++ mln/linear/log.hh | 89 +++++++++++++++++++++++- mln/make/w_window.hh | 86 ++++++++++++++++++++++++ mln/make/w_window2d.hh | 15 ++-- tests/convolve.cc | 5 - tests/linear_lap.cc | 51 ++++++++++++++ tests/pixter_dpoint2d.cc | 2 tests/w_window2d_int.cc | 27 ++++--- 24 files changed, 730 insertions(+), 120 deletions(-) Index: tests/convolve.cc --- tests/convolve.cc (revision 1051) +++ tests/convolve.cc (working copy) @@ -38,8 +38,7 @@ #include <mln/math/round.hh> #include <mln/level/transform.hh> -#include <mln/core/w_window.hh> -#include <mln/make/w_window2d.hh> +#include <mln/core/w_window2d_float.hh> #include <mln/border/thickness.hh> #include <mln/linear/convolve.hh> @@ -60,7 +59,7 @@ .04, .04, .04, .04, .04, .04, .04, .04, .04, .04, .04, .04, .04, .04, .04 }; - w_window_<dpoint2d,float> w = make::w_window2d(ws); + w_window2d_float w = make::w_window2d(ws); image2d_b<float> tmp(lena.domain()); linear::convolve(lena, w, tmp); Index: tests/w_window2d_int.cc --- tests/w_window2d_int.cc (revision 1051) +++ tests/w_window2d_int.cc (working copy) @@ -31,18 +31,21 @@ */ #include <mln/core/w_window2d_int.hh> +#include <mln/core/win/rectangle2d.hh> +#include <mln/convert/to_image.hh> +#include <mln/convert/to_w_window.hh> +#include <mln/debug/println.hh> -template <typename W, typename P> -void test(const W& w, const P& p) +struct my_f : mln::Function_p2v< my_f > { - mln_qiter(W) q(w, p); - for_all(q) - std::cout << q << ':' << q.weight() << ' '; - std::cout << std::endl; + typedef int result; + int operator()(const mln::point2d& p) const + { + return p.row() + p.col(); } - +}; int main() @@ -52,8 +55,12 @@ int ws[] = { -1, 0, 1, -2, 0, 2, -1, 0, 1 }; - w_window2d_int ww = make::w_window2d_int(ws); - std::cout << ww << std::endl; + w_window2d_int w_win = make::w_window2d(ws); + + image2d_b<int> ima = convert::to_image(w_win); + w_window2d_int w_win_2 = convert::to_w_window(ima); + mln_assertion(w_win_2 = w_win); - test(ww, make::point2d(0,0)); + w_window2d_int tmp = make::w_window(win::rectangle2d(3, 5), my_f()); + debug::println(convert::to_image(tmp)); } Index: tests/pixter_dpoint2d.cc --- tests/pixter_dpoint2d.cc (revision 1051) +++ tests/pixter_dpoint2d.cc (working copy) @@ -46,7 +46,7 @@ typedef image2d_b<int> I; typedef I::dpoint D; - typedef window_<D> W; + typedef window<D> W; typedef dpoints_fwd_pixter<I> qixter; Index: tests/linear_lap.cc --- tests/linear_lap.cc (revision 0) +++ tests/linear_lap.cc (revision 0) @@ -0,0 +1,51 @@ +// 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_lAP.cc + * + * \brief Tests on mln::linear::lap_4. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/value/int_u8.hh> +#include <mln/io/load_pgm.hh> + +#include <mln/border/thickness.hh> +#include <mln/linear/lap.hh> + + +int main() +{ + using namespace mln; + using value::int_u8; + + border::thickness = 1; + + image2d_b<int_u8> lena = io::load_pgm("../img/lena.pgm"); + image2d_b<int> tmp(lena.domain()); + linear::lap_4(lena, tmp); +} Index: mln/convert/to_image.hh --- mln/convert/to_image.hh (revision 1051) +++ mln/convert/to_image.hh (working copy) @@ -37,6 +37,7 @@ # include <mln/core/concept/point_set.hh> # include <mln/core/concept/window.hh> +# include <mln/core/concept/weighted_window.hh> # include <mln/core/concept/neighborhood.hh> # include <mln/convert/to_window.hh> @@ -62,6 +63,10 @@ template <typename N> image2d_b<bool> to_image(const Neighborhood<N>& nbh); + /// Convert a weighted window \p w_win into an image. + template <typename W> + image2d_b<mln_weight(W)> to_image(const Weighted_Window<W>& w_win); + # ifndef MLN_INCLUDE_ONLY @@ -99,6 +104,22 @@ return to_image(convert::to_window(nbh)); } + template <typename W> + image2d_b<mln_weight(W)> to_image(const Weighted_Window<W>& w_win_) + { + const W& w_win = exact(w_win_); + mln_precondition(! w_win.is_empty()); + + typedef mln_point(W) P; + box2d b = geom::bbox(w_win); + image2d_b<mln_weight(W)> ima(b); + mln_qiter(W) q(w_win, P::zero); + for_all(q) + ima(q) = q.w(); + return ima; + } + + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::convert Index: mln/convert/to_window.hh --- mln/convert/to_window.hh (revision 1051) +++ mln/convert/to_window.hh (working copy) @@ -30,9 +30,10 @@ /*! \file mln/convert/to_window.hh * - * \brief Convertions to mln::Window. + * \brief Conversions to mln::window. */ +# include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> # include <mln/core/window.hh> @@ -45,24 +46,44 @@ /// Convert a neighborhood \p nbh into a window. template <typename N> - window_<mln_dpoint(N)> to_window(const Neighborhood<N>& nbh); + window<mln_dpoint(N)> to_window(const Neighborhood<N>& nbh); + + /// Convert a binary image \p input into a window. + template <typename I> + window<mln_dpoint(I)> to_window(const Image<I>& input); # ifndef MLN_INCLUDE_ONLY template <typename N> - window_<mln_dpoint(N)> to_window(const Neighborhood<N>& nbh_) + window<mln_dpoint(N)> to_window(const Neighborhood<N>& nbh_) { const N& nbh = exact(nbh_); typedef mln_dpoint(N) D; typedef mln_point(D) P; - window_<D> win; + window<D> win; mln_niter(N) n(nbh, P::zero); for_all(n) win.insert(n - P::zero); return win; } + template <typename I> + window<mln_dpoint(I)> to_window(const Image<I>& input_) + { + const I& input = exact(input_); + mln_precondition(input.has_data()); + // FIXME: Check that input is binary! + typedef mln_dpoint(I) D; + typedef mln_point(D) P; + window<D> win; + mln_piter(I) p(input.domain()); + for_all(p) + if (input(p)) + win.insert(p - P::zero); + return win; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::convert Index: mln/convert/to_dpoint.hh --- mln/convert/to_dpoint.hh (revision 1051) +++ mln/convert/to_dpoint.hh (working copy) @@ -53,10 +53,12 @@ mln_dpoint(P) to_dpoint(const Generalized_Point<P>& p_) { const P& p = internal::force_exact<P>(p_); - mln_dpoint(P) tmp; + mln_dpoint(P) dp; for (unsigned i = 0; i < P::dim; ++i) - tmp[i] = p[i]; - return tmp; + dp[i] = p[i]; + typedef mln_point(P) P_; + mln_postcondition(dp = p - P_::zero); + return dp; } # endif // ! MLN_INCLUDE_ONLY Index: mln/convert/to_w_window.hh --- mln/convert/to_w_window.hh (revision 0) +++ mln/convert/to_w_window.hh (revision 0) @@ -0,0 +1,76 @@ +// 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_CONVERT_TO_W_WINDOW_HH +# define MLN_CONVERT_TO_W_WINDOW_HH + +/*! \file mln/convert/to_w_window.hh + * + * \brief Conversions to mln::w_window. + */ + +# include <mln/core/concept/image.hh> +# include <mln/core/window.hh> + + +namespace mln +{ + + namespace convert + { + + /// Convert an image \p input into a weighted window. + template <typename I> + w_window<mln_dpoint(I), mln_value(I)> to_w_window(const Image<I>& input); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + w_window<mln_dpoint(I), mln_value(I)> to_w_window(const Image<I>& input_) + { + const I& input = exact(input_); + mln_precondition(input.has_data()); + // FIXME: Check that input is scalar? + typedef mln_dpoint(I) D; + typedef mln_point(D) P; + w_window<D, mln_value(I)> w_win; + mln_piter(I) p(input.domain()); + for_all(p) + if (input(p) != 0) + w_win.insert(input(p), p - P::zero); + return w_win; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::convert + +} // end of namespace mln + + +#endif // ! MLN_CONVERT_TO_W_WINDOW_HH Index: mln/estim/min_max.hh --- mln/estim/min_max.hh (revision 1051) +++ mln/estim/min_max.hh (working copy) @@ -30,7 +30,7 @@ /*! \file mln/estim/min_max.hh * - * \brief Compute the min_max pixel value. + * \brief Compute the min and max pixel values of an image. */ # include <mln/accu/min_max.hh> Index: mln/geom/pmin_pmax.hh --- mln/geom/pmin_pmax.hh (revision 1051) +++ mln/geom/pmin_pmax.hh (working copy) @@ -51,6 +51,13 @@ pmin_pmax(const Point_Iterator<I>& p); + /// Compute the minimum and maximum points, \p pmin and \p max, + /// when browsing with iterator \p p. + template <typename I> + void + pmin_pmax(const Point_Iterator<I>& p, mln_point(I)& pmin, mln_point(I)& pmax); + + # ifndef MLN_INCLUDE_ONLY @@ -80,6 +87,16 @@ return tmp; } + template <typename I> + void + pmin_pmax(const Point_Iterator<I>& p, mln_point(I)& pmin, mln_point(I)& pmax) + { + typedef mln_point(I) P; + std::pair<P, P> tmp = pmin_pmax(p); + pmin = tmp.first; + pmax = tmp.second; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::geom Index: mln/geom/bbox.hh --- mln/geom/bbox.hh (revision 1051) +++ mln/geom/bbox.hh (working copy) @@ -37,6 +37,7 @@ # include <mln/core/concept/image.hh> # include <mln/core/concept/point_set.hh> # include <mln/core/concept/window.hh> +# include <mln/core/concept/weighted_window.hh> # include <mln/geom/pmin_pmax.hh> @@ -47,12 +48,18 @@ { - /// Compute the precise bounding box of a window \p win centered - /// at the origin. + /// Compute the precise bounding box of a window \p win when + /// centered at the origin. template <typename W> box_<mln_point(W)> bbox(const Window<W>& win); + /// Compute the precise bounding box of a weighted window \p w_win + /// when centered at the origin. + template <typename W> + box_<mln_point(W)> bbox(const Weighted_Window<W>& w_win); + + /// Compute the precise bounding box of a point set \p pset. template <typename S> box_<mln_point(S)> bbox(const Point_Set<S>& pset); @@ -80,6 +87,12 @@ return tmp; } + template <typename W> + box_<mln_point(W)> bbox(const Weighted_Window<W>& w_win) + { + return bbox(exact(w_win).win()); + } + template <typename S> box_<mln_point(S)> bbox(const Point_Set<S>& pset_) { Index: mln/core/macros.hh --- mln/core/macros.hh (revision 1051) +++ mln/core/macros.hh (working copy) @@ -161,6 +161,16 @@ # define mln_viter(T) typename T::fwd_viter +// w + +/// Shortcut to access the weight type associated to T. +# define mln_weight(T) typename T::weight + +/// Shortcut to access the window type associated to T. +# define mln_window(T) typename T::window + + + Index: mln/core/w_window.hh --- mln/core/w_window.hh (revision 1051) +++ mln/core/w_window.hh (working copy) @@ -30,13 +30,13 @@ /*! \file mln/core/w_window.hh * - * \brief Definition of the generic weighted window class mln::w_window_. + * \brief Definition of the generic weighted window class mln::w_window. */ # include <map> -# include <mln/core/concept/weighted_window.hh> # include <mln/core/window.hh> +# include <mln/core/concept/weighted_window.hh> namespace mln @@ -54,7 +54,7 @@ * the type of weights. */ template <typename D, typename W> - struct w_window_ : public Weighted_Window< w_window_<D,W> > + struct w_window : public Weighted_Window< w_window<D,W> > { /// Point associated type. typedef mln_point(D) point; @@ -62,6 +62,12 @@ /// Dpoint associated type. typedef D dpoint; + /// Weight associated type. + typedef W weight; + + /// Window associated type. + typedef mln::window<D> window; + /// Point_Iterator type to browse (forward) the points of a generic w_window. typedef with_w_< dpoints_fwd_piter<D>, W > fwd_qiter; @@ -71,15 +77,15 @@ /// Constructor without argument. - w_window_(); + w_window(); - /// Insert a delta-point \p d and its associated weight \p w. - w_window_<D,W>& insert(const D& d, const W& w); + /// Insert a couple of weight \p w and delta-point \p d. + w_window<D,W>& insert(const W& w, const D& d); /// Give the \p i-th weight. - W weight(unsigned i) const; + W w(unsigned i) const; /// Give access to the vector of weights. const std::vector<W>& weights() const; @@ -95,22 +101,31 @@ const std::vector<D>& vect() const; /// Give the corresponding window. - const window_<D>& window() const; + const mln::window<D>& win() const; /// Give the symmetrical w_window. - w_window_<D,W> sym_() const; + w_window<D,W> sym_() const; protected: - window_<D> win_; + mln::window<D> win_; std::vector<W> wei_; }; - /// Print a weighted window \p wwin into an output stream \p ostr. + /* \brief Print a weighted window \p w_win into an output stream \p ostr. + * \relates mln::w_window + */ template <typename D, typename W> - std::ostream& operator<<(std::ostream& ostr, const w_window_<D,W>& wwin); + std::ostream& operator<<(std::ostream& ostr, const w_window<D,W>& w_win); + + + /* \brief Equality test between two weighted windows \p lhs and \p rhs. + * \relates mln::w_window + */ + template <typename D, typename Wl, typename Wr> + bool operator=(const w_window<D,Wl>& lhs, const w_window<D,Wr>& rhs); @@ -122,7 +137,7 @@ template <typename Ds, typename P> with_w_(const Ds& ds, const P& p); - W weight() const; + W w() const; protected: const std::vector<W> wei_; @@ -146,39 +161,30 @@ template <typename It, typename W> W - with_w_<It,W>::weight() const + with_w_<It,W>::w() const { mln_precondition(this->i_ < wei_.size()); return wei_[this->i_]; } - // w_window_<D,W> - - template <typename D, typename W> - std::ostream& operator<<(std::ostream& ostr, const w_window_<D,W>& wwin) - { - ostr << '['; - for (unsigned i = 0; i < wwin.window().ndpoints(); ++i) - ostr << wwin.vect()[i] << ':' << wwin.weight(i) << ' '; - return ostr << ']'; - } + // w_window<D,W> template <typename D, typename W> - w_window_<D,W>::w_window_() + w_window<D,W>::w_window() { } template <typename D, typename W> - const window_<D>& - w_window_<D,W>::window() const + const mln::window<D>& + w_window<D,W>::win() const { return win_; } template <typename D, typename W> const D& - w_window_<D,W>::dp(unsigned i) const + w_window<D,W>::dp(unsigned i) const { mln_precondition(i < win_.ndpoints()); mln_invariant(wei_.size() = win_.ndpoints()); @@ -187,7 +193,7 @@ template <typename D, typename W> unsigned - w_window_<D,W>::ndpoints() const + w_window<D,W>::ndpoints() const { mln_invariant(wei_.size() = win_.ndpoints()); return win_.ndpoints(); @@ -195,21 +201,21 @@ template <typename D, typename W> const std::vector<D>& - w_window_<D,W>::vect() const + w_window<D,W>::vect() const { return win_.vect(); } template <typename D, typename W> const std::vector<W>& - w_window_<D,W>::weights() const + w_window<D,W>::weights() const { return wei_; } template <typename D, typename W> W - w_window_<D,W>::weight(unsigned i) const + w_window<D,W>::w(unsigned i) const { mln_precondition(i < wei_.size()); mln_invariant(wei_.size() = win_.ndpoints()); @@ -217,12 +223,13 @@ } template <typename D, typename W> - w_window_<D,W>& - w_window_<D,W>::insert(const D& d, const W& w) + w_window<D,W>& + w_window<D,W>::insert(const W& w, const D& d) { mln_invariant(wei_.size() = win_.ndpoints()); + mln_precondition(! win_.has(d)); - if (win_.has(d)) + if (w = W(0)) // FIXME: Implicit restriction "W scalar"... // no-op return *this; @@ -244,19 +251,48 @@ return *this; } - template <typename D, typename W> - w_window_<D,W> - w_window_<D,W>::sym_() const + w_window<D,W> + w_window<D,W>::sym_() const { - w_window_<D,W> tmp(*this); + w_window<D,W> tmp(*this); tmp.win_ = - this->win_; return *this; } + // operators + + template <typename D, typename W> + std::ostream& operator<<(std::ostream& ostr, const w_window<D,W>& w_win) + { + ostr << '['; + for (unsigned i = 0; i < w_win.win().ndpoints(); ++i) + ostr << w_win.vect()[i] << ':' << w_win.w(i) << ' '; + return ostr << ']'; + } + + template <typename D, typename Wl, typename Wr> + bool operator=(const w_window<D,Wl>& lhs, const w_window<D,Wr>& rhs) + { + if (lhs.ndpoints() != rhs.ndpoints()) + return false; + if (lhs.win() != rhs.win()) + return false; + const std::vector<Wl>& wl = lhs.weights(); + const std::vector<Wr>& wr = rhs.weights(); + mln_assertion(wl.size() = wr.size()); + for (unsigned i = 0; i < wl.size(); ++i) + if (wr[i] != wl[i]) + return false; + return true; + } + # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln +# include <mln/make/w_window.hh> + + #endif // ! MLN_CORE_W_WINDOW_HH Index: mln/core/window.hh --- mln/core/window.hh (revision 1051) +++ mln/core/window.hh (working copy) @@ -30,7 +30,7 @@ /*! \file mln/core/window.hh * - * \brief Definition of the generic window class mln::window_. + * \brief Definition of the generic window class mln::window. */ # include <mln/core/concept/window.hh> @@ -56,10 +56,10 @@ * parameter is \c D, type of delta-point. */ template <typename D> - class window_ : public Window< window_<D> >, - public internal::dpoints_base_<D, window_<D> > + class window : public Window< window<D> >, + public internal::dpoints_base_<D, window<D> > { - typedef internal::dpoints_base_<D, window_<D> > super_; + typedef internal::dpoints_base_<D, window<D> > super_; public: /*! \brief Point_Iterator type to browse the points of a generic window @@ -77,7 +77,7 @@ * * The constructed window is empty. */ - window_(); + window(); /*! \brief Test if the window is symmetric. @@ -85,10 +85,10 @@ bool is_symmetric() const; /// Insert a delta-point \p dp. - window_<D>& insert(const D& dp); + window<D>& insert(const D& dp); /// Give the symmetrical window. - window_<D> sym_() const; + window<D> sym_() const; protected: @@ -100,40 +100,40 @@ /// Shift a window \p win with a delta-point \p dp. template <typename W> - window_<mln_dpoint(W)> operator+(const Window<W>& win, + window<mln_dpoint(W)> operator+(const Window<W>& win, const mln_dpoint(W)& dp); /// Shift a window \p win with the delta-point (-\p dp). template <typename W> - window_<mln_dpoint(W)> operator-(const Window<W>& win, + window<mln_dpoint(W)> operator-(const Window<W>& win, const mln_dpoint(W)& dp); /// Substract \p rhs from \p lhs. // FIXME: Give details! template <typename Wl, typename Wr> - window_<mln_dpoint(Wl)> operator-(const Window<Wl>& lhs, + window<mln_dpoint(Wl)> operator-(const Window<Wl>& lhs, const Window<Wr>& rhs); # ifndef MLN_INCLUDE_ONLY - // window_<D> + // window<D> template <typename D> - window_<D>::window_() + window<D>::window() { } template <typename D> - bool window_<D>::is_symmetric() const + bool window<D>::is_symmetric() const { return this->sym_() = *this; } template <typename D> - window_<D>& - window_<D>::insert(const D& dp) + window<D>& + window<D>::insert(const D& dp) { mln_precondition(! has(dp)); this->super_::insert(dp); @@ -141,10 +141,10 @@ } template <typename D> - window_<D> - window_<D>::sym_() const + window<D> + window<D>::sym_() const { - window_<D> tmp; + window<D> tmp; const unsigned n = this->ndpoints(); for (unsigned i = 0; i < n; ++i) tmp.insert(- this->dp(i)); @@ -155,11 +155,11 @@ // operators template <typename W> - window_<mln_dpoint(W)> operator+(const Window<W>& win, + window<mln_dpoint(W)> operator+(const Window<W>& win, const mln_dpoint(W)& dp) { typedef mln_point(W) P; - window_<mln_dpoint(W)> tmp; + window<mln_dpoint(W)> tmp; mln_qiter(W) q(win, P::zero); for_all(q) tmp.insert(convert::to_dpoint(q) + dp); @@ -167,18 +167,18 @@ } template <typename W> - window_<mln_dpoint(W)> operator-(const Window<W>& win, + window<mln_dpoint(W)> operator-(const Window<W>& win, const mln_dpoint(W)& dp) { return win + (-dp); } template <typename W, typename Wr> - window_<mln_dpoint(W)> operator-(const Window<W>& lhs, + window<mln_dpoint(W)> operator-(const Window<W>& lhs, const Window<Wr>& rhs) { typedef mln_point(W) P; - window_<mln_dpoint(W)> tmp; + window<mln_dpoint(W)> tmp; mln_qiter(W) q(lhs, P::zero); for_all(q) { Index: mln/core/window2d.hh --- mln/core/window2d.hh (revision 1051) +++ mln/core/window2d.hh (working copy) @@ -44,7 +44,7 @@ /*! \brief Type alias for a window with arbitrary shape, defined on * the 2D square grid with integer coordinates. */ - typedef window_<dpoint2d> window2d; + typedef window<dpoint2d> window2d; } // end of namespace mln Index: mln/core/concept/weighted_window.hh --- mln/core/concept/weighted_window.hh (revision 1051) +++ mln/core/concept/weighted_window.hh (working copy) @@ -55,6 +55,8 @@ typedef point; typedef dpoint; + typedef weight; + typedef window; E sym_() const; */ @@ -62,13 +64,13 @@ /// Test if the weighted window is empty; final method. bool is_empty() const { - return exact(this)->window().is_empty(); + return exact(this)->win().is_empty(); } /// Test if the weighted window is centered; final method. bool is_centered() const { - return exact(this)->window().is_centered(); + return exact(this)->win().is_centered(); } // FIXME: Remove because too ambiguous: bool is_symmetric() const @@ -76,7 +78,7 @@ /// Give the maximum coordinate gap. unsigned delta() const { - return exact(this)->window().delta(); + return exact(this)->win().delta(); } protected: @@ -99,12 +101,17 @@ { typedef mln_point(E) point; typedef mln_dpoint(E) dpoint; + typedef mln_weight(E) weight; + typedef mln_window(E) window; typedef mln_fwd_qiter(E) fwd_qiter; typedef mln_bkd_qiter(E) bkd_qiter; - E (E::*m_)() const = & E::sym_; - m_ = 0; + E (E::*m1)() const = & E::sym_; + m1 = 0; + + const window& (E::*m2)() const = & E::win; + m2 = 0; } template <typename W> Index: mln/core/concept/doc/weighted_window.hh --- mln/core/concept/doc/weighted_window.hh (revision 1051) +++ mln/core/concept/doc/weighted_window.hh (working copy) @@ -56,6 +56,18 @@ */ typedef void bkd_qiter; + /// Point associated type. + typedef void point; + + /// Dpoint associated type. + typedef void dpoint; + + /// Weight associated type. + typedef void weight; + + /// Window associated type. + typedef void window; + /*! \brief Test if the weighted window is empty. * * A weighted_window of null size is empty. @@ -73,6 +85,10 @@ */ unsigned delta() const; + /*! \brief Give the corresponding window. + */ + const window& win() const; + /*! \brief Give the symmetrical weighted_window. */ E sym_() const; Index: mln/core/w_window2d_int.hh --- mln/core/w_window2d_int.hh (revision 1051) +++ mln/core/w_window2d_int.hh (working copy) @@ -44,13 +44,13 @@ * on the 2D square grid (with integer coordinates) and whose * weights are integers. */ - typedef w_window_<dpoint2d, int> w_window2d_int; + typedef w_window<dpoint2d, int> w_window2d_int; } // end of namespace mln -# include <mln/make/w_window2d_int.hh> +# include <mln/make/w_window2d.hh> #endif // ! MLN_CORE_W_WINDOW2D_INT_HH Index: mln/core/w_window2d_float.hh --- mln/core/w_window2d_float.hh (revision 0) +++ mln/core/w_window2d_float.hh (revision 0) @@ -0,0 +1,56 @@ +// 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_CORE_W_WINDOW2D_FLOAT_HH +# define MLN_CORE_W_WINDOW2D_FLOAT_HH + +/*! \file mln/core/w_window2d_float.hh + * + * \brief Definition of the mln::w_window2d_float alias. + */ + +# include <mln/core/w_window.hh> +# include <mln/core/dpoint2d.hh> + + +namespace mln +{ + + /*! \brief Type alias for a w_window with arbitrary shape, defined + * on the 2D square grid (with integer coordinates) and whose + * weights are floating values. + */ + typedef w_window<dpoint2d, float> w_window2d_float; + + +} // end of namespace mln + + +# include <mln/make/w_window2d.hh> + + +#endif // ! MLN_CORE_W_WINDOW2D_FLOAT_HH Index: mln/linear/log.hh --- mln/linear/log.hh (revision 1051) +++ mln/linear/log.hh (working copy) @@ -34,7 +34,7 @@ */ # include <mln/linear/convolve.hh> -# include <mln/make/w_window2d_int.hh> +# include <mln/make/w_window2d.hh> @@ -47,21 +47,96 @@ template <typename I, typename O> void LoG_5x5(const Image<I>& input, Image<O>& output); + template <typename I, typename O> + void LoG_7x7(const Image<I>& input, Image<O>& output); + + template <typename I, typename O> + void LoG_13x13(const Image<I>& input, Image<O>& output); + + template <typename I, typename O> + void LoG_17x17(const Image<I>& input, Image<O>& output); + # ifndef MLN_INCLUDE_ONLY // LoG_5x5 (Cf. Sonka et al., pages 85-86) + // This is also a "mexican hat". 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, + 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); + +0, -1, -2, -1, 0, + +0, 0, -1, 0, 0 }; + convolve(input, make::w_window2d(ws), output); + } + + // LoG 7x7 (Cf. Russ, p. 250) + + template <typename I, typename O> + void LoG_7x7(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { +0, 0, -1, -1, -1, 0, 0, + +0, -1, -3, -3, -3, -1, 0, + -1, -3, 0, 7, 0, -3, -1, + -1, -3, 7, 24, 7, -3, -1, + -1, -3, 0, 7, 0, -3, -1, + +0, -1, -3, -3, -3, -1, 0, + +0, 0, -1, -1, -1, 0, 0 }; + convolve(input, make::w_window2d(ws), output); + } + + // LoG 13x13 (Cf. Russ, p. 250) + + template <typename I, typename O> + void LoG_13x13(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { +0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, + +0, 0, 0, -1, -1, -2, -2, -2, -1, -1, 0, 0, 0, + +0, 0, -2, -2, -3, -3, -4, -3, -3, -2, -2, 0, 0, + +0, -1, -2, -3, -3, -3, -2, -3, -3, -3, -2, -1, 0, + +0, -1, -3, -3, -1, 4, 6, 4, -1, -3, -3, -1, 0, + -1, -2, -3, -3, 4, 14, 19, 14, 4, -3, -3, -2, -1, + -1, -2, -4, -2, 6, 19, 24, 19, 6, -2, -4, -2, -1, + -1, -2, -3, -3, 4, 14, 19, 14, 4, -3, -3, -2, -1, + +0, -1, -3, -3, -1, 4, 6, 4, -1, -3, -3, -1, 0, + +0, -1, -2, -3, -3, -3, -2, -3, -3, -3, -2, -1, 0, + +0, 0, -2, -2, -3, -3, -4, -3, -3, -2, -2, 0, 0, + +0, 0, 0, -1, -1, -2, -2, -2, -1, -1, 0, 0, 0, + +0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0 }; + convolve(input, make::w_window2d(ws), output); + } + + + // LoG 17x17 (Cf. Sonka et al., pages 85-86) + + template <typename I, typename O> + void LoG_17x17(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, + +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, + +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0, + +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0, + +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0, + +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0, + -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1, + -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1, + -1,-1,-3,-3,-3, 4,12,21,24,21,12, 4,-3,-3,-3,-1,-1, + -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1, + -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1, + +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0, + +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0, + +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0, + +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0, + +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, + +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0 }; + convolve(input, make::w_window2d(ws), output); } # endif // ! MLN_INCLUDE_ONLY @@ -71,4 +146,4 @@ } // end of namespace mln -#endif // ! MLN_LINEAR_CONVOLVE_HH +#endif // ! MLN_LINEAR_LOG_HH Index: mln/linear/convolve.hh --- mln/linear/convolve.hh (revision 1051) +++ mln/linear/convolve.hh (working copy) @@ -48,10 +48,13 @@ /*! Convolution of image \p input by the weighted window \p win. * + * \warning Computation of \p output(p) is performed with the + * value type of \p output. + * * \pre output.domain = input.domain */ template <typename I, typename W, typename O> - void convolve(const Image<I>& input, const Weighted_Window<W>& win, + void convolve(const Image<I>& input, const Weighted_Window<W>& w_win, Image<O>& output); @@ -61,47 +64,47 @@ { template <typename I, typename W, typename O> - void convolve(const Image<I>& input_, const Weighted_Window<W>& win_, + void convolve(const Image<I>& input_, const Weighted_Window<W>& w_win_, Image<O>& output_) { const I& input = exact(input_); - const W& win = exact(win_); + const W& w_win = exact(w_win_); O& output = exact(output_); mln_piter(I) p(input.domain()); - mln_qiter(W) q(win, p); + mln_qiter(W) q(w_win, p); for_all(p) { mln_value(O) v = 0; for_all(q) if (input.has(q)) - v += input(q) * q.weight(); + v += input(q) * q.w(); output(p) = v; } } template <typename I, typename W, typename O> - void convolve(const Fast_Image<I>& input_, const Weighted_Window<W>& win_, + void convolve(const Fast_Image<I>& input_, const Weighted_Window<W>& w_win_, Fast_Image<O>& output_) { const I& input = exact(input_); - const W& win = exact(win_); + const W& w_win = exact(w_win_); O& output = exact(output_); - border::resize(input, win.delta()); + border::resize(input, w_win.delta()); border::duplicate(input); mln_pixter(O) p_out(output); mln_pixter(const I) p(input); - mln_qixter(const I, W) q(input, win, p); + mln_qixter(const I, W) q(input, w_win, p); for_all_2(p, p_out) { mln_value(O) v = 0; unsigned i = 0; for_all(q) - v += win.weight(i++) * *q; + v += w_win.w(i++) * *q; *p_out = v; } } @@ -109,11 +112,11 @@ } // end of namespace mln::linear::impl template <typename I, typename W, typename O> - void convolve(const Image<I>& input, const Weighted_Window<W>& win, + void convolve(const Image<I>& input, const Weighted_Window<W>& w_win, Image<O>& output) { mln_precondition(exact(output).domain() = exact(input).domain()); - impl::convolve(exact(input), exact(win), exact(output)); + impl::convolve(exact(input), - exact(w_win), exact(output)); } # endif // ! MLN_INCLUDE_ONLY Index: mln/linear/lap.hh --- mln/linear/lap.hh (revision 0) +++ mln/linear/lap.hh (revision 0) @@ -0,0 +1,113 @@ +// 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_LAP_HH +# define MLN_LINEAR_LAP_HH + +/*! \file mln/linear/lap.hh + * + * \brief Laplacian. + */ + +# include <mln/linear/convolve.hh> +# include <mln/make/w_window2d.hh> + + + +namespace mln +{ + + namespace linear + { + + // FIXME: Doc! + + template <typename I, typename O> + void lap_4(const Image<I>& input, Image<O>& output); + + template <typename I, typename O> + void lap_8(const Image<I>& input, Image<O>& output); + + template <typename I, typename O> + void lap_x(const Image<I>& input, Image<O>& output); + + template <typename I, typename O> + void lap_o(const Image<I>& input, Image<O>& output); + + +# ifndef MLN_INCLUDE_ONLY + + // Laplacian operators (Cf. Sonka et al., p. 81) + + template <typename I, typename O> + void lap_4(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { 0, 1, 0, + 1, -4, 1, + 0, 1, 0 }; + convolve(input, make::w_window2d(ws), output); + } + + template <typename I, typename O> + void lap_8(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { 1, 1, 1, + 1, -8, 1, + 1, 1, 1 }; + convolve(input, make::w_window2d(ws), output); + } + + template <typename I, typename O> + void lap_x(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { +2, -1, +2, + -1, -4, -1, + +2, -1, +2 }; + convolve(input, make::w_window2d(ws), output); + } + + template <typename I, typename O> + void lap_o(const Image<I>& input, Image<O>& output) + { + mln_precondition(exact(output).domain() = exact(input).domain()); + int ws[] = { -1, +2, -1, + +2, -4, +2, + -1, +2, -1 }; + convolve(input, make::w_window2d(ws), output); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::linear + +} // end of namespace mln + + +#endif // ! MLN_LINEAR_LAP_HH Index: mln/make/w_window2d.hh --- mln/make/w_window2d.hh (revision 1051) +++ mln/make/w_window2d.hh (working copy) @@ -30,12 +30,13 @@ /*! \file mln/make/w_window2d.hh * - * \brief Routine to create an mln::w_window_ in the 2D case. + * \brief Routine to create an mln::w_window in the 2D case. */ # include <cmath> + # include <mln/core/w_window.hh> -# include <mln/make/dpoint2d.hh> +# include <mln/core/dpoint2d.hh> namespace mln @@ -44,7 +45,7 @@ namespace make { - /*! \brief Create a mln::w_window_ in the 2D case. + /*! \brief Create a 2D mln::w_window from an array of weights. * * \param[in] weights Array. * @@ -53,24 +54,24 @@ * \return A 2D weighted window. */ template <typename W, unsigned M> - mln::w_window_<mln::dpoint2d, W> w_window2d(W (&weights)[M]); + mln::w_window<mln::dpoint2d, W> w_window2d(W (&weights)[M]); # ifndef MLN_INCLUDE_ONLY template <typename W, unsigned M> - mln::w_window_<mln::dpoint2d, W> + mln::w_window<mln::dpoint2d, W> w_window2d(W (&weights)[M]) { int h = unsigned(std::sqrt(float(M))) / 2; mln_precondition((2 * h + 1) * (2 * h + 1) = M); - mln::w_window_<mln::dpoint2d, W> tmp; + mln::w_window<mln::dpoint2d, W> tmp; unsigned i = 0; for (int row = - h; row <= h; ++row) for (int col = - h; col <= h; ++col) { if (weights[i] != 0) - tmp.insert(make::dpoint2d(row, col), weights[i]); + tmp.insert(weights[i], make::dpoint2d(row, col)); i++; } return tmp; Index: mln/make/w_window.hh --- mln/make/w_window.hh (revision 0) +++ mln/make/w_window.hh (revision 0) @@ -0,0 +1,86 @@ +// 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_MAKE_W_WINDOW_HH +# define MLN_MAKE_W_WINDOW_HH + +/*! \file mln/make/w_window.hh + * + * \brief Routine to create a mln::w_window. + */ + +# include <mln/core/concept/window.hh> +# include <mln/core/concept/function.hh> +# include <mln/core/w_window.hh> + + +namespace mln +{ + + namespace make + { + + /*! \brief Create a mln::w_window from a window and a weight + * function. + * + * \param[in] weights Array. + * + * \pre The array size, \c M, has to be a square of an odd integer. + * + * \return A weighted window. + */ + template <typename W, typename F> + mln::w_window<mln_dpoint(W), mln_result(F)> w_window(const Window<W>& win, + const Function_p2v<F>& wei); + + +# ifndef MLN_INCLUDE_ONLY + + template <typename W, typename F> + mln::w_window<mln_dpoint(W), mln_result(F)> w_window(const Window<W>& win_, + const Function_p2v<F>& wei_) + { + const W& win = exact(win_); + const F& wei = exact(wei_); + mln_precondition(! win.is_empty()); + typedef mln_dpoint(W) D; + typedef mln_point(D) P; + mln::w_window<D, mln_result(F)> w_win; + mln_qiter(W) q(win, P::zero); + for_all(q) + w_win.insert(wei(q), q - P::zero); + return w_win; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::make + +} // end of namespace mln + + +#endif // ! MLN_MAKE_W_WINDOW_HH
participants (1)
-
Thierry Geraud