
https://svn.lrde.epita.fr/svn/oln/trunk/olena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Handle virtual borders. * oln/morpher/add_neighborhood.hh: Remove; obsolete. * oln/border/fill.hh: New. * oln/accumulator/min.hh (operator()): Untemplate. * oln/debug/print_nbh.hh: Use macros. * oln/debug/println.hh (println): Remove unuseful exact. * oln/core/concept/image.hh (Image_with_Border): New. * oln/core/concept/image_identity.hh (set_impl): New version. * oln/core/concept/accumulator.hh (init_with): New. * oln/core/1d/image1d_b.hh (vborder): New. (border): Rename as... (impl_border): ...this. * oln/core/2d/image2d_b.hh: Likewise. * oln/core/2d/array2d.hh (row_pad): New. * oln/core/equipment.hh (vborder): New. * oln/core/internal/image_selectors.hh (Image_border): New. * oln/morpho/elementary_erosion.hh (elementary_erosion_): Handle border. (elementary_erosion_): New version; fast, to be activated. (include): Add border/fill.hh. * oln/level/local.hh (init): Replace this call by... (init_with): ...this. accumulator/min.hh | 14 +--- border/fill.hh | 135 +++++++++++++++++++++++++++++++++++++++ core/1d/image1d_b.hh | 6 + core/2d/array2d.hh | 6 + core/2d/image2d_b.hh | 14 +++- core/concept/accumulator.hh | 11 +++ core/concept/image.hh | 26 +++++++ core/concept/image_identity.hh | 19 +++++ core/equipment.hh | 1 core/internal/image_selectors.hh | 13 +++ debug/print_nbh.hh | 11 ++- debug/println.hh | 2 level/local.hh | 2 morpho/elementary_erosion.hh | 48 +++++++++++++ 14 files changed, 287 insertions(+), 21 deletions(-) Index: oln/accumulator/min.hh --- oln/accumulator/min.hh (revision 890) +++ oln/accumulator/min.hh (working copy) @@ -47,10 +47,9 @@ min_(); void init() const; - result value() const; + const T& value() const; - template <typename U> - void operator()(U i) const; + void operator()(const T& val) const; private: mutable T val_; @@ -73,19 +72,18 @@ } template <typename T> - typename min_<T>::result + const T& min_<T>::value() const { return this->val_; } template <typename T> - template <typename U> void - min_<T>::operator()(U i) const + min_<T>::operator()(const T& val) const { - if (i < this->val_) - this->val_ = static_cast<T>(i); + if (val < this->val_) + this->val_ = val; } # endif // ! OLN_INCLUDE_ONLY Index: oln/debug/print_nbh.hh --- oln/debug/print_nbh.hh (revision 890) +++ oln/debug/print_nbh.hh (working copy) @@ -43,6 +43,8 @@ void print_nbh(const Image_with_Nbh<I>& input, std::ostream& ostr = std::cout); +# ifndef OLN_INCLUDE_ONLY + namespace impl { @@ -52,8 +54,8 @@ void print_nbh(const Image<I>&, const I& input, std::ostream& ostr) { - typename I::fwd_piter p(input.points()); - typename I::fwd_niter n(p, input.nbhood()); + oln_piter(I) p(input.points()); + oln_niter(I) n(p, input.nbhood()); for_all(p) { ostr << input(p) << ": "; @@ -71,8 +73,8 @@ void print_nbh(const Point_Wise_Accessible_Image<I>&, const I& input, std::ostream& ostr) { - typename I::fwd_piter p(input.points()); - typename I::fwd_niter n(p, input.nbhood()); + oln_piter(I) p(input.points()); + oln_niter(I) n(p, input.nbhood()); for_all(p) { ostr << input(p) << ": "; @@ -93,6 +95,7 @@ impl::print_nbh(exact(input), exact(input), ostr); } +# endif // ! OLN_INCLUDE_ONLY } // end of namespace oln::debug Index: oln/debug/println.hh --- oln/debug/println.hh (revision 890) +++ oln/debug/println.hh (working copy) @@ -46,7 +46,7 @@ template <typename I> void println(const Image<I>& input, std::ostream& ostr) { - print(exact(input), ostr); + debug::print(input, ostr); ostr << std::endl; } Index: oln/core/concept/image.hh --- oln/core/concept/image.hh (revision 890) +++ oln/core/concept/image.hh (working copy) @@ -163,6 +163,18 @@ }; + /// Concept-class "Image_with_Border". + + template <typename Exact> + struct Image_with_Border : public virtual Image<Exact>, + public automatic::get_impl<Image_with_Border, Exact> + { + unsigned border() const; + protected: + Image_with_Border(); + }; + + /// Concept-class "Mutable_Image". template <typename Exact> @@ -394,6 +406,20 @@ { } + // ----------------------------------- Image_with_Border<Exact> + + template <typename Exact> + unsigned + Image_with_Border<Exact>::border() const + { + return exact(this)->impl_border(); + } + + template <typename Exact> + Image_with_Border<Exact>::Image_with_Border() + { + } + // ----------------------------------- Mutable_Image<Exact> template <typename Exact> Index: oln/core/concept/image_identity.hh --- oln/core/concept/image_identity.hh (revision 890) +++ oln/core/concept/image_identity.hh (working copy) @@ -68,6 +68,15 @@ }; + /// Concept-class "Image_with_Border". + + template <typename Exact> + struct set_impl< Image_with_Border, behavior::identity, Exact > : public virtual Any<Exact> + { + unsigned impl_border() const; + }; + + /// Concept-class "Mutable_Image". template <typename Exact> @@ -209,6 +218,16 @@ } + /// Concept-class "Image_with_Border". + + template <typename Exact> + unsigned + set_impl< Image_with_Border, behavior::identity, Exact >::impl_border() const + { + return exact(this)->image().border(); + } + + /// Concept-class "Mutable_Image". template <typename Exact> Index: oln/core/concept/accumulator.hh --- oln/core/concept/accumulator.hh (revision 890) +++ oln/core/concept/accumulator.hh (working copy) @@ -39,6 +39,8 @@ template <typename Exact> struct Accumulator : public Function<Exact> { + template <typename T> + void init_with(const T& val) const; protected: Accumulator(); }; @@ -52,6 +54,15 @@ { } + template <typename Exact> + template <typename T> + void + Accumulator<Exact>::init_with(const T& val) const + { + exact(this)->init(); + exact(this)->operator()(val); + } + # endif // ! OLN_INCLUDE_ONLY } // end of namespace oln Index: oln/core/1d/image1d_b.hh --- oln/core/1d/image1d_b.hh (revision 890) +++ oln/core/1d/image1d_b.hh (working copy) @@ -64,6 +64,8 @@ unsigned, box_<point1d> > data; + typedef mlc::true_ vborder; + typedef image1d_b<T> plain; typedef image1d_b<pl::value> skeleton; }; @@ -107,7 +109,7 @@ box1d impl_points() const; - unsigned border() const; + unsigned impl_border() const; }; @@ -190,7 +192,7 @@ } template <typename T> - unsigned image1d_b<T>::border() const + unsigned image1d_b<T>::impl_border() const { assert(this->has_data()); return this->data_->second; Index: oln/core/2d/array2d.hh --- oln/core/2d/array2d.hh (revision 890) +++ oln/core/2d/array2d.hh (working copy) @@ -71,6 +71,12 @@ const T* buffer() const; T* buffer(); + std::size_t row_pad() const + { + precondition(buffer_ != 0 and array_ != 0); + return &(array_[imin_+1][jmin_]) - &(array_[imin_][jmin_]); + } + protected: C imin_, jmin_, imax_, jmax_; Index: oln/core/2d/image2d_b.hh --- oln/core/2d/image2d_b.hh (revision 890) +++ oln/core/2d/image2d_b.hh (working copy) @@ -101,6 +101,8 @@ typedef box2d pset; typedef internal::array_b_<point2d, T> data; + typedef mlc::true_ vborder; + typedef image2d_b<T> plain; typedef image2d_b<pl::value> skeleton; @@ -148,7 +150,8 @@ box2d impl_points() const; - unsigned border() const; + unsigned impl_border() const; + std::size_t pad(const dpoint2d& dp) const; }; // template <typename T, typename D> @@ -250,12 +253,19 @@ } template <typename T> - unsigned image2d_b<T>::border() const + unsigned image2d_b<T>::impl_border() const { assert(this->has_data()); return this->data_->border; } + template <typename T> + std::size_t image2d_b<T>::pad(const dpoint2d& dp) const + { + assert(this->has_data()); + return this->data_->array.row_pad() * dp.row() + dp.col(); + } + // template <typename T, typename D> // bool init_(image2d_b<T>* this_, const D& dat) // { Index: oln/core/equipment.hh --- oln/core/equipment.hh (revision 890) +++ oln/core/equipment.hh (working copy) @@ -143,6 +143,7 @@ // v stc_decl_associated_type( value ); + stc_decl_associated_type( vborder ); stc_decl_associated_type( vsite ); # define oln_value(T) oln_typename_shortcut__(T, value) Index: oln/core/internal/image_selectors.hh --- oln/core/internal/image_selectors.hh (revision 890) +++ oln/core/internal/image_selectors.hh (working copy) @@ -123,6 +123,19 @@ }; + // 5. border + + typedef selector<Image, 5> Image_border; + + template <typename Exact> + struct case_< Image_border, Exact, 1 > + : + where_< stc_type_is_found(vborder) > + { + typedef Image_with_Border<Exact> ret; + }; + + } // end of namespace oln::internal Index: oln/morpho/elementary_erosion.hh --- oln/morpho/elementary_erosion.hh (revision 890) +++ oln/morpho/elementary_erosion.hh (working copy) @@ -29,6 +29,7 @@ # define OLN_MORPHO_ELEMENTARY_EROSION_HH #include <oln/level/apply_local.hh> +#include <oln/border/fill.hh> #include <oln/accumulator/min.hh> @@ -50,16 +51,57 @@ namespace impl { - /// Generic version + // Generic version. template <typename I> oln_plain(I) - elementary_erosion_(const Image_with_Nbh<I>& input) + elementary_erosion_(const Image<I>&, + const I& input) { + border::fill(input, oln_max(oln_value(I))); accumulator::min_<oln_value(I)> min; return level::apply_local(min, input); } + + + // Fast version. + +// template <typename I> +// oln_plain(I) +// elementary_erosion_(const /*Fast_*/Image<I>&, +// const I& input) +// { +// std::cout << "fast" << std::endl; + +// typedef oln_value(I) T; +// border::fill(input, oln_max(T)); +// accumulator::min_<T> min; + +// oln_plain(I) output; +// prepare(output, with, input); + +// unsigned n = input.nbhood().size(); +// T* jump = new T[n]; +// for (unsigned i = 0; i < n; ++i) +// jump[i] = input.image().pad(input.nbhood()[i]); // FIXME: pad is in Fast... + +// oln_piter(I) p(input.points()); +// for_all(p) +// { +// const T* ptr = & input(p); +// min.init_with(*ptr); +// for (unsigned i = 0; i < n; ++i) +// min(*(ptr + jump[i])); +// output(p) = min.value(); +// } +// delete[] jump; +// return output; +// } + + + + } // end of namespace oln::morpho::impl @@ -69,7 +111,7 @@ oln_plain(I) elementary_erosion(const Image_with_Nbh<I>& input) { - return impl::elementary_erosion_(exact(input)); + return impl::elementary_erosion_(exact(input), exact(input)); } # endif // ! OLN_INCLUDE_ONLY Index: oln/level/local.hh --- oln/level/local.hh (revision 890) +++ oln/level/local.hh (working copy) @@ -66,7 +66,7 @@ const Image_with_Nbh<I>& input, const oln_point(I)& p) { - f.init(); + f.init_with(input(p)); oln_niter(I) n(p, input.nbhood()); // FIXME: 2nd arg should be 'input'! for_all(n) f(input(n)); Index: oln/border/fill.hh --- oln/border/fill.hh (revision 0) +++ oln/border/fill.hh (revision 0) @@ -0,0 +1,135 @@ +// 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 OLN_BORDER_FILL_HH +# define OLN_BORDER_FILL_HH + +# include <oln/core/concept/image.hh> + + +namespace oln +{ + + namespace border + { + + // Fwd decl. + + template <typename I> + void fill(const Image<I>& input, const oln_value(I)& value); + + +# ifndef OLN_INCLUDE_ONLY + + namespace impl + { + +# ifdef OLN_ENV_2D + + template <typename I> + void fill_2D_(I& input, const oln_value(I)& value) + { + oln_point(I) + pmin(input.min_row() - input.border(), + input.min_col() - input.border()), + pmax(input.max_row() + input.border(), + input.max_col() + input.border()); + if (not input.owns_(pmin) or not input.owns_(pmax)) + return; + oln_coord(I) row, col; + for (col = pmin.col(); col <= pmax.col(); ++col) + { + // top + for (row = input.min_row() - input.border(); + row <= input.min_row() - 1; + ++row) + input.at(row, col) = value; + // bot + for (row = input.max_row() + 1; + row <= input.max_row() + int(input.border()); + ++row) + input.at(row, col) = value; + } + for (row = input.min_row(); + row <= input.max_row(); + ++row) + { + // left + for (col = input.min_col() - input.border(); + col <= input.min_col() - 1; + ++col) + input.at(row, col) = value; + // right + for (col = input.max_col() + 1; + col <= input.max_col() + int(input.border()); + ++col) + input.at(row, col) = value; + } + } + + template <typename I> + void fill_nD_(Image_2D<I>& input, const oln_value(I)& value) + { + fill_2D_(exact(input), value); + } + +# endif // OLN_ENV_2D + + + template <typename I> + void fill_(const Image_with_Border<I>& input, const oln_value(I)& value) + { + // FIXME: Requires also Point_Wise_Accessible_Image, Mutable_Image... + I& input_ = const_cast<I&>(exact(input)); + fill_nD_(input_, value); + } + + template <typename I> + void fill_(const Image<I>&, const oln_value(I)&) + { + // no-op + } + + } // end of namespace oln::border::impl + + + // Facade. + + template <typename I> + void fill(const Image<I>& input, const oln_value(I)& value) + { + impl::fill_(exact(input), value); + } + +# endif // ! OLN_INCLUDE_ONLY + + } // end of namespace oln::border + +} // end of namespace oln + + +#endif // ! OLN_BORDER_FILL_HH