// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) // // This file is part of Olena. // // Olena is free software: you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation, version 2 of the License. // // Olena 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 Olena. If not, see . // // As a special exception, you may use this file as part of a free // software project 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_ACCU_SHAPE_VOLUME_HH # define MLN_ACCU_SHAPE_VOLUME_HH /// \file /// 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 */ # include # include # include # include # include namespace mln { namespace accu { namespace shape { /// \brief Volume accumulator class. /// /// The parameter \p I is the image type on which the accumulator /// of pixels is built. /// /// \ingroup modaccuimages template struct volume : public mln::accu::internal::base< unsigned , volume > { /// 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. /// FIXME: Replaced by mln::morpho::attribute::volume typedef util::pix argument; /// The value type associated to the pixel type. typedef typename argument::value value; volume(); /// Manipulators. /// \{ void init(); void take(const argument& pixel); void take(const volume& other); /// Force the value of the counter to \a v. void set_value(unsigned v); /// \} /// Get the value of the accumulator. unsigned to_result() const; /// Check whether this accu is able to return a result. /// Always true here. bool is_valid() const; protected: /// The reference level (the level of the component's root). value ref_level__; /// The area of the component. unsigned area__; /// The volume of the component. unsigned volume_; }; } // end of mln::accu::shape namespace meta { namespace shape { /// Meta accumulator for volume. struct volume : public Meta_Accumulator< volume > { template struct with { typedef accu::shape::volume ret; }; }; } // end of namespace mln::accu::meta::shape } // end of namespace mln::accu::meta # ifndef MLN_INCLUDE_ONLY namespace shape { template inline volume::volume() { init(); } template inline void volume::init() { ref_level__ = literal::zero; volume_ = 0; area__ = 0; } template inline void volume::take(const argument& pixel) { /* 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& other)'). 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 inline void volume::take(const volume& 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. */ volume_ += other.volume_ + other.area__ * mln::math::diff_abs(other.ref_level__, ref_level__); // Member ref_level__ is not touched. } template inline unsigned volume::to_result() const { return volume_; } template inline void volume::set_value(unsigned v) { volume_ = v; // Reset the other members. ref_level__ = literal::zero; area__ = 0; } template inline bool volume::is_valid() const { return true; } } // end of namespace mln::accu::shape # endif // ! MLN_INCLUDE_ONLY } // end of namespace mln::accu } // end of namespace mln #endif // ! MLN_ACCU_SHAPE_VOLUME_HH