
https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Thierry Geraud <thierry.geraud@lrde.epita.fr> Add morpho algebraic closing. * mln/morpho/attribute/volume.hh: New. * mln/morpho/closing_algebraic.hh: Copy to... * mln/morpho/opening_algebraic.hh: ...this new file. Make it a closing. * mln/canvas/morpho/algebraic_filter.hh (todo): New. * tests/morpho/closing_volume.cc: Test that the new version with morpho::attribute::volume gives the same result as the former version. mln/canvas/morpho/algebraic_filter.hh | 2 mln/morpho/attribute/volume.hh | 172 +++++++++++++++++----------------- mln/morpho/opening_algebraic.hh | 24 ++-- tests/morpho/closing_volume.cc | 16 ++- 4 files changed, 113 insertions(+), 101 deletions(-) Index: mln/morpho/attribute/volume.hh --- mln/morpho/attribute/volume.hh (revision 3334) +++ mln/morpho/attribute/volume.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 @@ -26,33 +26,50 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_ACCU_VOLUME_HH -# define MLN_ACCU_VOLUME_HH +#ifndef MLN_MORPHO_ATTRIBUTE_VOLUME_HH +# define MLN_MORPHO_ATTRIBUTE_VOLUME_HH -/// \file mln/accu/volume.hh +/// \file mln/morpho/attribute/volume.hh +/// /// Define an accumulator that computes the volume of a -/// component through one of its pixels. -/*! - This accumulator uses an mln::util::pix (pixel) to update the - reference level, area and volume information of the component. - - The class mln/accu/volume is not a general-purpose accumulator; - it is used to implement volume-based connected filters. - \see mln::morpho::closing_volume - \see mln::morpho::opening_volume -*/ +/// component. # include <mln/accu/internal/base.hh> -# include <mln/core/concept/meta_accumulator.hh> # include <mln/math/diff_abs.hh> -# include <mln/util/pix.hh> -# include <mln/literal/zero.hh> namespace mln { - namespace accu + // Forward declaration. + namespace morpho { + namespace attribute { + template <typename I> class volume; + } + } + + + // Traits. + + namespace trait + { + + template <typename I> + struct accumulator_< morpho::attribute::volume<I> > + { + typedef accumulator::has_untake::no has_untake; + typedef accumulator::has_set_value::no has_set_value; + typedef accumulator::has_stop::no has_stop; + typedef accumulator::when_pix::use_v when_pix; + }; + + } // end of namespace mln::trait + + + namespace morpho + { + + namespace attribute { /// Volume accumulator class. @@ -63,26 +80,20 @@ struct volume : public mln::accu::internal::base< unsigned , volume<I> > { - /// The accumulated data type. - /// - /// The volume of component is represented by the volume of its - /// root pixel. See mln::morpho::closing_volume and - /// mln::morpho::opening_volume for actual uses of this - /// accumulator. - typedef util::pix<I> argument; - /// The value type associated to the pixel type. - typedef typename argument::value value; + typedef mln_value(I) argument; volume(); /// Manipulators. /// \{ void init(); - void take(const argument& pixel); + + void take(const mln_value(I)& v); + void take(const util::pix<I>& px); void take(const volume<I>& other); - /// Force the value of the counter to \a v. - void set_value(unsigned v); + void take_as_init(const mln_value(I)& v); + void take_as_init(const util::pix<I>& px); /// \} /// Get the value of the accumulator. @@ -93,31 +104,15 @@ bool is_valid() const; protected: - /// The reference level (the level of the component's root). - value ref_level__; + /// The current level. + mln_value(I) level_; /// The area of the component. - unsigned area__; + unsigned area_; /// The volume of the component. unsigned volume_; }; - namespace meta - { - - /// Meta accumulator for volume. - - struct volume : public Meta_Accumulator< volume > - { - template <typename I> - struct with - { - typedef accu::volume<I> ret; - }; - }; - - } // end of namespace mln::accu::meta - # ifndef MLN_INCLUDE_ONLY @@ -133,32 +128,32 @@ void volume<I>::init() { - ref_level__ = literal::zero; volume_ = 0; - area__ = 0; } template <typename I> inline void - volume<I>::take(const argument& pixel) + volume<I>::take(const mln_value(I)& v) { - /* FIXME: Growing a component using this particular `take' - routine won't work, since the update does not take care of - the reference level to compute the new volume. Maybe we - could distinguish two cases: - - 1. the empty accumulator case (which corresponds to the - following code); - 2. the non-empty accumulator case (which sohuld act as in - `take(const volume<I>& other)'). + mln_invariant(volume_ != mln_max(unsigned)); + if (! is_valid()) + { + take_as_init(v); + return; + } + ++area_; + volume_ += 1 + math::diff_abs(v, level_); + level_ = v; + } - Currently, the implementation is only valid if the - accumulator was initialy empty before the call to - `take(const argument&)'. */ - ref_level__ = pixel.v(); - ++area__; - ++volume_; + template <typename I> + inline + void + volume<I>::take(const util::pix<I>& px) + { + mln_invariant(volume_ != mln_max(unsigned)); + take(px.v()); } template <typename I> @@ -166,33 +161,38 @@ void volume<I>::take(const volume<I>& other) { - area__ += other.area__; - /* FIXME: Is it `t.area__' or `area__' ? Th�o said it was - the latter, but both the ISMM 2005 paper and Olena 0.11 use - the former. */ + mln_invariant(volume_ != mln_max(unsigned)); + area_ += other.area_; volume_ += other.volume_ + - other.area__ * math::diff_abs(other.ref_level__, ref_level__); - // Member ref_level__ is not touched. + other.area_ * math::diff_abs(other.level_, level_); + // level_ do not change. } template <typename I> inline - unsigned - volume<I>::to_result() const + void + volume<I>::take_as_init(const mln_value(I)& v) { - return volume_; + level_ = v; + area_ = 1; + volume_ = 1; } template <typename I> inline void - volume<I>::set_value(unsigned v) + volume<I>::take_as_init(const util::pix<I>& px) + { + take_as_init(px.v()); + } + + template <typename I> + inline + unsigned + volume<I>::to_result() const { - volume_ = v; - // Reset the other members. - ref_level__ = literal::zero; - area__ = 0; + return volume_; } template <typename I> @@ -200,14 +200,16 @@ bool volume<I>::is_valid() const { - return true; + return volume_ != 0; } # endif // ! MLN_INCLUDE_ONLY - } // end of namespace mln::accu + } // end of namespace mln::morpho::attribute + + } // end of namespace mln::morpho } // end of namespace mln -#endif // ! MLN_ACCU_VOLUME_HH +#endif // ! MLN_MORPHO_ATTRIBUTE_VOLUME_HH Property changes on: mln/morpho/attribute/volume.hh ___________________________________________________________________ Added: svn:mergeinfo Index: mln/morpho/opening_algebraic.hh --- mln/morpho/opening_algebraic.hh (revision 3334) +++ mln/morpho/opening_algebraic.hh (working copy) @@ -26,12 +26,12 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef MLN_MORPHO_CLOSING_ALGEBRAIC_HH -# define MLN_MORPHO_CLOSING_ALGEBRAIC_HH +#ifndef MLN_MORPHO_OPENING_ALGEBRAIC_HH +# define MLN_MORPHO_OPENING_ALGEBRAIC_HH -/// \file mln/morpho/closing_algebraic.hh +/// \file mln/morpho/opening_algebraic.hh /// -/// Morphological algebraic closing. +/// Morphological algebraic opening. # include <mln/morpho/includes.hh> # include <mln/canvas/morpho/algebraic_filter.hh> @@ -43,10 +43,10 @@ namespace morpho { - /// Morphological algebraic closing. + /// Morphological algebraic opening. template <typename I, typename N, typename A> mln_concrete(I) - closing_algebraic(const Image<I>& input, const Neighborhood<N>& nbh, + opening_algebraic(const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& accu, const mln_result(A)& lambda); @@ -58,20 +58,20 @@ template <typename I, typename N, typename A> inline mln_concrete(I) - closing_algebraic(const Image<I>& input, const Neighborhood<N>& nbh, + opening_algebraic(const Image<I>& input, const Neighborhood<N>& nbh, const Accumulator<A>& accu, const mln_result(A)& lambda) { - trace::entering("morpho::closing_algebraic"); + trace::entering("morpho::opening_algebraic"); mln_precondition(exact(input).is_valid()); mln_concrete(I) output; output = canvas::morpho::algebraic_filter(input, nbh, accu, lambda, - /* increasing = */ true); + /* increasing = */ false); - mln_postcondition(output >= input); + mln_postcondition(output <= input); - trace::exiting("morpho::closing_algebraic"); + trace::exiting("morpho::opening_algebraic"); return output; } @@ -83,4 +83,4 @@ } // end of namespace mln -#endif // ! MLN_MORPHO_CLOSING_ALGEBRAIC_HH +#endif // ! MLN_MORPHO_OPENING_ALGEBRAIC_HH Index: mln/canvas/morpho/algebraic_filter.hh --- mln/canvas/morpho/algebraic_filter.hh (revision 3343) +++ mln/canvas/morpho/algebraic_filter.hh (working copy) @@ -32,6 +32,8 @@ /// \file mln/canvas/morpho/algebraic_filter.hh /// /// Canvas for morphological algebraic filters. +/// +/// \todo Add a version without 'activity' thanx to set_value. # include <mln/core/concept/image.hh> # include <mln/core/concept/neighborhood.hh> Index: tests/morpho/closing_volume.cc --- tests/morpho/closing_volume.cc (revision 3343) +++ tests/morpho/closing_volume.cc (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 @@ -38,15 +38,23 @@ #include <mln/io/pgm/save.hh> #include <mln/morpho/closing_volume.hh> +#include <mln/morpho/attribute/volume.hh> #include "tests/data.hh" + int main() { using namespace mln; using value::int_u8; - image2d<int_u8> lena; + typedef image2d<int_u8> I; + I lena; io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm"); - io::pgm::save(morpho::closing_volume(lena, c4(), 10000), "out.pgm"); + io::pgm::save(morpho::closing_volume(lena, c4(), 10000), + "ref.pgm"); + + typedef morpho::attribute::volume<I> A; + io::pgm::save(morpho::closing_attribute<A>(lena, c4(), 10000), + "out.pgm"); }