
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add stack and transpose morphers. * tests/t_image.cc: New. * tests/stack.cc: New. * tests/approx_median.cc: New. * mln/core/t_image.hh: New. * mln/value/stack.hh: New. * tests/median.cc: Update. * tests/README: Update. * mln/core/internal/image_base.hh (morpher_lvalue_): New. * mln/core/internal/image_adaptor.hh: Use morpher_lvalue_. (image_adaptor_): Change Image<I> into I. * mln/core/safe.hh: Update. * mln/core/image2d_b.hh: Remove dead code. * mln/metal/vec.hh: Split decls and defs. (operator<<): New. * mln/level/median.hh (hline2d): Update. (vline2d): New. mln/core/image2d_b.hh | 18 --- mln/core/internal/image_adaptor.hh | 8 - mln/core/internal/image_base.hh | 13 ++ mln/core/safe.hh | 4 mln/core/t_image.hh | 178 ++++++++++++++++++++++++++++++++++ mln/level/median.hh | 45 ++++---- mln/metal/vec.hh | 44 +++++++- mln/value/stack.hh | 191 +++++++++++++++++++++++++++++++++++++ tests/README | 14 ++ tests/approx_median.cc | 59 +++++++++++ tests/median.cc | 4 tests/stack.cc | 49 +++++++++ tests/t_image.cc | 52 ++++++++++ 13 files changed, 626 insertions(+), 53 deletions(-) Index: tests/median.cc --- tests/median.cc (revision 1041) +++ tests/median.cc (working copy) @@ -38,7 +38,6 @@ #include <mln/value/int_u8.hh> #include <mln/level/median.hh> -#include <mln/level/approx/median.hh> @@ -57,7 +56,4 @@ level::median(lena, rect, out); io::save_pgm(out, "out.pgm"); - -// level::approx::median(lena, rec, out); -// io::save_pgm(out, "outa.pgm"); } Index: tests/t_image.cc --- tests/t_image.cc (revision 0) +++ tests/t_image.cc (revision 0) @@ -0,0 +1,52 @@ +// 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/+t_image.cc + * + * \brief Tests on mln::t_image. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/core/t_image.hh> + +#include <mln/debug/iota.hh> +#include <mln/debug/println.hh> + + +int main() +{ + using namespace mln; + + typedef image2d_b<int> I; + + I ima(2, 3); + debug::iota(ima); + debug::println(ima); + + t_image<I> tima(ima, 0, 1); + debug::println(tima); +} Index: tests/stack.cc --- tests/stack.cc (revision 0) +++ tests/stack.cc (revision 0) @@ -0,0 +1,49 @@ +// 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/stack.cc + * + * \brief Tests on mln::value::stack. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/value/stack.hh> +#include <mln/debug/iota.hh> +#include <mln/debug/println.hh> + + +int main() +{ + using namespace mln; + + typedef image2d_b<int> I; + + I ima(2, 3); + debug::iota(ima); + debug::println(ima); + debug::println(value::stack(ima, ima)); +} Index: tests/approx_median.cc --- tests/approx_median.cc (revision 0) +++ tests/approx_median.cc (revision 0) @@ -0,0 +1,59 @@ +// 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/approx_median.cc + * + * \brief Test on mln::level::approx::median. + */ + +#include <mln/core/image2d_b.hh> +#include <mln/core/win/rectangle2d.hh> + +#include <mln/io/load_pgm.hh> +#include <mln/io/save_pgm.hh> + +#include <mln/value/int_u8.hh> +#include <mln/level/approx/median.hh> + + + + +int main() +{ + using namespace mln; + using value::int_u8; + + win::rectangle2d rect(51, 51); + border::thickness = 52; + + image2d_b<int_u8> + lena = io::load_pgm("../img/lena.pgm"), + out(lena.domain()); + + level::approx::median(lena, rect, out); + io::save_pgm(out, "out.pgm"); +} Index: tests/README --- tests/README (revision 1041) +++ tests/README (working copy) @@ -1,3 +1,17 @@ + + -*- outline -*- + + +* compilation + g++-4.1 -ansi -pedantic -W -Wall -Wextra -Wconversion -I.. sample.cc g++-2.95 -ansi -pedantic -W -Wall -Wconversion -ftemplate-depth-51 -I.. sample.cc + + +* bench + +naive: 18s +median: 1s +approx: 0.05s + Index: mln/core/internal/image_adaptor.hh --- mln/core/internal/image_adaptor.hh (revision 1041) +++ mln/core/internal/image_adaptor.hh (working copy) @@ -68,7 +68,7 @@ typedef mln_rvalue(I) rvalue; /// Return type of read-write access. - typedef mln_lvalue(I) lvalue; + typedef typename internal::morpher_lvalue_<I>::ret lvalue; /// Test if this image has been initialized. @@ -94,7 +94,7 @@ I& adaptee_; /// Constructor from an \p adaptee image. - image_adaptor_(Image<I>& adaptee); + image_adaptor_(I& adaptee); }; // FIXME: image_const_adaptor_ @@ -148,8 +148,8 @@ } template <typename I, typename E, typename S> - image_adaptor_<I,E,S>::image_adaptor_(Image<I>& adaptee) - : adaptee_(exact(adaptee)) + image_adaptor_<I,E,S>::image_adaptor_(I& adaptee) + : adaptee_(adaptee) { } Index: mln/core/internal/image_base.hh --- mln/core/internal/image_base.hh (revision 1041) +++ mln/core/internal/image_base.hh (working copy) @@ -43,6 +43,19 @@ { + template <typename I> + struct morpher_lvalue_ + { + typedef mln_lvalue(I) ret; + }; + + template <typename I> + struct morpher_lvalue_< const I > + { + typedef mln_rvalue(I) ret; + }; + + template <typename Is_fast, typename E> struct select_image_concept_; Index: mln/core/safe.hh --- mln/core/safe.hh (revision 1041) +++ mln/core/safe.hh (working copy) @@ -51,6 +51,7 @@ { typedef safe_image<mln_ch_value(I, U)> ret; }; + }; @@ -62,10 +63,9 @@ # ifndef MLN_INCLUDE_ONLY - template <typename I> safe_image<I>::safe_image(Image<I>& ima) - : super(ima) + : super(exact(ima)) { } Index: mln/core/t_image.hh --- mln/core/t_image.hh (revision 0) +++ mln/core/t_image.hh (revision 0) @@ -0,0 +1,178 @@ +// 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_T_IMAGE_HH +# define MLN_CORE_T_IMAGE_HH + +/*! \file mln/core/t_image.hh + * + * \brief Definition of the "transposed" image class mln::t_image. + */ + +# include <mln/core/internal/image_adaptor.hh> + + +namespace mln +{ + + + /*! \brief Transposed image class. + * + * Swap a couple of coordinates. + * + * \warning This class only works on images whose domain is a box. + */ + template <typename I> + struct t_image : public internal::image_adaptor_< I, t_image<I> > + { + + /// Test if a pixel value is accessible at \p p. + bool owns_(const mln_point(I)& p) const; + + /// Give the definition domain. + const box_<mln_point(I)>& domain() const; + + /// Read-only access of pixel value at point site \p p. + mln_rvalue(I) operator()(const mln_point(I)& p) const; + + /// Type returned by the read-write pixel value operator. + typedef typename internal::morpher_lvalue_<I>::ret lvalue; + + /// Read-write access of pixel value at point site \p p. + lvalue operator()(const mln_point(I)& p); + + + /// Change value type. + template <typename U> + struct change_value + { + typedef mln_ch_value(I, U) ret; + }; + + + /// Constructor. + t_image(I& ima, unsigned c1, unsigned c2); + + protected: + + typedef internal::image_adaptor_< I, t_image<I> > super_; + const unsigned c1_, c2_; // coords to swap + box_<mln_point(I)> b_; + + mln_point(I) transpose_(const mln_point(I)& p) const; + }; + + + template <typename I> + t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2); + + template <typename I> + t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2); + + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + t_image<I> swap_coords(Image<I>& ima, unsigned c1, unsigned c2) + { + typedef mln_point(I) P; + mln_precondition(c1 != c2); + mln_precondition(c1 <= P::dim && c2 <= P::dim); + t_image<I> tmp(exact(ima), c1, c2); + return tmp; + } + + template <typename I> + t_image<const I> swap_coords(const Image<I>& ima, unsigned c1, unsigned c2) + { + typedef mln_point(I) P; + mln_precondition(c1 != c2); + mln_precondition(c1 <= P::dim && c2 <= P::dim); + t_image<const I> tmp(exact(ima), c1, c2); + return tmp; + } + + template <typename I> + t_image<I>::t_image(I& ima, unsigned c1, unsigned c2) + : super_(ima), + c1_(c1), + c2_(c2) + { + mln_precondition(ima.has_data()); + b_.pmin() = transpose_(this->adaptee_.bbox().pmin()); + b_.pmax() = transpose_(this->adaptee_.bbox().pmax()); + } + + template <typename I> + mln_point(I) + t_image<I>::transpose_(const mln_point(I)& p) const + { + mln_point(I) tmp(p); + tmp[c1_] = p[c2_]; + tmp[c2_] = p[c1_]; + return tmp; + } + + template <typename I> + const box_<mln_point(I)>& + t_image<I>::domain() const + { + mln_precondition(this->has_data()); + return b_; + } + + template <typename I> + bool + t_image<I>::owns_(const mln_point(I)& p) const + { + mln_precondition(this->has_data()); + return this->adaptee_.owns_(transpose_(p)); + } + + template <typename I> + mln_rvalue(I) + t_image<I>::operator()(const mln_point(I)& p) const + { + mln_precondition(this->owns_(p)); + return this->adaptee_(transpose_(p)); + } + + template <typename I> + typename internal::morpher_lvalue_<I>::ret + t_image<I>::operator()(const mln_point(I)& p) + { + mln_precondition(this->owns_(p)); + return this->adaptee_(transpose_(p)); + } + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + + +#endif // ! MLN_CORE_T_IMAGE_HH Index: mln/core/image2d_b.hh --- mln/core/image2d_b.hh (revision 1041) +++ mln/core/image2d_b.hh (working copy) @@ -78,28 +78,14 @@ struct image2d_b : public internal::image_base_< box2d, image2d_b<T> >, public internal::box_impl_< 2, int, image2d_b<T> > { - - // warning: just to make effective types appear in Doxygen + // Warning: just to make effective types appear in Doxygen: typedef box2d pset; typedef point2d psite; typedef point2d point; typedef dpoint2d dpoint; typedef mln_fwd_piter(box2d) fwd_piter; typedef mln_bkd_piter(box2d) bkd_piter; - // end of warning - - - - // FIXME: - -// /// Forward pixel iterator associated to image2d -// typedef fwd_pixter2d_b<T> fwd_pixter; - -// /// Foward pixel iterator on dpoints assoicated to image 2d -// typedef dpoints_pixter< image2d_b<T> > fwd_qixter; - -// typedef fwd_pixter pixter; -// typedef fwd_qixter qixter; + // End of warning. /// Value associated type. Index: mln/metal/vec.hh --- mln/metal/vec.hh (revision 1041) +++ mln/metal/vec.hh (working copy) @@ -28,6 +28,8 @@ #ifndef MLN_CORE_METAL_VEC_HH # define MLN_CORE_METAL_VEC_HH +# include <cstdarg> + # include <mln/core/concept/object.hh> @@ -37,27 +39,55 @@ namespace metal { + // FIXME: Doc! + Change coord into comp. + template <unsigned n, typename T> struct vec : public Object< vec<n,T> > { enum { dim = n }; typedef T coord; - T& operator[](unsigned i) + T& operator[](unsigned i); + T operator[](unsigned i) const; + + protected: + T coord_[n]; + }; + + + template <unsigned n, typename T> + std::ostream& operator<<(std::ostream& ostr, const vec<n,T>& v); + + +# ifndef MLN_INCLUDE_ONLY + + template <unsigned n, typename T> + T& + vec<n,T>::operator[](unsigned i) { - assert(i < n); + mln_precondition(i < n); return coord_[i]; } - T operator[](unsigned i) const + template <unsigned n, typename T> + T + vec<n,T>::operator[](unsigned i) const { - assert(i < n); + mln_precondition(i < n); return coord_[i]; } - protected: - T coord_[n]; - }; + template <unsigned n, typename T> + std::ostream& operator<<(std::ostream& ostr, const vec<n,T>& v) + { + ostr << "[ "; + for (unsigned i = 0; i < n; ++i) + ostr << v[i] << ' '; + return ostr << ']'; + } + +# endif // ! MLN_INCLUDE_ONLY + } // end of namespace mln::metal Index: mln/level/median.hh --- mln/level/median.hh (revision 1041) +++ mln/level/median.hh (working copy) @@ -38,6 +38,7 @@ # include <mln/core/window2d.hh> # include <mln/core/win/hline2d.hh> +# include <mln/core/t_image.hh> # include <mln/accu/median.hh> # include <mln/canvas/sbrowsing.hh> @@ -156,37 +157,41 @@ } - - template <typename I, typename O> void median(const I& input, const win::hline2d& win, O& output) { typedef mln_coord(I) coord; const coord - max_row = input.max_row(), - min_col = input.min_col(), - max_col = input.max_col(); + max_row = input.bbox().max_row(), + min_col = input.bbox().min_col(), + max_col = input.bbox().max_col(); const coord half = win.length() / 2; point2d p; coord& row = p.row(); coord& col = p.col(); + point2d pt; + coord& ct = pt.col(); + + point2d pu; + coord& cu = pu.col(); + accu::median<mln_vset(I)> med(input.values()); - for (row = input.min_row(); row <= max_row; ++row) + for (row = input.bbox().min_row(); row <= max_row; ++row) { - coord ct, cu; + pt.row() = pu.row() = row; // initialization (before first point of the row) med.init(); for (ct = min_col; ct < min_col + half; ++ct) - med.take(input.at(row, ct)); + med.take(input(pt)); // left columns (just take new points) for (col = min_col; col <= min_col + half; ++col, ++ct) { - med.take(input.at(row, ct)); + med.take(input(pt)); output(p) = med; } @@ -194,29 +199,29 @@ cu = min_col; for (; col <= max_col - half; ++cu, ++col, ++ct) { - med.take(input.at(row, ct)); - med.untake(input.at(row, cu)); + med.take(input(pt)); + med.untake(input(pu)); output(p) = med; } // right columns (now just untake old points) for (; col <= max_col; ++cu, ++col) { - med.untake(input.at(row, cu)); + med.untake(input(pu)); output(p) = med; } } } - // FIXME: Use transpose. - -// template <typename I, typename O> -// void median(const I& input, const win::vline2d& win, O& output) -// { - -// median(, win::hline2d(win.length()), output); -// } + template <typename I, typename O> + void median(const I& input, const win::vline2d& win, O& output) + { + t_image<O> swap_output = swap_coords(output, 0, 1); + impl::median(swap_coords(input, 0, 1), + win::hline2d(win.length()), + swap_output); + } } // end of namespace mln::level::impl Index: mln/value/stack.hh --- mln/value/stack.hh (revision 0) +++ mln/value/stack.hh (revision 0) @@ -0,0 +1,191 @@ +// 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_VALUE_STACK_HH +# define MLN_VALUE_STACK_HH + +/*! \file mln/value/stack.hh + * + * \brief Definition of an image class FIXME + */ + +# include <mln/core/internal/image_base.hh> +# include <mln/metal/vec.hh> +# include <mln/value/set.hh> + + +namespace mln +{ + + namespace value + { + + /*! \brief FIXME + * + */ + template <unsigned n, typename I> + struct stack_image : public mln::internal::image_base_< mln_pset(I), stack_image<n,I> > + { + /// Point_Site associated type. + typedef mln_psite(I) psite; + + /// Point_Set associated type. + typedef mln_pset(I) pset; + + /// Value associated type. + typedef metal::vec<n, mln_value(I)> value; + + /// Return type of read-only access. + typedef value rvalue; + + /// Return type of read-write access. + typedef void lvalue; // FIXME + + /// Value set associated type. + typedef mln::value::set<value> vset; + + + /// Constructor. + stack_image(const metal::vec<n,I*>& imas); + + + /// Test if this image has been initialized. + bool has_data() const; + + /// Test if a pixel value is accessible at \p p. + bool owns_(const psite& p) const; + + /// Give the definition domain. + const mln_pset(I)& domain() const; + + /// Read-only access of pixel value at point site \p p. + rvalue operator()(const psite& p) const; + + /// Read-write access of pixel value at point site \p p. + void operator()(const psite&); + + /// Give the set of values of the image. + const vset& values() const; + + /// Change value type. + template <typename U> + struct change_value + { + typedef metal::vec<n,U> vec_n_U; + typedef mln_ch_value(I, vec_n_U) ret; + }; + + protected: + metal::vec<n,I*> imas_; + }; + + + + template <typename I> + stack_image<2,const I> + stack(const Image<I>& ima1, const Image<I>& ima2) + { + mln_precondition(exact(ima1).domain() = exact(ima2).domain()); + metal::vec<2, const I*> imas; + imas[0] = & exact(ima1); + imas[1] = & exact(ima2); + stack_image<2, const I> tmp(imas); + return tmp; + } + + + +# ifndef MLN_INCLUDE_ONLY + + template <unsigned n, typename I> + stack_image<n,I>::stack_image(const metal::vec<n,I*>& imas) + : imas_(imas) + { + for (unsigned i = 0; i < n; ++i) + { + mln_precondition(imas[i] != 0); + mln_precondition(imas[i]->has_data()); + } + } + + template <unsigned n, typename I> + bool stack_image<n,I>::has_data() const + { + for (unsigned i = 0; i < n; ++i) + mln_invariant(imas_[i]->has_data()); + return true; + } + + template <unsigned n, typename I> + bool stack_image<n,I>::owns_(const psite& p) const + { + for (unsigned i = 0; i < n; ++i) + if (! imas_[i]->owns_(p)) + return false; + return true; + } + + template <unsigned n, typename I> + const mln_pset(I)& + stack_image<n,I>::domain() const + { + return imas_[0]->domain(); + } + + template <unsigned n, typename I> + metal::vec<n, mln_value(I)> + stack_image<n,I>::operator()(const psite& p) const + { + mln_precondition(this->owns_(p)); + metal::vec<n, mln_value(I)> tmp; + for (unsigned i = 0; i < n; ++i) + tmp[i] = imas_[i]->operator()(p); + return tmp; + } + + template <unsigned n, typename I> + void + stack_image<n,I>::operator()(const psite&) + { + mln_invariant(0); // FIXME: Turn into a compile-time error... + } + + template <unsigned n, typename I> + const mln::value::set< metal::vec<n, mln_value(I)> >& + stack_image<n,I>::values() const + { + return vset::the(); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::value + +} // end of namespace mln + + +#endif // ! MLN_VALUE_STACK_HH
participants (1)
-
Thierry Geraud