
2005-04-14 Thierry GERAUD <theo@tegucigalpa.lrde.epita.fr> * oln/core/typedefs.hh (oln_super_of): New macro. * oln/core/abstract/image_operator.hh (set_props): Declare output_type. * oln/core/1d/qiter1d.hh: Remove typedefs. * oln/core/2d/qiter2d.hh: Likewise. * oln/core/3d/qiter3d.hh: Likewise. * oln/core/1d/window1d.hh: Use inheritance. * oln/core/2d/window2d.hh: Likewise. (win_rectangle2d): New class. * oln/core/3d/window3d.hh: Likewise. * oln/core/any/dpoint.hh (operator+): Move to... * oln/core/any/point.hh: ...here. * oln/core/gen/regular_fwd_qiter.hh: Add parameter W. * oln/core/gen/regular_bkd_qiter.hh: Likewise. * oln/core/gen/regular_qiter.hh: Update. * oln/core/gen/regular_window.hh: Update. * oln/core/gen/regular_neighborhood.hh: Update. * oln/morpho/stat.hh (stat_): Remove. * oln/morpho/erosion.hh: Rewrite. Index: oln/core/typedefs.hh =================================================================== --- oln/core/typedefs.hh (revision 153) +++ oln/core/typedefs.hh (working copy) @@ -38,8 +38,14 @@ # include <mlc/to_string.hh> +# define oln_super_of_(Type) \ +oln::internal::get_super_type<Type>::ret +# define oln_super_of(Type) \ +typename oln_super_of_(Type) + + namespace oln { Index: oln/core/abstract/image.hh =================================================================== --- oln/core/abstract/image.hh (revision 153) +++ oln/core/abstract/image.hh (working copy) @@ -39,6 +39,7 @@ + namespace oln { Index: oln/core/abstract/image_operator.hh =================================================================== --- oln/core/abstract/image_operator.hh (revision 153) +++ oln/core/abstract/image_operator.hh (working copy) @@ -48,8 +48,18 @@ template <typename O, typename I1, typename I2, typename E> struct set_super_type< abstract::image_binary_operator<O, I1, I2, E> > { typedef abstract::image_operator<O, E> ret; }; + // props + template <typename O, typename E> + struct set_props < category::image, abstract::image_operator<O, E> > + { + typedef O output_type; + }; + + + + namespace abstract { Index: oln/core/1d/qiter1d.hh =================================================================== --- oln/core/1d/qiter1d.hh (revision 153) +++ oln/core/1d/qiter1d.hh (working copy) @@ -31,18 +31,11 @@ # include <oln/core/1d/grid1d.hh> # include <oln/core/1d/point1d.hh> # include <oln/core/1d/dpoint1d.hh> + # include <oln/core/1d/window1d.hh> # include <oln/core/gen/regular_fwd_qiter.hh> # include <oln/core/gen/regular_bkd_qiter.hh> -namespace oln { - - typedef regular_fwd_qiter<grid1d> fwd_qiter1d; - typedef regular_bkd_qiter<grid1d> bkd_qiter1d; - -} - - #endif // ! OLENA_CORE_1D_QITER1D_HH Index: oln/core/1d/window1d.hh =================================================================== --- oln/core/1d/window1d.hh (revision 153) +++ oln/core/1d/window1d.hh (working copy) @@ -36,8 +36,37 @@ namespace oln { - typedef regular_window< grid1d > window1d; + // fwd decl + struct window1d; + + // super type + template <> + struct set_super_type< window1d > { typedef abstract::regular_window< grid1d, window1d > ret; }; + + + struct window1d : public abstract::regular_window< grid1d, window1d > + { + typedef abstract::regular_window< grid1d, window1d > super_type; + + window1d() + {} + + window1d(unsigned n, const coord_t crd[]) : + super_type(n, crd) + {} + + window1d& add(const dpoint1d& dp) + { + this->add_(dp); + return *this; + } + + }; + + + + // classical 1d windows /*! Index: oln/core/2d/qiter2d.hh =================================================================== --- oln/core/2d/qiter2d.hh (revision 153) +++ oln/core/2d/qiter2d.hh (working copy) @@ -31,18 +31,11 @@ # include <oln/core/2d/grid2d.hh> # include <oln/core/2d/point2d.hh> # include <oln/core/2d/dpoint2d.hh> + # include <oln/core/2d/window2d.hh> # include <oln/core/gen/regular_fwd_qiter.hh> # include <oln/core/gen/regular_bkd_qiter.hh> -namespace oln { - - typedef regular_fwd_qiter<grid2d> fwd_qiter2d; - typedef regular_bkd_qiter<grid2d> bkd_qiter2d; - -} - - #endif // ! OLENA_CORE_2D_QITER2D_HH Index: oln/core/2d/window2d.hh =================================================================== --- oln/core/2d/window2d.hh (revision 153) +++ oln/core/2d/window2d.hh (working copy) @@ -37,8 +37,70 @@ namespace oln { - typedef regular_window< grid2d > window2d; + // fwd decl + struct window2d; + // super type + template <> + struct set_super_type< window2d > { typedef abstract::regular_window< grid2d, window2d > ret; }; + + + struct window2d : public oln_super_of_(window2d) + { + typedef oln_super_of_(window2d) super_type; + + window2d() + {} + + window2d(unsigned n, const coord_t crd[]) : + super_type(n, crd) + {} + + window2d& add(const dpoint2d& dp) + { + this->add_(dp); + return *this; + } + + }; + + + // fwd decl + struct win_rectangle2d; + + // super type + template <> + struct set_super_type< win_rectangle2d > { typedef abstract::regular_window< grid2d, win_rectangle2d > ret; }; + + + /// Class win_rectangle2d. + struct win_rectangle2d : public oln_super_of_(win_rectangle2d) + { + typedef oln_super_of_(win_rectangle2d) super_type; + + win_rectangle2d(unsigned height, unsigned width) : + height(height), + width(width) + { + int + min_drow = (1 - int(height)) / 2, + max_drow = int(height) / 2, + min_dcol = (1 - int(width)) / 2, + max_dcol = int(width) / 2; + for (int drow = min_drow; drow <= max_drow; ++drow) + for (int dcol = min_dcol; dcol <= max_dcol; ++dcol) + { + dpoint2d dp(drow, dcol); + this->add_(dp); + } + } + + const unsigned height; + const unsigned width; + }; + + + // classical 2d windows /*! Index: oln/core/3d/qiter3d.hh =================================================================== --- oln/core/3d/qiter3d.hh (revision 153) +++ oln/core/3d/qiter3d.hh (working copy) @@ -31,18 +31,11 @@ # include <oln/core/3d/grid3d.hh> # include <oln/core/3d/point3d.hh> # include <oln/core/3d/dpoint3d.hh> + # include <oln/core/3d/window3d.hh> # include <oln/core/gen/regular_fwd_qiter.hh> # include <oln/core/gen/regular_bkd_qiter.hh> -namespace oln { - - typedef regular_fwd_qiter<grid3d> fwd_qiter3d; - typedef regular_bkd_qiter<grid3d> bkd_qiter3d; - -} - - #endif // ! OLENA_CORE_3D_QITER3D_HH Index: oln/core/3d/window3d.hh =================================================================== --- oln/core/3d/window3d.hh (revision 153) +++ oln/core/3d/window3d.hh (working copy) @@ -36,8 +36,37 @@ namespace oln { - typedef regular_window< grid3d > window3d; + // fwd decl + struct window3d; + + // super type + template <> + struct set_super_type< window3d > { typedef abstract::regular_window< grid3d, window3d > ret; }; + + + struct window3d : public abstract::regular_window< grid3d, window3d > + { + typedef abstract::regular_window< grid3d, window3d > super_type; + + window3d() + {} + + window3d(unsigned n, const coord_t crd[]) : + super_type(n, crd) + {} + + window3d& add(const dpoint3d& dp) + { + this->add_(dp); + return *this; + } + + }; + + + + // classical 3d windows /*! Index: oln/core/any/point.hh =================================================================== --- oln/core/any/point.hh (revision 153) +++ oln/core/any/point.hh (working copy) @@ -127,8 +127,15 @@ # include <oln/core/any/dpoint.hh> + namespace oln { + template <typename P> + const any_point any_dpoint::operator+(const abstract::point<P>& rhs) const + { + return any_point(); + } + const any_dpoint any_point::impl_minus(const any_point& rhs) const { precondition(false); Index: oln/core/any/dpoint.hh =================================================================== --- oln/core/any/dpoint.hh (revision 153) +++ oln/core/any/dpoint.hh (working copy) @@ -31,7 +31,6 @@ # include <iostream> # include <mlc/contract.hh> # include <oln/core/abstract/dpoint.hh> -# include <oln/core/any/point.hh> namespace oln { @@ -124,14 +123,5 @@ # include <oln/core/any/point.hh> -namespace oln { - template <typename P> - const any_point any_dpoint::operator+(const abstract::point<P>& rhs) const - { - return any_point(); - } - -} - #endif // ! OLENA_CORE_ANY_DPOINT_HH Index: oln/core/gen/regular_fwd_qiter.hh =================================================================== --- oln/core/gen/regular_fwd_qiter.hh (revision 153) +++ oln/core/gen/regular_fwd_qiter.hh (working copy) @@ -34,20 +34,27 @@ namespace oln { // fwd decl - template <typename G> struct regular_fwd_qiter; + template <typename G, typename W> struct regular_fwd_qiter; // category - template <typename G> - struct set_super_type< regular_fwd_qiter<G> > { typedef abstract::regular_qiter< G, regular_fwd_qiter<G> > ret; }; + template <typename G, typename W> + struct set_super_type< regular_fwd_qiter<G,W> > { typedef abstract::regular_qiter< G, regular_fwd_qiter<G,W> > ret; }; + // props + template <typename G, typename W> + struct set_props < category::qiter, regular_fwd_qiter<G,W> > + { + typedef W window_type; + }; - template <typename G> - struct regular_fwd_qiter : public abstract::regular_qiter< G, regular_fwd_qiter<G> > + + template <typename G, typename W> + struct regular_fwd_qiter : public abstract::regular_qiter< G, regular_fwd_qiter<G,W> > { - typedef regular_fwd_qiter<G> self_type; + typedef regular_fwd_qiter<G,W> self_type; typedef abstract::regular_qiter<G, self_type> super_type; - regular_fwd_qiter(const regular_window<G>& win) : + regular_fwd_qiter(const abstract::regular_window<G,W>& win) : super_type(win) { this->invalidate(); Index: oln/core/gen/regular_bkd_qiter.hh =================================================================== --- oln/core/gen/regular_bkd_qiter.hh (revision 153) +++ oln/core/gen/regular_bkd_qiter.hh (working copy) @@ -34,21 +34,27 @@ namespace oln { // bkd decl - template <typename G> - struct regular_bkd_qiter; + template <typename G, typename W> struct regular_bkd_qiter; // category - template <typename G> - struct set_super_type< regular_bkd_qiter<G> > { typedef abstract::regular_qiter< G, regular_bkd_qiter<G> > ret; }; + template <typename G, typename W> + struct set_super_type< regular_bkd_qiter<G,W> > { typedef abstract::regular_qiter< G, regular_bkd_qiter<G,W> > ret; }; + // props + template <typename G, typename W> + struct set_props < category::qiter, regular_bkd_qiter<G,W> > + { + typedef W window_type; + }; - template <typename G> - struct regular_bkd_qiter : public abstract::regular_qiter< G, regular_bkd_qiter<G> > + + template <typename G, typename W> + struct regular_bkd_qiter : public abstract::regular_qiter< G, regular_bkd_qiter<G,W> > { - typedef regular_bkd_qiter<G> self_type; + typedef regular_bkd_qiter<G,W> self_type; typedef abstract::regular_qiter<G, self_type> super_type; - regular_bkd_qiter(const regular_window<G>& win) : + regular_bkd_qiter(const abstract::regular_window<G,W>& win) : super_type(win) { this->invalidate(); Index: oln/core/gen/regular_qiter.hh =================================================================== --- oln/core/gen/regular_qiter.hh (revision 153) +++ oln/core/gen/regular_qiter.hh (working copy) @@ -48,8 +48,7 @@ template <typename G, typename E> struct set_props < category::qiter, abstract::regular_qiter<G,E> > { - typedef G grid_type; - typedef regular_window<G> window_type; + typedef G grid_type; }; @@ -68,8 +67,8 @@ typedef oln_grd_type_of(G, dimvalue) dimvalue_type; static const unsigned dim = dimvalue_type::val; - regular_qiter(const regular_window<G>& win) : - super_type(win) + regular_qiter(const regular_window<G, oln_qit_type_of(E, window)>& win) : + super_type(win.exact()) { } Index: oln/core/gen/regular_window.hh =================================================================== --- oln/core/gen/regular_window.hh (revision 153) +++ oln/core/gen/regular_window.hh (working copy) @@ -43,124 +43,133 @@ namespace oln { // fwd decls - template <typename G> class regular_window; - template <typename G> class regular_fwd_qiter; + template <typename G, typename W> class regular_fwd_qiter; + namespace abstract { + template <typename G, typename E> class regular_window; + } // super_type - template <typename G> struct set_super_type< regular_window<G> > { typedef abstract::window< regular_window<G> > ret; }; + template <typename G, typename E> struct set_super_type< abstract::regular_window<G, E> > { typedef abstract::window<E> ret; }; // props - template <typename G> - struct set_props< category::window, regular_window<G> > + template <typename G, typename E> + struct set_props< category::window, abstract::regular_window<G, E> > { typedef G grid_type; typedef oln_grd_type_of(G, dpoint) dpoint_type; typedef oln_grd_type_of(G, size) size_type; - typedef regular_fwd_qiter<G> fwd_iter_type; -// typedef regular_fwd_dpiter<G> fwd_dpiter_type; // FIXME: later... + typedef regular_fwd_qiter<G,E> fwd_iter_type; + // typedef regular_fwd_dpiter<G> fwd_dpiter_type; // FIXME: later... }; - template <typename G> - class regular_window : public abstract::window< regular_window<G> > + + + namespace abstract { - public: + template <typename G, typename E> + class regular_window : public window<E> + { + + public: - typedef regular_window<G> self_type; + typedef regular_window<G, E> self_type; - typedef oln_grd_type_of(G, coord) coord_type; - typedef oln_grd_type_of(G, dpoint) dpoint_type; - typedef oln_grd_type_of(G, dimvalue) dimvalue_type; + typedef oln_grd_type_of(G, coord) coord_type; + typedef oln_grd_type_of(G, dpoint) dpoint_type; + typedef oln_grd_type_of(G, dimvalue) dimvalue_type; - static const unsigned dim = dimvalue_type::val; + static const unsigned dim = dimvalue_type::val; - regular_window() : - dp_(), - delta_(0) - { - } + coord_type delta() const + { + return this->delta_; + } - regular_window(unsigned n, const coord_type crd[]) : - dp_(), - delta_(0) - { - precondition(n != 0); - // FIXME: size of crd wrt n - for (unsigned i = 0; i < n; ++i) - { - dpoint_type dp; - for (unsigned c = 0; c < dim; ++c) - dp.nth(c) = crd[i * dim + c]; - this->add(dp); - } - } + unsigned card() const + { + return this->dp_.size(); + } - self_type& add(const dpoint_type& dp) - { - this->dpset_.insert(dp); - this->dp_.clear(); - std::copy(this->dpset_.begin(), this->dpset_.end(), - std::back_inserter(this->dp_)); - this->delta_update_(dp); - return *this; - } + const dpoint_type dp(unsigned i) const + { + precondition(i < this->card()); + return this->dp_[i]; + } - coord_type delta() const - { - return this->delta_; - } + const self_type operator-() const + { + self_type tmp; + for (unsigned i = 0; i < this->card(); ++i) + tmp.add_(- this->dp_[i]); + return tmp; + } - unsigned card() const - { - return this->dp_.size(); - } + void sym() + { + *this = - *this; + } - const dpoint_type dp(unsigned i) const - { - precondition(i < this->card()); - return this->dp_[i]; - } + const std::vector<dpoint_type>& get_dp() const + { + return this->dp_; + } - const self_type operator-() const - { - self_type tmp; - for (unsigned i = 0; i < this->card(); ++i) - tmp.add(- this->dp_[i]); - return tmp; - } + protected: - void sym() - { - *this = - *this; - } + regular_window() : + dp_(), + delta_(0) + { + } - const std::vector<dpoint_type>& get_dp() const - { - return this->dp_; - } + regular_window(unsigned n, const coord_type crd[]) : + dp_(), + delta_(0) + { + precondition(n != 0); + // FIXME: size of crd wrt n + for (unsigned i = 0; i < n; ++i) + { + dpoint_type dp; + for (unsigned c = 0; c < dim; ++c) + dp.nth(c) = crd[i * dim + c]; + this->add_(dp); + } + } - private: + void add_(const dpoint_type& dp) + { + this->dpset_.insert(dp); + this->dp_.clear(); + std::copy(this->dpset_.begin(), this->dpset_.end(), + std::back_inserter(this->dp_)); + this->delta_update_(dp); + } + + private: - std::set<dpoint_type, fwd_less_dpoint> dpset_; - std::vector<dpoint_type> dp_; - coord_type delta_; + std::set<dpoint_type, fwd_less_dpoint> dpset_; + std::vector<dpoint_type> dp_; + coord_type delta_; - void delta_update_(const dpoint_type& dp) - { - for (unsigned c = 0; c < dim; ++c) - if (abs(dp.nth(c)) > this->delta_) - this->delta_ = abs(dp.nth(c)); - } + void delta_update_(const dpoint_type& dp) + { + for (unsigned c = 0; c < dim; ++c) + if (abs(dp.nth(c)) > this->delta_) + this->delta_ = abs(dp.nth(c)); + } - }; + }; + } // end of namespace oln::abstract } // end of namespace oln -template<class G> -std::ostream& operator<<(std::ostream& ostr, const oln::regular_window<G>& win) +template<typename G, typename E> +std::ostream& operator<<(std::ostream& ostr, const oln::abstract::regular_window<G, E>& win) { ostr << "["; for (unsigned i = 0; i < win.card(); ++i) Index: oln/core/gen/regular_neighborhood.hh =================================================================== --- oln/core/gen/regular_neighborhood.hh (revision 153) +++ oln/core/gen/regular_neighborhood.hh (working copy) @@ -40,13 +40,27 @@ // super_type template <typename G> struct set_super_type< regular_neighborhood<G> > { typedef abstract::neighborhood< regular_neighborhood<G> > ret; }; + + // FIXME: temporary code to get a window type from a grid type + struct grid1d; struct window1d; + struct grid2d; struct window2d; + struct grid3d; struct window3d; + namespace internal { + template <typename grid_type> struct to_window; + template <> struct to_window <grid1d> { typedef window1d ret; }; + template <> struct to_window <grid2d> { typedef window2d ret; }; + template <> struct to_window <grid3d> { typedef window3d ret; }; + } + // FIXME: end of temporary code + + // props template <typename G> struct set_props< category::neighborhood, regular_neighborhood<G> > { typedef oln_grd_type_of(G, dpoint) dpoint_type; typedef oln_grd_type_of(G, size) size_type; - typedef regular_window<G> window_type; + typedef typename internal::to_window<G>::ret window_type; }; @@ -58,6 +72,7 @@ public: typedef regular_neighborhood<G> self_type; + typedef oln_nbh_type_of(self_type, window) window_type; typedef oln_grd_type_of(G, coord) coord_type; typedef oln_grd_type_of(G, dpoint) dpoint_type; @@ -69,7 +84,7 @@ { } - regular_neighborhood(const regular_window<G>& win) + regular_neighborhood(const window_type& win) { for (unsigned i = 0; i < win.card(); ++i) this->add(win.dp(i)); @@ -117,7 +132,7 @@ return this->win_.get_dp(); } - const regular_neighborhood<G>& get_win() const + const window_type& get_win() const { return this->win_; } @@ -125,7 +140,7 @@ private: /// Only attribute (to delegate to). - regular_window<G> win_; + window_type win_; }; Index: oln/morpho/stat.hh =================================================================== --- oln/morpho/stat.hh (revision 153) +++ oln/morpho/stat.hh (working copy) @@ -30,7 +30,7 @@ # include <mlc/cmp.hh> # include <ntg/bin.hh> -# include <oln/core/abstract/image.hh> +# include <oln/core/abstract/images.hh> # include <oln/core/abstract/window.hh> @@ -38,160 +38,87 @@ namespace morpho { - namespace internal { - /*! - ** \brief Min and Max on a window. - ** - ** We need to use this inner definition in order to specialize - ** max and min on binary images. - ** - ** \param I Image exact type. - ** \param W Window type. - ** \param V Associated value type. - */ - template <class I, class W, class V = oln_type_of(I, value)> - struct stat_ - { - /*! - ** \brief Maximum of a window. - ** - ** Look for the maximum in the window win disposed - ** on the image input, at the point p. - ** - ** \arg input Input image. - ** \arg p Point of the image to move the window on. - ** \arg win The window to use. - */ - static V - max(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - const abstract::window<W>& win) - { - mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); + /// Local min on a function. - oln_wn_type_of(W, fwd_iter) q(win); - q.start_at_p(p); - V val = input[q]; - for_all_remaining_q (q) - if (input.hold(q)) - if (val < input[q].value()) - val = input[q].value(); - return val; - } + template <typename I, typename W> + oln_type_of(I, value) min(const abstract::image<I>& input, + const oln_type_of(I, point)& p, + const abstract::window<W>& win) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); - /*! - ** \brief Minimum of a window. - ** - ** Look for the minimum in the window win disposed - ** on the image input, at the point p. - ** - ** \arg input Input image. - ** \arg p Point of the image to move the window on. - ** \arg win The window to use. - */ - static V - min(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - const abstract::window<W>& win) - { - mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); + oln_wn_type_of(W, fwd_iter) q(win); + oln_type_of(I, value) val; - oln_wn_type_of(W, fwd_iter) q(win); - q.start_at(p); - V val = input[q]; - for_all_remaining_q (q) - if (input.hold(q)) - if (val > input[q].value()) - val = input[q].value(); - return val; - } + q.start_at_p(p); + val = input[q]; + + for_all_remaining_q (q) + if (input.hold(q) and input[q].value() < val) + val = input[q].value(); - }; + return val; + } - /* Binary specialization. */ - template <class I, class W> - struct stat_<I, W, ntg::bin> - { - static ntg::bin - max(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - const abstract::window<W>& win) - { - mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); - oln_wn_type_of(W, fwd_iter) q(win); - for_all_q_of_p (q, p) - if (input.hold(q)) - if (input[q] == true) - return true; - return false; - } + /// Local min on a set. - static ntg::bin - min(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - const abstract::window<W>& win) - { - mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); - oln_wn_type_of(W, fwd_iter) q(win); - for_all_q_of_p (q, p) - if (input.hold(q)) - if (input[q] == false) - return false; - return true; - } + template <typename I, typename W> + bool min(const abstract::binary_image<I>& input, + const oln_type_of(I, point)& p, + const abstract::window<W>& win) + { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); - }; + oln_wn_type_of(W, fwd_iter) q(win); + for_all_q_of_p (q, p) + if (input.hold(q) and not input[q]) + return false; + return true; + } - } // internal - /*! - ** \brief Maximum of a window. - ** - ** Look for the maximum in the window win disposed - ** on the image input, at the point p. - ** - ** \param I Image exact type. - ** \param W Window type. - ** - ** \arg input Input image. - ** \arg p Point of the image to move the window on. - ** \arg win The window to use. - */ - template<class I, class W> - oln_type_of(I, value) - max(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - const abstract::window<W>& win) + /// Local max on a function. + + template <typename I, typename W> + oln_type_of(I, value) max(const abstract::image<I>& input, + const oln_type_of(I, point)& p, + const abstract::window<W>& win) { - // FIXME: test dim I == dim W - return internal::stat_<I, W>::max(input.exact(), p, win.exact()); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); + + oln_wn_type_of(W, fwd_iter) q(win); + oln_type_of(I, value) val; + + q.start_at_p(p); + val = input[q]; + + for_all_remaining_q (q) + if (input.hold(q) and input[q].value() > val) + val = input[q].value(); + + return val; } - /*! ** \brief Minimum of a window. - ** - ** Look for the minimum in the window win disposed - ** on the image input, at the point p. - ** - ** \param I Image exact type. - ** \param W Window type. - ** - ** \arg input Input image. - ** \arg p Point of the image to move the window on. - ** \arg win The window to use. - */ - template<class I, class W> - oln_type_of(I, value) - min(const abstract::image<I>& input, - const oln_type_of(I, point)& p, - // const mlc_exact_type(I)::iter_type& p, - const abstract::window<W>& win) + + /// Local max on a set. + + template <typename I, typename W> + bool max(const abstract::binary_image<I>& input, + const oln_type_of(I, point)& p, + const abstract::window<W>& win) { - // FIXME: test dim I == dim W - return internal::stat_<I, W>::min(input.exact(), p, win.exact()); + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); + + oln_wn_type_of(W, fwd_iter) q(win); + for_all_q_of_p (q, p) + if (input.hold(q) and input[q]) + return true; + return false; } + } // end of namespace morpho } // end of namespace oln Index: oln/morpho/erosion.hh =================================================================== --- oln/morpho/erosion.hh (revision 153) +++ oln/morpho/erosion.hh (working copy) @@ -30,23 +30,50 @@ # include <mlc/cmp.hh> +# include <oln/core/abstract/images.hh> # include <oln/core/abstract/image_operator.hh> # include <oln/morpho/stat.hh> +# include <oln/core/2d/window2d.hh> + namespace oln { + + // fwd decl + namespace morpho { + template <typename I> struct erosion_ret; + } + // super_type + template <typename I> + struct set_super_type< morpho::erosion_ret<I> > + { + typedef oln_type_of(I, concrete) output_type; + + typedef morpho::erosion_ret<I> self_type; + typedef abstract::image_unary_operator<output_type, I, self_type > ret; + }; + + + + + namespace morpho { + + + + // Erosion as a 'classical' procedure returning an image (do not + // use it; prefer morpho::erosion). + namespace proc { - /// Erosion as a procedure (do not use it; prefer morpho::erosion). - template<typename I, typename W> oln_type_of(I, concrete) erosion(const abstract::image<I>& input, const abstract::window<W>& win) { + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); oln_type_of(I, concrete) output(input.size()); oln_type_of(I, fwd_piter) p(input.size()); for_all_p (p) @@ -58,136 +85,127 @@ - /*! - ** \brief Perform a morphological erosion. - ** - ** Compute the morphological erosion of input using win - ** as structuring element. - ** - ** On grey-scale images, each point is replaced by the minimum - ** value of its neighbors, as indicated by win. On binary - ** images, a logical and is performed between neighbors. The - ** morpho::fast version of this function use a different - ** algorithm: an histogram of the value of the neighborhood - ** indicated by win is updated while iterating over all point of - ** the image. Doing so is more efficient when the structuring - ** element is large. - ** - ** \param I Exact type of the input image. - ** \param W Exact type of the structuring element. - ** - ** - ** \arg input Input image. - ** \arg win Structuring element to use. - ** - ** \code - ** #include <oln/basics2d.hh> - ** #include <oln/morpho/erosion.hh> - ** #include <oln/level/compare.hh> - ** #include <ntg/all.hh> - ** int main() - ** { - ** typedef oln::image2d<ntg::bin> im_type; - ** - ** im_type im1(oln::load(IMG_IN "object.pbm")); - ** save(oln::morpho::erosion(im1, oln::win_c8p()), - ** IMG_OUT "oln_morpho_erosion.pbm"); - ** } - ** \endcode - ** - ** \image html object_pbm.png - ** \image latex object_pbm.png - ** => - ** \image html oln_morpho_erosion.png - ** \image latex oln_morpho_erosion.png - ** - ** \see oln::morpho::fast::erosion() - */ + /// Erosion return type. - // fwd decl - template <typename I, typename W> struct erosion_ret; - - } - - // super_type - template <typename I, typename W> - struct set_super_type< morpho::erosion_ret<I,W> > - { - typedef abstract::image_unary_operator<oln_type_of(I, concrete), I, morpho::erosion_ret<I,W> > ret; - }; - - - - - namespace morpho { - - /// Erosion return. - - template <typename I, typename W> - struct erosion_ret : public abstract::image_unary_operator<oln_type_of(I, concrete), I, erosion_ret<I,W> > + template <typename I> + struct erosion_ret : public oln_super_of_(erosion_ret<I>) { - typedef abstract::image_unary_operator<oln_type_of(I, concrete), I, erosion_ret<I,W> > super_type; - typedef typename super_type::output_type output_type; + typedef oln_super_of(erosion_ret<I>) super_type; - const W win; - - erosion_ret(const abstract::image<I>& input, - const abstract::window<W>& win) : - super_type(input), - win(win.exact()) + erosion_ret(const abstract::image<I>& input) : + super_type(input) { } }; + // Various implementation. + namespace impl { - /// Erosion generic implementation. + /// Generic implementation of erosion (type). + template <typename I, typename W> - struct generic_erosion : public erosion_ret<I,W> + struct generic_erosion : public erosion_ret<I> { - typedef erosion_ret<I,W> super_type; - typedef typename super_type::output_type output_type; + typedef erosion_ret<I> super_type; + const W& win; + generic_erosion(const abstract::image<I>& input, const abstract::window<W>& win) : - super_type(input, win) + super_type(input), + win(win.exact()) { } void impl_run() { - mlc::eq<oln_type_of(I, size), oln_wn_type_of(W, size)>::ensure(); + oln_type_of(super_type, output) tmp(input.size()); // FIXME: trick + output = tmp; - output_type tmp(this->input.size()); // FIXME: trick - this->output = tmp; - - oln_type_of(I, fwd_piter) p(this->input.size()); + oln_type_of(I, fwd_piter) p(input.size()); for_all_p (p) - this->output[p] = morpho::min(this->input, p, this->win); + output[p] = morpho::min(input, p, win); } }; + // Generic implementation of erosion (routine). + + template<typename I, typename W> + erosion_ret<I> erosion(const abstract::image<I>& input, + const abstract::window<W>& win) + { + impl::generic_erosion<I,W> tmp(input, win); + tmp.run(); + return tmp; + } + + + + + /// Rectangle2d implementation of erosion (type). + + template <typename I> + struct rectangle2d_erosion : public erosion_ret<I> + { + typedef erosion_ret<I> super_type; + + const win_rectangle2d& win; + + rectangle2d_erosion(const abstract::image<I>& input, + const win_rectangle2d& win) : + super_type(input), + win(win) + {} + + void impl_run() + { + oln_type_of(super_type, output) temp(input.size()); // FIXME: trick + + win_rectangle2d hline(1, win.width); + win_rectangle2d vline(win.height, 1); + + temp = morpho::erosion(input, hline); + output = morpho::erosion(temp, vline); + } + }; + + // Rectangle2d implementation of erosion (routine). + + template<typename I> + erosion_ret<I> erosion(const abstract::image<I>& input, + const win_rectangle2d& win) + { + impl::rectangle2d_erosion<I> tmp(input, win); + tmp.run(); + return tmp; + } + + + + } // end of namespace oln::morpho::impl - /// Erosion generic routine. + /// Generic erosion (facade). + template<typename I, typename W> - erosion_ret<I,W> erosion(const abstract::image<I>& input, - const abstract::window<W>& win) + erosion_ret<I> erosion(const abstract::image<I>& input, + const abstract::window<W>& win) { - impl::generic_erosion<I,W> tmp(input, win); - tmp.run(); - return tmp; + mlc::eq<oln_type_of(I, grid), oln_wn_type_of(W, grid)>::ensure(); + return impl::erosion(input.exact(), win.exact()); } } // end of namespace oln::morpho + } // end of namespace oln