
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Have area closing and opening work on line graph images. * mln/core/concept/point_set.hh (mln::Point_Set<E>::Point_Set): No longer require the presence of a bounding box. * mln/core/concept/point_site.hh: Add a FIXME. * mln/level/sort_points.hh: Wrap long lines. (sort_points_increasing_(trait::image::quant::low, const I&)) (sort_points_decreasing_(trait::image::quant::low, const I&)): Fix the initialization of the return value. * mln/level/sort_psites.hh: New. Use it... * mln/morpho/closing_attribute.hh, * mln/morpho/opening_attribute.hh: ...here. s/point/psite/ * mln/canvas/morpho/algebraic_union_find.hh, * mln/labeling/regional_minima.hh, * mln/convert/to_p_array.hh: Likewise. * mln/core/p_array.hh (mln::p_array<P>::psite, mln::p_array<P>::point): New typedefs. (mln::p_array<P>::has): Tale a psite as argument, not a point. s/box_<P>/box_<point>/. * mln/core/p_array_piter.hh (mln::p_array_fwd_piter_<P>::psite) (mln::p_array_fwd_piter_<P>::point): (mln::p_array_bkd_piter_<P>::psite) (mln::p_array_bkd_piter_<P>::point): New typedefs. (mln::p_array_fwd_piter_<P>::to_psite) (mln::p_array_fwd_piter_<P>::operator psite): (mln::p_array_bkd_piter_<P>::to_psite) (mln::p_array_bkd_piter_<P>::operator psite): New. (mln::p_array_fwd_piter_<P>::operator P): (mln::p_array_bkd_piter_<P>::operator P): Remove. (mln::p_array_fwd_piter_<P>::p_) (mln::p_array_bkd_piter_<P>::p_): Change the type of this member from P to psite. (mln::p_array_fwd_piter_<P>::to_point) (mln::p_array_fwd_piter_<P>::operator[](unsigned)): (mln::p_array_bkd_piter_<P>::to_point) (mln::p_array_bkd_piter_<P>::operator[](unsigned)): Fix return types. * tests/morpho/lena_line_graph_image_wst2.cc: Simplify the line graph image using an area closing, instead of simplifying the initial (image2d) image. mln/canvas/morpho/algebraic_union_find.hh | 19 +- mln/convert/to_p_array.hh | 16 - mln/core/concept/point_set.hh | 9 - mln/core/concept/point_site.hh | 2 mln/core/p_array.hh | 13 + mln/core/p_array_piter.hh | 105 ++++++++---- mln/labeling/regional_minima.hh | 4 mln/level/sort_points.hh | 14 - mln/level/sort_psites.hh | 244 +++++++++++++++++++++++++++++ mln/morpho/closing_attribute.hh | 6 mln/morpho/opening_attribute.hh | 6 tests/morpho/lena_line_graph_image_wst2.cc | 39 ++-- 12 files changed, 383 insertions(+), 94 deletions(-) Index: mln/core/concept/point_set.hh --- mln/core/concept/point_set.hh (revision 1774) +++ mln/core/concept/point_set.hh (working copy) @@ -77,8 +77,10 @@ typedef bkd_piter; bool has(const psite& p) const; - const box_<point>& bbox() const; std::size_t npoints() const; + + // FIXME: No longer required (at least, not this way). + const box_<point>& bbox() const; */ protected: @@ -157,8 +159,9 @@ bool (E::*m1)(const psite& p) const = & E::has; m1 = 0; - const box_<point>& (E::*m2)() const = & E::bbox; - m2 = 0; + // FIXME: No longer required (at least, not this way). +// const box_<point>& (E::*m2)() const = & E::bbox; +// m2 = 0; std::size_t (E::*m3)() const = & E::npoints; m3 = 0; } Index: mln/core/concept/point_site.hh --- mln/core/concept/point_site.hh (revision 1774) +++ mln/core/concept/point_site.hh (working copy) @@ -338,6 +338,8 @@ return tmp; } + // FIXME: We shall not rely on a point object associted to the point + // site! (Such an object does not always exist.) template <typename P> inline std::ostream& operator<<(std::ostream& ostr, const Point_Site<P>& p_) Index: mln/level/sort_points.hh --- mln/level/sort_points.hh (revision 1774) +++ mln/level/sort_points.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -156,8 +156,7 @@ for_all(p) vec[loc[vset.index_of(input(p))]++] = p; - p_array<mln_point(I)> v; - v.hook_() = vec; + p_array<mln_point(I)> v(vec); return v; } @@ -201,8 +200,7 @@ for_all(p) vec[loc[vset.index_of(input(p))]++] = p; - p_array<mln_point(I)> v; - v.hook_() = vec; + p_array<mln_point(I)> v(vec); return v; } @@ -218,7 +216,8 @@ sort_points_increasing(const Image<I>& input) { mln_precondition(exact(input).has_data()); - return impl::sort_points_increasing_(mln_trait_image_quant(I)(), exact(input)); + return impl::sort_points_increasing_(mln_trait_image_quant(I)(), + exact(input)); } template <typename I> @@ -227,7 +226,8 @@ sort_points_decreasing(const Image<I>& input) { mln_precondition(exact(input).has_data()); - return impl::sort_points_decreasing_(mln_trait_image_quant(I)(), exact(input)); + return impl::sort_points_decreasing_(mln_trait_image_quant(I)(), + exact(input)); } # endif // ! MLN_INCLUDE_ONLY Index: mln/level/sort_psites.hh --- mln/level/sort_psites.hh (revision 0) +++ mln/level/sort_psites.hh (revision 0) @@ -0,0 +1,244 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) +// +// 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_LEVEL_SORT_PSITES_HH +# define MLN_LEVEL_SORT_PSITES_HH + +/*! \file mln/level/sort_psites.hh + * + * \brief Sort_Psites the contents of an image into another one. + * + * \todo Factor code + optimize. + */ + +/* FIXME: Factor with mln/level/sort_points.hh, if needed (maybe wait + for the upcoming big changes regarding types associated to images + (point -> site, etc.). */ + +# include <algorithm> + +# include <mln/core/concept/image.hh> +# include <mln/convert/to_p_array.hh> +# include <mln/histo/compute.hh> + + +namespace mln +{ + + namespace level + { + + /*! Sort psites the image \p input through a function \p f to set + * the \p output image in increasing way. + * + * \param[in] input The input image. + * + * \pre \p input.has_data + */ + template <typename I> + p_array<mln_psite(I)> sort_psites_increasing(const Image<I>& input); + + /*! Sort psites the image \p input through a function \p f to set + * the \p output image in decreasing way. + * + * \param[in] input The input image. + * + * \pre \p input.has_data + */ + template <typename I> + p_array<mln_psite(I)> sort_psites_decreasing(const Image<I>& input); + + +# ifndef MLN_INCLUDE_ONLY + + namespace impl + { + + // utility + + template <typename I> + struct value_psite_less_ + { + const I& ima_; + + inline + value_psite_less_(const I& ima) + : ima_(ima) + { + } + + inline + bool operator()(const mln_psite(I)& lhs, + const mln_psite(I)& rhs) const + { + return ima_(lhs) < ima_(rhs) || (ima_(lhs) == ima_(rhs) + && lhs < rhs); + } + }; + + template <typename I> + struct value_psite_greater_ + { + const I& ima_; + + inline + value_psite_greater_(const I& ima) + : ima_(ima) + { + } + + inline + bool operator()(const mln_psite(I)& lhs, + const mln_psite(I)& rhs) const + { + return ima_(lhs) > ima_(rhs) || (ima_(lhs) == ima_(rhs) + && lhs > rhs); + } + }; + + + // increasing + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_increasing_(trait::image::quant::any, // general case + const I& input) + { + p_array<mln_psite(I)> v = convert::to_p_array(input.domain()); + std::sort(v.hook_().begin(), v.hook_().end(), + value_psite_less_<I>(input)); + return v; + } + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_increasing_(trait::image::quant::low, // low quantization + const I& input) + { + typedef mln_vset(I) S; + const S& vset = input.values(); + const unsigned n = vset.nvalues(); + + // h + histo::data<S> h = histo::compute(input); + + // preparing output data + std::vector<unsigned> loc(vset.nvalues()); + loc[0] = 0; + for (unsigned i = 1; i != n; ++i) + loc[i] = loc[i-1] + h[i-1]; + + // computing output data + std::vector<mln_psite(I)> vec(input.npoints()); + mln_fwd_piter(I) p(input.domain()); + for_all(p) + vec[loc[vset.index_of(input(p))]++] = p; + + p_array<mln_psite(I)> v(vec); + return v; + } + + + // decreasing + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_decreasing_(trait::image::quant::any, // general case + const I& input) + { + p_array<mln_psite(I)> v = convert::to_p_array(input.domain()); + std::sort(v.hook_().begin(), v.hook_().end(), + value_psite_greater_<I>(input)); + return v; + } + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_decreasing_(trait::image::quant::low, // low quantization + const I& input) + { + typedef mln_vset(I) S; + const S& vset = input.values(); + const unsigned n = vset.nvalues(); + + // h + histo::data<S> h = histo::compute(input); + + // preparing output data + std::vector<unsigned> loc(vset.nvalues()); + loc[n-1] = 0; + for (int i = n - 2; i >= 0; --i) + loc[i] = loc[i+1] + h[i+1]; + + // computing output data + std::vector<mln_psite(I)> vec(input.npoints()); + mln_fwd_piter(I) p(input.domain()); + for_all(p) + vec[loc[vset.index_of(input(p))]++] = p; + + p_array<mln_psite(I)> v(vec); + return v; + } + + + } // end of namespace mln::level::impl + + + // Facades. + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_increasing(const Image<I>& input) + { + mln_precondition(exact(input).has_data()); + return impl::sort_psites_increasing_(mln_trait_image_quant(I)(), + exact(input)); + } + + template <typename I> + inline + p_array<mln_psite(I)> + sort_psites_decreasing(const Image<I>& input) + { + mln_precondition(exact(input).has_data()); + return impl::sort_psites_decreasing_(mln_trait_image_quant(I)(), + exact(input)); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::level + +} // end of namespace mln + + +#endif // ! MLN_LEVEL_SORT_PSITES_HH Index: mln/morpho/closing_attribute.hh --- mln/morpho/closing_attribute.hh (revision 1774) +++ mln/morpho/closing_attribute.hh (working copy) @@ -35,7 +35,7 @@ # include <mln/morpho/includes.hh> # include <mln/canvas/morpho/algebraic_union_find.hh> -# include <mln/level/sort_points.hh> +# include <mln/level/sort_psites.hh> # include <mln/util/pix.hh> @@ -66,7 +66,7 @@ typename I_, typename N_, typename O_> struct closing_attribute_t { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::morpho::algebraic_union_find @@ -108,7 +108,7 @@ closing_attribute_t(const I_& input, const N_& nbh, mln_result(A) lambda, O_& output) : input(input), nbh(nbh), lambda(lambda), output(output), - s(level::sort_points_increasing(input)) + s(level::sort_psites_increasing(input)) { } Index: mln/morpho/opening_attribute.hh --- mln/morpho/opening_attribute.hh (revision 1774) +++ mln/morpho/opening_attribute.hh (working copy) @@ -35,7 +35,7 @@ # include <mln/morpho/includes.hh> # include <mln/canvas/morpho/algebraic_union_find.hh> -# include <mln/level/sort_points.hh> +# include <mln/level/sort_psites.hh> # include <mln/util/pix.hh> @@ -66,7 +66,7 @@ typename I_, typename N_, typename O_> struct opening_attribute_t { - typedef mln_point(I_) P; + typedef mln_psite(I_) P; // requirements from mln::canvas::morpho::algebraic_union_find @@ -108,7 +108,7 @@ opening_attribute_t(const I_& input, const N_& nbh, mln_result(A) lambda, O_& output) : input(input), nbh(nbh), lambda(lambda), output(output), - s(level::sort_points_decreasing(input)) + s(level::sort_psites_decreasing(input)) { } Index: mln/canvas/morpho/algebraic_union_find.hh --- mln/canvas/morpho/algebraic_union_find.hh (revision 1774) +++ mln/canvas/morpho/algebraic_union_find.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -60,11 +60,11 @@ typedef typename F::O O; typedef typename F::S S; typedef typename F::A A; - typedef mln_point(I) point; + typedef mln_psite(I) psite; // aux: mln_ch_value(O, bool) deja_vu; - mln_ch_value(O, point) parent; + mln_ch_value(O, psite) parent; mln_ch_value(O, A) data; algebraic_union_find(F& f) @@ -83,6 +83,7 @@ initialize(data, f.input); f.init(); } + // first pass { mln_fwd_piter(S) p(f.s); @@ -116,18 +117,18 @@ } // end of run() - void make_set(const point& p) + void make_set(const psite& p) { parent(p) = p; data(p).take_as_init(make::pix(f.input, p)); // FIXME: algebraic so p! } - bool is_root(const point& p) const + bool is_root(const psite& p) const { return parent(p) == p; } - point find_root(const point& x) + psite find_root(const psite& x) { if (parent(x) == x) return x; @@ -135,15 +136,15 @@ return parent(x) = find_root(parent(x)); } - bool equiv(const point2d& r, const point2d& p) + bool equiv(const psite& r, const psite& p) { // Either a flat zone or the component of r is still growing. return f.input(r) == f.input(p) || f.is_active(data(r)); } - void do_union(const point& n, const point& p) + void do_union(const psite& n, const psite& p) { - point r = find_root(n); + psite r = find_root(n); if (r != p) { if (equiv(r, p)) Index: mln/labeling/regional_minima.hh --- mln/labeling/regional_minima.hh (revision 1774) +++ mln/labeling/regional_minima.hh (working copy) @@ -38,7 +38,7 @@ # include <mln/core/concept/neighborhood.hh> # include <mln/canvas/labeling.hh> # include <mln/level/fill.hh> -# include <mln/level/sort_points.hh> +# include <mln/level/sort_psites.hh> namespace mln @@ -107,7 +107,7 @@ regional_minima_functor(const I_& input, const N_& nbh) : input(input), nbh(nbh), - s(level::sort_points_increasing(input)), // FIXME: + s(level::sort_psites_increasing(input)), // FIXME: // sort_psites_increasing attr(input.domain()) { Index: mln/convert/to_p_array.hh --- mln/convert/to_p_array.hh (revision 1774) +++ mln/convert/to_p_array.hh (working copy) @@ -45,14 +45,14 @@ /// Convert a point set \p pset into a p_array (point set vector). template <typename S> - p_array<mln_point(S)> to_p_array(const Point_Set<S>& pset); + p_array<mln_psite(S)> to_p_array(const Point_Set<S>& pset); /// Convert a window \p win centered at point \p p into a p_array /// (point set vector). template <typename W> - p_array<mln_point(W)> to_p_array(const Window<W>& win, - const mln_point(W)& p); + p_array<mln_psite(W)> to_p_array(const Window<W>& win, + const mln_psite(W)& p); @@ -60,10 +60,10 @@ template <typename S> inline - p_array<mln_point(S)> to_p_array(const Point_Set<S>& pset_) + p_array<mln_psite(S)> to_p_array(const Point_Set<S>& pset_) { const S& pset = exact(pset_); - p_array<mln_point(S)> v; + p_array<mln_psite(S)> v; v.reserve(pset.npoints()); mln_fwd_piter(S) p(pset); for_all(p) @@ -73,10 +73,10 @@ template <typename W> inline - p_array<mln_point(W)> to_p_array(const Window<W>& win, - const mln_point(W)& p) + p_array<mln_psite(W)> to_p_array(const Window<W>& win, + const mln_psite(W)& p) { - p_array<mln_point(W)> v; + p_array<mln_psite(W)> v; v.reserve(exact(win).ndpoints()); mln_qiter(W) q(win, p); for_all(q) Index: mln/core/p_array.hh --- mln/core/p_array.hh (revision 1774) +++ mln/core/p_array.hh (working copy) @@ -60,6 +60,11 @@ class p_array : public internal::point_set_base_< P, p_array<P> > { public: + /// The associated psite type. + typedef P psite; + + /// The associated point type. + typedef mln_point(P) point; /// Forward Point_Iterator associated type. typedef p_array_fwd_piter_<P> fwd_piter; @@ -77,13 +82,13 @@ void reserve(std::size_t n); /// Test is \p p belongs to this point set. - bool has(const P& p) const; + bool has(const psite& p) const; /// Give the number of points. std::size_t npoints() const; /// Give the exact bounding box. - const box_<P>& bbox() const; + const box_<point>& bbox() const; /// Append a point \p p. p_array<P>& append(const P& p); @@ -103,7 +108,7 @@ protected: std::vector<P> vect_; - mutable accu::bbox<P> bb_; + mutable accu::bbox<point> bb_; mutable bool bb_needs_update_; void update_bb_() const; @@ -177,7 +182,7 @@ template <typename P> inline - const box_<P>& + const box_<mln_point(P)>& p_array<P>::bbox() const { mln_precondition(npoints() != 0); Index: mln/core/p_array_piter.hh --- mln/core/p_array_piter.hh (revision 1774) +++ mln/core/p_array_piter.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2007 EPITA Research and Development Laboratory +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE) // // This file is part of the Olena Library. This library is free // software; you can redistribute it and/or modify it under the terms @@ -28,10 +28,8 @@ #ifndef MLN_CORE_P_ARRAY_PITER_HH # define MLN_CORE_P_ARRAY_PITER_HH -/*! \file mln/core/p_array_piter.hh - * - * \brief Definition of point iterators on mln::p_array. - */ +/// \file mln/core/p_array_piter.hh +/// \brief Definition of point iterators on mln::p_array. # include <mln/core/p_array.hh> @@ -39,28 +37,34 @@ namespace mln { - /*! \brief Forward iterator on points of a p_array<P>. - * - */ + /// \brief Forward iterator on points of a p_array<P>. template <typename P> - struct p_array_fwd_piter_ : public internal::point_iterator_base_< P, p_array_fwd_piter_<P> > + struct p_array_fwd_piter_ + : public internal::point_iterator_base_< P, p_array_fwd_piter_<P> > { typedef p_array_fwd_piter_<P> self_; typedef internal::point_iterator_base_< P, self_ > super_; public: + /// The associated psite type. + typedef P psite; + + /// The associated point type. + typedef mln_point(P) point; - // Make definitions from super class available. enum { dim = super_::dim }; /// Coordinate associated type. template <typename S> p_array_fwd_piter_(const Point_Set<S>& s); + /// Reference of the corresponding psite. + const psite& to_psite() const; + /// Reference of the corresponding point. - const P& to_point() const; + const point& to_point() const; /// Read-only access to the \p i-th coordinate. - mln_coord(P) operator[](unsigned i) const; + mln_coord(point) operator[](unsigned i) const; /// Test if the iterator is valid. bool is_valid() const; @@ -74,39 +78,46 @@ /// Go to the next point. void next_(); - /// Convert the iterator into a point. - operator P() const; + /// Convert the iterator into a psite. + operator psite() const; protected: const std::vector<P>& vect_; - unsigned i_; // FIXME: Why it's unsigned in fwd iterator and signed in the bkd one ? - P p_; + // FIXME: Why it's unsigned in fwd iterator and signed in the bkd one ? + unsigned i_; + psite p_; }; - /*! \brief Backward iterator on points of a p_array<P>. - * - */ + /// \brief Backward iterator on points of a p_array<P>. template <typename P> - struct p_array_bkd_piter_ : public internal::point_iterator_base_< P, p_array_bkd_piter_<P> > + struct p_array_bkd_piter_ + : public internal::point_iterator_base_< P, p_array_bkd_piter_<P> > { typedef p_array_bkd_piter_<P> self_; typedef internal::point_iterator_base_< P, self_ > super_; public: + /// The associated psite type. + typedef P psite; + + /// The associated point type. + typedef mln_point(P) point; - // Make definitions from super class available. enum { dim = super_::dim }; /// Coordinate associated type. template <typename S> p_array_bkd_piter_(const Point_Set<S>& s); + /// Reference of the corresponding psite. + const psite& to_psite() const; + /// Reference of the corresponding point. - const P& to_point() const; + const point& to_point() const; /// Read-only access to the \p i-th coordinate. - mln_coord(P) operator[](unsigned i) const; + mln_coord(point) operator[](unsigned i) const; /// Test if the iterator is valid. bool is_valid() const; @@ -120,20 +131,28 @@ /// Go to the next point. void next_(); - /// Convert the iterator into a point. - operator P() const; + /// Convert the iterator into a psite. + operator psite() const; protected: const std::vector<P>& vect_; + /* FIXME: See the comment on p_array_fwd_piter_<P>::i_ above. We + could turn this `int' into an `unsigned'. Then, + - setting the value of i_ to -1 (== UINT_MAX) in invalidate(), + - and having valid() test whether i_ is strictly smaller than + vect_.size() + should work in both iterators (fwd and bkd). */ int i_; - P p_; + psite p_; }; # ifndef MLN_INCLUDE_ONLY - // p_array_fwd_piter_<P> + /*------------------------. + | p_array_fwd_piter_<P>. | + `------------------------*/ template <typename P> template <typename S> @@ -147,19 +166,27 @@ template <typename P> inline const P& - p_array_fwd_piter_<P>::to_point() const + p_array_fwd_piter_<P>::to_psite() const { return p_; } template <typename P> inline - mln_coord(P) + const mln_point(P)& + p_array_fwd_piter_<P>::to_point() const + { + return p_.to_point(); + } + + template <typename P> + inline + mln_coord(mln_point_(P)) p_array_fwd_piter_<P>::operator[](unsigned i) const { mln_precondition(i < dim); mln_precondition(is_valid()); - return p_[i]; + return p_.to_point()[i]; } template <typename P> @@ -207,7 +234,9 @@ } - // p_array_bkd_piter_<P> + /*------------------------. + | p_array_bkd_piter_<P>. | + `------------------------*/ template <typename P> template <typename S> @@ -221,19 +250,27 @@ template <typename P> inline const P& - p_array_bkd_piter_<P>::to_point() const + p_array_bkd_piter_<P>::to_psite() const { return p_; } template <typename P> inline - mln_coord(P) + const mln_point(P)& + p_array_bkd_piter_<P>::to_point() const + { + return p_.to_point(); + } + + template <typename P> + inline + mln_coord(mln_point_(P)) p_array_bkd_piter_<P>::operator[](unsigned i) const { mln_precondition(i < dim); mln_precondition(is_valid()); - return p_[i]; + return p_.to_point()[i]; } template <typename P> Index: tests/morpho/lena_line_graph_image_wst2.cc --- tests/morpho/lena_line_graph_image_wst2.cc (revision 1774) +++ tests/morpho/lena_line_graph_image_wst2.cc (working copy) @@ -34,7 +34,6 @@ \brief More tests on the Watershed Transform (WST) on a mln::line_graph_image. - The scenario is as follows: \li load a 2-D, gray-level image from a PGM file; \li simplify the image to reduce the number of local minima; @@ -99,14 +98,6 @@ image2d<input_val_t> input; io::pgm::load(input, MLN_IMG_DIR "/small.pgm"); - /* FIXME: In fact, we'd probably want to compute the gradient - /before/ simplfying the image, but as the area closing doesn't - work (yet) on graph images, hence we cannot do this yet. */ - - // Simplify the input image. - image2d<input_val_t> work(input.domain()); - morpho::closing_area(input, c8(), 500, work); - /*-------------. | Line graph. | `-------------*/ @@ -118,18 +109,18 @@ // Points. /* FIXME: The need for such a structure during the conversion exhibits the lack of a service from util::graph (or a another, - missing tool) regarding the retrieval of node ids from + missing tool) regarding the retrieval of nodes' ids from points. */ std::map<point2d, util::node_id> points; util::node_id id = 0; // Nodes. std::vector<input_val_t> node_values; - mln_fwd_piter_(image2d<input_val_t>) p(work.domain()); + mln_fwd_piter_(image2d<input_val_t>) p(input.domain()); for_all (p) { g.add_node (p); - node_values.push_back (work(p)); + node_values.push_back (input(p)); /* FIXME: ``Guessing'' the id of the point just being inserted is bad. utill:graph<N,E>::add_node should return this id. */ @@ -144,12 +135,12 @@ mln_fwd_qiter_(window2d) q(next_c4_win, p); for_all (p) for_all (q) - if (work.has(q)) + if (input.has(q)) { g.add_edge(points[p], points[q]); // The computed value is a kind of norm of the gradient // bewteen P and Q. - edge_values.push_back(math::abs(work(p) - work(q))); + edge_values.push_back(math::abs(input(p) - input(q))); } // Line graph point set. @@ -163,21 +154,27 @@ | Simplification. | `-----------------*/ - // FIXME: Adjust the area closing filter, so that we can apply it on - // graph images. + typedef line_graph_elt_neighborhood<point2d> nbh_t; + nbh_t nbh; + + ima_t closed_lg_ima (lg_ima.domain()); + /* FIXME: We should change the attribute closing performed here; + instead of computing the area using the data on the lines + (edges), whe should use the data on the pixels (vertices). + + The best way is probably to create another attribute-functor and + use the algebraic_union_find canvas. */ + morpho::closing_area(lg_ima, nbh, 20, closed_lg_ima); /*------. | WST. | `------*/ - typedef line_graph_elt_neighborhood<point2d> nbh_t; - nbh_t nbh; - // Perform a Watershed Transform. typedef int_u16 wst_full_val_t; wst_full_val_t nbasins; typedef line_graph_image<point2d, wst_full_val_t> wst_full_ima_t; - wst_full_ima_t wshed_full = morpho::meyer_wst(lg_ima, nbh, nbasins); + wst_full_ima_t wshed_full = morpho::meyer_wst(closed_lg_ima, nbh, nbasins); std::cout << "nbasins = " << nbasins << std::endl; // Reduce the value set to 8-bit. @@ -243,7 +240,7 @@ { if (wshed(pw) == 0) { - mln_point_(wst_ima_t) pp(pw); + mln_psite_(wst_ima_t) pp(pw); // Equivalent of the line (edge) PP in OUTPUT. int row1 = pp.first()[0] * 2; int col1 = pp.first()[1] * 2;