3596: Several bug fixes.
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Several bug fixes. * mln/histo/array.hh: Layout. * mln/core/image/image1d.hh (from_to_): Remove border setting to 0. Add some hints of future code. (todo): New. * mln/core/alias/point1d.hh: Upgrade doc style. (row, row_t): Fix naming as... (ind, ind_t): ...those. * mln/linear/gaussian_directional_2d.hh: New. * mln/linear/gaussian_1d.hh: New. Both files have been copied from my sandbox. * mln/linear/all.hh: Update. * mln/accu/center.hh (to_result): Make it work when invalid. (todo): New. * mln/value/label.hh (prev): New. * mln/canvas/morpho/attribute_filter.hh (lambda): Use macro for this arg type. (attribute_filter_dispatch): Fix missing border adjustment for the fastest version. (attribute_filter_fastest): New precondition. Fix missing border initialization so that it is neutral. * tests/morpho/closing/volume.cc: Force no border to test that the border is correctly adapted to nbh. * mln/labeling/compute.hh: Move code intro trace. mln/accu/center.hh | 18 ++--- mln/canvas/morpho/attribute_filter.hh | 42 ++++++++----- mln/core/alias/point1d.hh | 48 +++++++------- mln/core/image/image1d.hh | 12 +++ mln/histo/array.hh | 1 mln/labeling/compute.hh | 15 +++- mln/linear/all.hh | 11 ++- mln/linear/gaussian_1d.hh | 109 ++++++++++++++++++++++++++++++++++ mln/linear/gaussian_directional_2d.hh | 98 ++++++++++++++++++++++++------ mln/value/label.hh | 11 +++ tests/morpho/closing/volume.cc | 5 + 11 files changed, 291 insertions(+), 79 deletions(-) Index: mln/histo/array.hh --- mln/histo/array.hh (revision 3595) +++ mln/histo/array.hh (working copy) @@ -81,6 +81,7 @@ + # ifndef MLN_INCLUDE_ONLY template <typename T> Index: mln/core/image/image1d.hh --- mln/core/image/image1d.hh (revision 3595) +++ mln/core/image/image1d.hh (working copy) @@ -32,6 +32,8 @@ /// \file mln/core/image/image1d.hh /// /// Definition of the basic mln::image1d class. +/// +/// \todo Rewrite from_to(histo, image1d) after Etienne's work. # include <mln/core/internal/fixme.hh> # include <mln/core/internal/image_primary.hh> @@ -576,7 +578,13 @@ void from_to_(const histo::array<V>& from, image1d<T>& to) { - to.init_(make::box1d(from.nvalues()), 0); + // FIXME: The code should looks like: + +// box1d b(point1d(mln_min(V)), point1d(mln_max(V))); +// ima.init_(b, 0); +// for_all(v) +// from_to(h(v), ima.at_( index_of(v) )); + to.init_(make::box1d(from.nvalues())); for (unsigned i = 0; i < from.nvalues(); ++i) from_to(from[i], to(point1d(i))); } @@ -587,7 +595,7 @@ void from_to_(const util::array<V>& from, image1d<T>& to) { - to.init_(make::box1d(from.nelements()), 0); + to.init_(make::box1d(from.nelements())); for (unsigned i = 0; i < from.nelements(); ++i) from_to(from[i], to(point1d(i))); } Index: mln/core/alias/point1d.hh --- mln/core/alias/point1d.hh (revision 3595) +++ mln/core/alias/point1d.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2007, 2008, 2009 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 @@ -29,25 +29,26 @@ #ifndef MLN_CORE_ALIAS_POINT1D_HH # define MLN_CORE_ALIAS_POINT1D_HH -/*! \file mln/core/alias/point1d.hh - * - * \brief Definition of the mln::point1d alias and of its construction - * routine. - */ +/// \file mln/core/alias/point1d.hh +/// +/// Definition of the mln::point1d alias and of its construction +/// routine. # include <mln/core/point.hh> // For site_const_impl and site_mutable_impl. # include <mln/core/concept/site_proxy.hh> # include <mln/core/internal/force_exact.hh> + namespace mln { - /*! \brief Type alias for a point defined on the 1D square grid with - * integer coordinates. - */ + /// Type alias for a point defined on the 1D square grid with + /// integer coordinates. + // typedef point<grid::tick, def::coord> point1d; + namespace internal { @@ -59,8 +60,8 @@ typedef C coord; enum { dim = 1 }; - typedef const C& row_t; - const C& row() const; + typedef const C& ind_t; + const C& ind() const; const C& operator[](unsigned i) const; const C& last_coord() const; @@ -79,8 +80,8 @@ typedef subject_impl< const point<grid::tick, C>, E > super_; E& exact_(); public: - using super_::row; - C& row(); + using super_::ind; + C& ind(); using super_::operator[]; C& operator[](unsigned i); }; @@ -94,9 +95,9 @@ template <typename C, typename E> inline const C& - subject_impl< const point<grid::tick, C>, E >::row() const + subject_impl< const point<grid::tick, C>, E >::ind() const { - return exact_().get_subject().row(); + return exact_().get_subject().ind(); } template <typename C, typename E> @@ -104,8 +105,9 @@ const C& subject_impl< const point<grid::tick, C>, E >::operator[](unsigned i) const { - mln_precondition(i < 1); - return exact_().get_subject()[i]; + mln_precondition(i == 0); + (void)i; + return exact_().get_subject()[0]; } template <typename C, typename E> @@ -121,9 +123,9 @@ template <typename C, typename E> inline C& - subject_impl< point<grid::tick, C>, E >::row() + subject_impl< point<grid::tick, C>, E >::ind() { - return exact_().get_subject().row(); + return exact_().get_subject().ind(); } template <typename C, typename E> @@ -131,15 +133,15 @@ C& subject_impl< point<grid::tick, C>, E >::operator[](unsigned i) { - mln_precondition(i < 2); - return exact_().get_subject()[i]; + mln_precondition(i == 0); + (void)i; + return exact_().get_subject()[0]; } # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::internal - } // end of namespace mln Index: mln/linear/all.hh --- mln/linear/all.hh (revision 3595) +++ mln/linear/all.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2007, 2008, 2009 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 @@ -50,8 +50,7 @@ { /// Namespace of local linear routines implementation details. - namespace impl - {} + namespace impl {} } } @@ -62,7 +61,11 @@ # include <mln/linear/convolve.hh> # include <mln/linear/convolve_2x1d.hh> # include <mln/linear/convolve_directional.hh> + # include <mln/linear/gaussian.hh> +# include <mln/linear/gaussian_directional_2d.hh> +# include <mln/linear/gaussian_1d.hh> + # include <mln/linear/lap.hh> # include <mln/linear/log.hh> //# include <mln/linear/sobel.hh> Index: mln/linear/gaussian_directional_2d.hh --- mln/linear/gaussian_directional_2d.hh (revision 3588) +++ mln/linear/gaussian_directional_2d.hh (working copy) @@ -1,3 +1,38 @@ +// Copyright (C) 2009 EPITA Research and 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, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, 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_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH +# define MLN_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH + +/// \file mln/linear/gaussian_directional_2d.hh +/// +/// Directional Gaussian filter for 2D images. +/// +/// \todo This is experimental code to be merged with regular code... #include <mln/core/image/image2d.hh> #include <mln/extension/adjust_fill.hh> @@ -11,6 +46,17 @@ namespace linear { + + template <typename I> + mln_concrete(I) + gaussian_directional_2d(const Image<I>& input, + unsigned dir, double sigma, + const mln_value(I)& bdr); + + + +# ifndef MLN_INCLUDE_ONLY + namespace my { @@ -20,14 +66,14 @@ DericheGaussianFirstDerivative, DericheGaussianSecondDerivative }; - std::vector<MLN_FLOAT> n, d, nm, dm; - MLN_FLOAT sumA, sumC; + std::vector<double> n, d, nm, dm; + double sumA, sumC; - recursivefilter_coef_(MLN_FLOAT a0, MLN_FLOAT a1, - MLN_FLOAT b0, MLN_FLOAT b1, - MLN_FLOAT c0, MLN_FLOAT c1, - MLN_FLOAT w0, MLN_FLOAT w1, - MLN_FLOAT s, FilterType filter_type) + recursivefilter_coef_(double a0, double a1, + double b0, double b1, + double c0, double c1, + double w0, double w1, + double s, FilterType filter_type) { n.reserve(5); d.reserve(5); @@ -39,10 +85,10 @@ w0 /= s; w1 /= s; - MLN_FLOAT sin0 = sin(w0); - MLN_FLOAT sin1 = sin(w1); - MLN_FLOAT cos0 = cos(w0); - MLN_FLOAT cos1 = cos(w1); + double sin0 = sin(w0); + double sin1 = sin(w1); + double cos0 = cos(w0); + double cos1 = cos(w1); switch (filter_type) { @@ -81,7 +127,7 @@ case DericheGaussianSecondDerivative : { - MLN_FLOAT aux; + double aux; aux = 12.0 * cos0 * exp( 3.0 * b0 ) - 3.0 * exp( 2.0 * b0 ) + 8.0 * cos0 * cos0 * cos0 * exp( 3.0 * b0 ) - 12.0 * cos0 * cos0 * @@ -197,15 +243,15 @@ template <typename I, typename C> inline void - recursivefilter_directional_2d_generic(I& ima, + recursivefilter_directional_generic(I& ima, const C& c, const mln_psite(I)& start, const mln_psite(I)& finish, int len, const mln_deduce(I, psite, delta)& d) { - std::vector<MLN_FLOAT> tmp1(len); - std::vector<MLN_FLOAT> tmp2(len); + std::vector<double> tmp1(len); + std::vector<double> tmp2(len); tmp1[0] = c.n[0]*ima(start); @@ -292,7 +338,7 @@ template <typename I, typename C> inline void - recursivefilter_directional_2d_fastest(I& ima, + recursivefilter_directional_fastest(I& ima, const C& c, const mln_psite(I)& start, const mln_psite(I)& finish, @@ -303,8 +349,8 @@ // extension::adjust_fill(ima, 5 * int(151 + .50001) + 1, bdr); // extension::fill(ima, bdr); - std::vector<MLN_FLOAT> tmp1(len); - std::vector<MLN_FLOAT> tmp2(len); + std::vector<double> tmp1(len); + std::vector<double> tmp2(len); unsigned delta_offset = ima.delta_index(d); unsigned @@ -418,9 +464,14 @@ inline mln_concrete(I) gaussian_directional_2d(const Image<I>& input_, - unsigned dir, MLN_FLOAT sigma, + unsigned dir, double sigma, const mln_value(I)& bdr) { + trace::entering("linear::gaussian_directional_2d"); + + typedef mln_site(I) P; + mlc_bool(P::dim == 2)::check(); + const I& input = exact(input_); mln_precondition(dir == 0 || dir == 1); @@ -447,7 +498,7 @@ if (dir == 0) { for (int j = 0; j < ncols; ++j) - recursivefilter_directional_2d_fastest(output, coef, + recursivefilter_directional_fastest(output, coef, point2d(- b, j), point2d(nrows - 1 + b, j), nrows + 2 * b, @@ -458,7 +509,7 @@ if (dir == 1) { for (int i = 0; i < nrows; ++i) - recursivefilter_directional_2d_fastest(output, coef, + recursivefilter_directional_fastest(output, coef, point2d(i, - b), point2d(i, ncols - 1 + b), ncols + 2 * b, @@ -466,10 +517,15 @@ bdr); } + trace::exiting("linear::gaussian_directional_2d"); return output; } +# endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::linear } // end of namespace mln + + +#endif // ! MLN_LINEAR_GAUSSIAN_DIRECTIONAL_2D_HH Property changes on: mln/linear/gaussian_directional_2d.hh ___________________________________________________________________ Added: svn:mergeinfo Index: mln/linear/gaussian_1d.hh --- mln/linear/gaussian_1d.hh (revision 0) +++ mln/linear/gaussian_1d.hh (revision 0) @@ -0,0 +1,109 @@ +// Copyright (C) 2009 EPITA Research and 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, Inc., 51 Franklin Street, Fifth Floor, +// Boston, MA 02110-1301, 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_LINEAR_GAUSSIAN_1D_HH +# define MLN_LINEAR_GAUSSIAN_1D_HH + +/// \file mln/linear/gaussian_1d.hh +/// +/// Gaussian filter for fastest 1D images. +/// +/// \todo This is experimental code to be merged with regular code... + +#include <mln/core/image/image1d.hh> +#include <mln/linear/gaussian_directional_2d.hh> + + + +namespace mln +{ + + namespace linear + { + + + template <typename I> + mln_concrete(I) + gaussian_1d(const Image<I>& input, + double sigma, + const mln_value(I)& bdr); + + + +# ifndef MLN_INCLUDE_ONLY + + template <typename I> + inline + mln_concrete(I) + gaussian_1d(const Image<I>& input_, + double sigma, + const mln_value(I)& bdr) + { + trace::entering("linear::gaussian_1d"); + + typedef mln_site(I) P; + mlc_bool(P::dim == 1)::check(); + + const I& input = exact(input_); + mln_precondition(input.is_valid()); + + my::recursivefilter_coef_ coef(1.68f, 3.735f, + 1.783f, 1.723f, + -0.6803f, -0.2598f, + 0.6318f, 1.997f, + sigma, + my::recursivefilter_coef_::DericheGaussian); + + extension::adjust_fill(input, 5 * int(sigma + .50001) + 1, bdr); + mln_concrete(I) output = duplicate(input); + + if (sigma < 0.006) + return output; + + int + ninds = geom::ninds(input), + b = input.border(); + + recursivefilter_directional_fastest(output, coef, + point1d(- b), + point1d(ninds - 1 + b), + ninds + 2 * b, + dpoint1d(1), + bdr); + + trace::exiting("linear::gaussian_1d"); + return output; + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::linear + +} // end of namespace mln + + +#endif // ! MLN_LINEAR_GAUSSIAN_1D_HH Index: mln/accu/center.hh --- mln/accu/center.hh (revision 3595) +++ mln/accu/center.hh (working copy) @@ -1,4 +1,5 @@ -// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2008, 2009 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 @@ -31,7 +32,8 @@ /// \file mln/accu/center.hh /// /// Define an accumulator that computes the mass center of a site set. - +/// +/// \todo Fix to_result() value when invalid... # include <mln/accu/internal/base.hh> # include <mln/accu/bbox.hh> @@ -66,7 +68,6 @@ /// Get the value of the accumulator. V to_result() const; - operator V() const; operator P() const; /// Check whether this accu is able to return a result. @@ -136,19 +137,14 @@ V center<P,V>::to_result() const { - mln_precondition(is_valid()); + // mln_precondition(is_valid()); + if (! is_valid()) + return V(); return center_ / nsites_; } template <typename P, typename V> inline - center<P,V>::operator V() const - { - return to_result(); - } - - template <typename P, typename V> - inline center<P,V>::operator P() const { return P(to_result()); Index: mln/value/label.hh --- mln/value/label.hh (revision 3595) +++ mln/value/label.hh (working copy) @@ -155,6 +155,9 @@ /// Return the next value. label<n> next() const; + /// Return the previous value. + label<n> prev() const; + }; @@ -279,6 +282,14 @@ template <unsigned n> inline + label<n> + label<n>::prev() const + { + return label<n>(this->v_ - 1); + } + + template <unsigned n> + inline std::ostream& operator<<(std::ostream& ostr, const label<n>& i) { return ostr << debug::format(i.to_equiv()); Index: mln/canvas/morpho/attribute_filter.hh --- mln/canvas/morpho/attribute_filter.hh (revision 3595) +++ mln/canvas/morpho/attribute_filter.hh (working copy) @@ -1,5 +1,5 @@ -// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory -// (LRDE) +// Copyright (C) 2007, 2008, 2009 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 @@ -39,14 +39,15 @@ # include <mln/core/concept/accumulator.hh> # include <mln/level/sort_offsets.hh> - # include <mln/trait/accumulators.hh> - # include <mln/util/pix.hh> +# include <mln/border/get.hh> # include <mln/data/fill.hh> +# include <mln/extension/adjust_fill.hh> # include <mln/level/sort_psites.hh> + namespace mln { @@ -56,16 +57,20 @@ namespace morpho { - // Facade Fwd Declaration + // FIXME: Doc! + template <typename I, typename N, typename A> mln_concrete(I) attribute_filter(const Image<I>& input, const Neighborhood<N>& nbh, - const Accumulator<A>& a, const typename A::result& lambda, + const Accumulator<A>& a, const mln_result(A)& lambda, bool increasing); + + # ifndef MLN_INCLUDE_ONLY - namespace impl { + namespace impl + { template <typename A, typename I> void take_as_init_fastest (trait::accumulator::when_pix::use_none, A& accu, @@ -128,8 +133,9 @@ } - namespace generic { + namespace generic + { //////////////////////// /// Generic version. /// @@ -153,7 +159,7 @@ const Neighborhood<N>& nbh_, const Site_Set<S>& s_, const Accumulator<A>& a_, - const typename A::result& lambda) + const mln_result(A)& lambda) { trace::entering("canvas::morpho::impl::generic::attribute_filter"); // FIXME: Test?! @@ -278,7 +284,7 @@ const Neighborhood<N>& nbh_, const util::array<unsigned>& s, const Accumulator<A>& a_, - const typename A::result& lambda) + const mln_result(A)& lambda) { trace::entering("canvas::morpho::impl::attribute_filter_fastest"); // FIXME: Tests? @@ -287,6 +293,10 @@ const N& nbh = exact(nbh_); (void)a_; + // The border adaptation is performed in the calling scope since + // we want offsets of 's' to match the image structure / dimensions. + mln_precondition(border::get(input) >= nbh.delta()); + mln_concrete(I) output; initialize(output, input); @@ -303,6 +313,8 @@ { initialize(deja_vu, input); data::fill(deja_vu, false); + extension::fill(deja_vu, true); // So the border is neutral. + initialize(activity, input); data::fill(activity, true); initialize(parent, input); @@ -387,7 +399,7 @@ const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& a, - const typename A::result& lambda, + const mln_result(A)& lambda, bool increasing) { p_array<mln_psite(I)> s = increasing ? @@ -405,9 +417,11 @@ const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& a, - const typename A::result& lambda, + const mln_result(A)& lambda, bool increasing) { + extension::adjust(input, nbh); + util::array<unsigned> s = increasing ? level::sort_offsets_increasing(input) : @@ -424,7 +438,7 @@ attribute_filter_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& a, - const typename A::result& lambda, + const mln_result(A)& lambda, bool increasing) { enum { @@ -451,7 +465,7 @@ attribute_filter(const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& a, - const typename A::result& lambda, + const mln_result(A)& lambda, bool increasing) { return internal::attribute_filter_dispatch(input, nbh, a, lambda, increasing); Index: mln/labeling/compute.hh --- mln/labeling/compute.hh (revision 3595) +++ mln/labeling/compute.hh (working copy) @@ -1,4 +1,5 @@ -// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE) +// Copyright (C) 2008, 2009 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 @@ -39,7 +40,7 @@ # include <mln/core/concept/accumulator.hh> # include <mln/core/concept/meta_accumulator.hh> # include <mln/util/array.hh> -# include <mln/convert/to.hh> +# include <mln/convert/from_to.hh> namespace mln @@ -180,8 +181,11 @@ for_all(p) accus[label(p)].take(p); + util::array<mln_result(A)> res; + convert::from_to(accus, res); + trace::exiting("labeling::impl::generic::compute"); - return convert::to< util::array<mln_result(A)> >(accus); + return res; } @@ -206,8 +210,11 @@ for_all(p) accus[label(p)].take(input(p)); + util::array<mln_result(A)> res; + convert::from_to(accus, res); + trace::exiting("labeling::impl::generic::compute"); - return convert::to< util::array<mln_result(A)> >(accus); + return res; } } // end of namespace mln::labeling::impl::generic Index: tests/morpho/closing/volume.cc --- tests/morpho/closing/volume.cc (revision 3595) +++ tests/morpho/closing/volume.cc (working copy) @@ -40,6 +40,8 @@ #include <mln/morpho/closing/volume.hh> #include <mln/morpho/attribute/volume.hh> +#include <mln/border/resize.hh> + #include "tests/data.hh" @@ -51,6 +53,9 @@ typedef image2d<int_u8> I; I lena; io::pgm::load(lena, MLN_IMG_DIR "/tiny.pgm"); + + border::resize(lena, 0); + io::pgm::save(morpho::closing::volume(lena, c4(), 10000), "ref.pgm");
participants (1)
-
Thierry Geraud