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