* mln/core/internal/labeled_image_base.hh: New.
* mln/core/image/imorph/labeled_image.hh: Make inherit from labeled_image_base.
--- milena/ChangeLog | 9 + milena/mln/core/image/imorph/labeled_image.hh | 194 +------------- .../labeled_image_base.hh} | 270 +++++++------------- 3 files changed, 118 insertions(+), 355 deletions(-) copy milena/mln/core/{image/imorph/labeled_image.hh => internal/labeled_image_base.hh} (52%)
diff --git a/milena/ChangeLog b/milena/ChangeLog index 811c23e..aa70a1c 100644 --- a/milena/ChangeLog +++ b/milena/ChangeLog @@ -1,5 +1,14 @@ 2009-11-18 Guillaume Lazzara z@lrde.epita.fr
+ Introduce labeled_image_base. + + * mln/core/internal/labeled_image_base.hh: New. + + * mln/core/image/imorph/labeled_image.hh: Make inherit from + labeled_image_base. + +2009-11-18 Guillaume Lazzara z@lrde.epita.fr + Fix invalid macros.
* mln/core/box_runend_piter.hh, diff --git a/milena/mln/core/image/imorph/labeled_image.hh b/milena/mln/core/image/imorph/labeled_image.hh index b0e5ffb..438f6ae 100644 --- a/milena/mln/core/image/imorph/labeled_image.hh +++ b/milena/mln/core/image/imorph/labeled_image.hh @@ -30,35 +30,17 @@ /// /// \brief Definition of a morpher on a labeled image.
-# include <mln/core/image/dmorph/image_if.hh> -# include <mln/core/concept/function.hh> -# include <mln/core/internal/image_identity.hh> -# include <mln/core/site_set/box.hh> -# include <mln/core/routine/duplicate.hh> - -# include <mln/accu/pair.hh> -# include <mln/accu/nil.hh> -# include <mln/accu/center.hh> +# include <mln/core/internal/labeled_image_base.hh>
-# include <mln/labeling/compute.hh> -# include <mln/labeling/pack.hh> -# include <mln/labeling/relabel.hh> +# include <mln/core/routine/duplicate.hh>
# include <mln/util/array.hh>
-# include <mln/pw/cst.hh> -# include <mln/pw/value.hh> - -# ifndef NDEBUG -# include <mln/accu/stat/max.hh> -# include <mln/data/compute.hh> -# endif // ! NDEBUG - - +# include <mln/accu/center.hh> # include <mln/accu/shape/bbox.hh> -# include <mln/labeling/relabel.hh> -# include <mln/make/relabelfun.hh> +# include <mln/accu/stat/max.hh>
+# include <mln/labeling/compute.hh>
namespace mln { @@ -78,14 +60,13 @@ namespace mln /// Data structure for \c mln::labeled_image<I>. template <typename I> struct data< labeled_image<I> > + : data< labeled_image_base<I, labeled_image<I> > > { + typedef data< labeled_image_base<I, labeled_image<I> > > super_; + data(const I& ima, const mln_value(I)& nlabels); data(const I& ima, const mln_value(I)& nlabels, const util::array<mln_box(I)>& bboxes); - - I ima_; - mln_value(I) nlabels_; - mutable util::array< box<mln_psite(I)> > bboxes_; };
} // end of namespace mln::internal @@ -95,19 +76,9 @@ namespace mln {
template <typename I> - struct image_< labeled_image<I> > : image_< I > // Same as I except... + struct image_< labeled_image<I> > + : image_< labeled_image_base<I, labeled_image<I> > > { - // ...these changes. - typedef trait::image::category::identity_morpher category; - typedef mln_internal_trait_image_speed_from(I) speed; // Un-fastest. - typedef trait::image::value_access::indirect value_access; - - typedef trait::image::value_io::read_only value_io; - typedef trait::image::pw_io::read pw_io; - - // extended domain - typedef trait::image::ext_value::multiple ext_value; - typedef trait::image::ext_io::read_only ext_io; };
} // end of namespace mln::trait @@ -128,19 +99,15 @@ namespace mln // template <typename I> class labeled_image - : public internal::image_identity< const I, mln_domain(I), labeled_image<I> > + : public labeled_image_base<I, labeled_image<I> > { - typedef internal::image_identity< const I, mln_domain(I), labeled_image<I> > - super_; + typedef labeled_image_base<I, labeled_image<I> > super_;
public:
/// Skeleton. typedef labeled_image< tag::image_<I> > skeleton;
- /// Type of the bounding component bounding boxes. - typedef mln_result(accu::shape::bbox<mln_psite(I)>) bbox_t; - /// Constructors /// @{ /// Constructor without argument. @@ -162,39 +129,6 @@ namespace mln /// Duplicate the underlying image and create a new labeled_image. void init_from_(const labeled_image<I>& model);
- /// Relabel according to a function. - /// @{ - // - /// Merge or delete labels according to the given function. - /// This method ensures that the labeling remains contiguous. - /// - // FIXME: currently the label is kept contiguous for - // performance reasons. Do we want to be less restrictive? - template <typename F> - void relabel(const Function_v2v<F>& f); - // - /// Labels may be removed. This overload make sure the labeling is still - /// contiguous. - template <typename F> - void relabel(const Function_v2b<F>& f); - /// @} - - /// Return the number of labels; - mln_value(I) nlabels() const; - - /// Update bounding boxes information. - void update_(const fun::i2v::array<mln_value(I)>& relabel_fun); - - /// Return the bounding box of the component \p label. - const bbox_t& bbox(const mln_value(I)& label) const; - - /// Return the component bounding boxes. - const util::array<bbox_t>& bboxes() const; - - /// Return the domain of the component with label \p label. - p_if<mln_box(I), - fun::eq_v2b_expr_<pw::value_<I>, pw::cst_<mln_value(I)> > > - subdomain(const mln_value(I)& label) const; };
@@ -204,7 +138,7 @@ namespace mln // 'labeled_image<I>'. template <typename I, typename J> void init_(tag::image_t, labeled_image<I>& target, - const labeled_image<J>& model); + const labeled_image<J>& model);
@@ -234,7 +168,7 @@ namespace mln template <typename I> inline data< labeled_image<I> >::data(const I& ima, const mln_value(I)& nlabels) - : ima_(ima), nlabels_(nlabels) + : super_(ima, nlabels) { }
@@ -242,7 +176,7 @@ namespace mln inline data< labeled_image<I> >::data(const I& ima, const mln_value(I)& nlabels, const util::array<mln_box(I)>& bboxes) - : ima_(ima), nlabels_(nlabels), bboxes_(bboxes) + : super_(ima, nlabels, bboxes) { }
@@ -296,61 +230,6 @@ namespace mln this->data_->bboxes_ = model.hook_data_()->bboxes_; }
- template <typename I> - template <typename F> - inline - void - labeled_image<I>::relabel(const Function_v2v<F>& f_) - { - const F& f = exact(f_); - mln_value(I) new_nlabels; - - fun::i2v::array<mln_value(I)> - packed_relabel_fun = make::relabelfun(f, - this->data_->nlabels_, - new_nlabels); - - labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_, - packed_relabel_fun); - - this->data_->nlabels_ = new_nlabels; - - /// We may have merged or deleted labels. - update_(packed_relabel_fun); - } - - - - template <typename I> - template <typename F> - inline - void - labeled_image<I>::relabel(const Function_v2b<F>& f_) - { - const F& f = exact(f_); - - // Relabel the underlying image. - typedef fun::i2v::array<mln_value(I)> fv2v_t; - fv2v_t fv2v = make::relabelfun(f, - this->data_->nlabels_, - this->data_->nlabels_); - - labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_, fv2v); - - - // Then, merge or delete bounding boxes according to this relabeling. - update_(fv2v); - } - - template <typename I> - inline - mln_value(I) - labeled_image<I>::nlabels() const - { - return this->data_->nlabels_; - } - - // init_
template <typename I, typename J> @@ -363,49 +242,6 @@ namespace mln }
- template <typename I> - void - labeled_image<I>::update_(const fun::i2v::array<mln_value(I)>& relabel_fun) - { - util::array<accu::shape::bbox<mln_psite(I)> > - new_bboxes(static_cast<unsigned>(this->data_->nlabels_) + 1); - - for (unsigned i = 1; i < this->data_->bboxes_.size(); ++i) - if (relabel_fun(i) != 0) - new_bboxes[relabel_fun(i)].take(this->data_->bboxes_[i]); - - convert::from_to(new_bboxes, this->data_->bboxes_); - - mln_assertion(new_bboxes.size() == this->data_->bboxes_.size()); - } - - - template <typename I> - const typename labeled_image<I>::bbox_t& - labeled_image<I>::bbox(const mln_value(I)& label) const - { - return this->data_->bboxes_[label]; - } - - - template <typename I> - const util::array<typename labeled_image<I>::bbox_t>& - labeled_image<I>::bboxes() const - { - return this->data_->bboxes_; - } - - - template <typename I> - p_if<mln_box(I), - fun::eq_v2b_expr_<pw::value_<I>, pw::cst_<mln_value(I)> > > - labeled_image<I>::subdomain(const mln_value(I)& label) const - { - return ((this->data_->ima_ | bbox(label)) - | (pw::value(this->data_->ima_) == pw::cst(label))).domain(); - } - - // Make routines.
namespace make diff --git a/milena/mln/core/image/imorph/labeled_image.hh b/milena/mln/core/internal/labeled_image_base.hh similarity index 52% copy from milena/mln/core/image/imorph/labeled_image.hh copy to milena/mln/core/internal/labeled_image_base.hh index b0e5ffb..e79bb12 100644 --- a/milena/mln/core/image/imorph/labeled_image.hh +++ b/milena/mln/core/internal/labeled_image_base.hh @@ -23,25 +23,20 @@ // exception does not however invalidate any other reasons why the // executable file might be covered by the GNU General Public License.
-#ifndef MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_HH -# define MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_HH +#ifndef MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_BASE_HH +# define MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_BASE_HH
/// \file /// -/// \brief Definition of a morpher on a labeled image. +/// \brief Definition of a base class for labeled image morphers.
# include <mln/core/image/dmorph/image_if.hh> # include <mln/core/concept/function.hh> # include <mln/core/internal/image_identity.hh> # include <mln/core/site_set/box.hh> -# include <mln/core/routine/duplicate.hh>
-# include <mln/accu/pair.hh> -# include <mln/accu/nil.hh> -# include <mln/accu/center.hh> +# include <mln/accu/shape/bbox.hh>
-# include <mln/labeling/compute.hh> -# include <mln/labeling/pack.hh> # include <mln/labeling/relabel.hh>
# include <mln/util/array.hh> @@ -49,35 +44,23 @@ # include <mln/pw/cst.hh> # include <mln/pw/value.hh>
-# ifndef NDEBUG -# include <mln/accu/stat/max.hh> -# include <mln/data/compute.hh> -# endif // ! NDEBUG - - -# include <mln/accu/shape/bbox.hh> -# include <mln/labeling/relabel.hh> # include <mln/make/relabelfun.hh>
namespace mln {
- // Forward declarations. - template <typename I> struct labeled_image; - namespace accu - { - template <typename T> struct nil; - template <typename T> struct bbox; - } + // Forward declaration. + template <typename I, typename E> + class labeled_image_base;
namespace internal {
- /// Data structure for \c mln::labeled_image<I>. - template <typename I> - struct data< labeled_image<I> > + /// Data structure for \c mln::labeled_image_base<I,E>. + template <typename I, typename E> + struct data< labeled_image_base<I,E> > { data(const I& ima, const mln_value(I)& nlabels); data(const I& ima, const mln_value(I)& nlabels, @@ -91,11 +74,12 @@ namespace mln } // end of namespace mln::internal
+ namespace trait {
- template <typename I> - struct image_< labeled_image<I> > : image_< I > // Same as I except... + template <typename I, typename E> + struct image_< labeled_image_base<I,E> > : image_< I > // Same as I except... { // ...these changes. typedef trait::image::category::identity_morpher category; @@ -114,54 +98,35 @@ namespace mln
- /// Morpher providing an improved interface for labeled image. - /// - /// \tparam I The label image type. - /// - /// This image type allows to access every site set at a given - /// label. - /// - /// This image type guaranties that labels are contiguous (from 1 to - /// n). - /// - /// \ingroup modimageidmorpher - // - template <typename I> - class labeled_image - : public internal::image_identity< const I, mln_domain(I), labeled_image<I> > + /*! \brief Base class Morpher providing an improved interface for + labeled image. + + \tparam I The label image type. + + This image type allows to access every site set at a given + label. + + This image type guaranties that labels are contiguous (from 1 to + n). + + */ + template <typename I, typename E> + class labeled_image_base + : public internal::image_identity< const I, mln_domain(I), E > { - typedef internal::image_identity< const I, mln_domain(I), labeled_image<I> > + typedef internal::image_identity< const I, mln_domain(I), E > super_;
public: - - /// Skeleton. - typedef labeled_image< tag::image_<I> > skeleton; - /// Type of the bounding component bounding boxes. typedef mln_result(accu::shape::bbox<mln_psite(I)>) bbox_t;
/// Constructors /// @{ /// Constructor without argument. - labeled_image(); - - /// Constructor from an image \p ima and the number of labels \p nlabels. - labeled_image(const I& ima, const mln_value(I)& nlabels); - - /// Constructor from an image \p ima, the number of labels \p - /// nlabels and the object bounding boxes. - labeled_image(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes); + labeled_image_base(); /// @}
- /// Deferred initialization from a labeled image \p ima and the number - /// of labels \p nlabels. - void init_(const I& ima, const mln_value(I)& nlabels); - - /// Duplicate the underlying image and create a new labeled_image. - void init_from_(const labeled_image<I>& model); - /// Relabel according to a function. /// @{ // @@ -182,9 +147,6 @@ namespace mln /// Return the number of labels; mln_value(I) nlabels() const;
- /// Update bounding boxes information. - void update_(const fun::i2v::array<mln_value(I)>& relabel_fun); - /// Return the bounding box of the component \p label. const bbox_t& bbox(const mln_value(I)& label) const;
@@ -195,27 +157,19 @@ namespace mln p_if<mln_box(I), fun::eq_v2b_expr_<pw::value_<I>, pw::cst_<mln_value(I)> > > subdomain(const mln_value(I)& label) const; - }; - - - // init_ - - //FIXME: not enough generic? We would like 'J' instead of - // 'labeled_image<I>'. - template <typename I, typename J> - void init_(tag::image_t, labeled_image<I>& target, - const labeled_image<J>& model); -
+ protected: + /// Update bounding boxes information. + void update_data(const fun::i2v::array<mln_value(I)>& relabel_fun);
- namespace make - { + template <typename F> + void relabel_(const Function_v2v<F>& f);
- template <typename I> - mln::labeled_image<I> - labeled_image(const Image<I>& ima, const mln_value(I)& nlabels); + template <typename F> + void relabel_(const Function_v2b<F>& f);
- } // end of namespace mln::make + void update_data_(const fun::i2v::array<mln_value(I)>& relabel_fun); + };
@@ -223,24 +177,24 @@ namespace mln # ifndef MLN_INCLUDE_ONLY
- // internal::data< labeled_image<I> > + // internal::data< labeled_image_base<I,E> >
namespace internal {
- // data< labeled_image<I> > + // data< labeled_image_base<I,E> >
- template <typename I> + template <typename I, typename E> inline - data< labeled_image<I> >::data(const I& ima, const mln_value(I)& nlabels) + data< labeled_image_base<I,E> >::data(const I& ima, const mln_value(I)& nlabels) : ima_(ima), nlabels_(nlabels) { }
- template <typename I> + template <typename I, typename E> inline - data< labeled_image<I> >::data(const I& ima, const mln_value(I)& nlabels, + data< labeled_image_base<I,E> >::data(const I& ima, const mln_value(I)& nlabels, const util::array<mln_box(I)>& bboxes) : ima_(ima), nlabels_(nlabels), bboxes_(bboxes) { @@ -250,57 +204,18 @@ namespace mln } // end of namespace mln::internal
- template <typename I> + template <typename I, typename E> inline - labeled_image<I>::labeled_image() + labeled_image_base<I,E>::labeled_image_base() { }
- template <typename I> - inline - labeled_image<I>::labeled_image(const I& ima, const mln_value(I)& nlabels) - { - init_(ima, nlabels); - }
- template <typename I> - inline - labeled_image<I>::labeled_image(const I& ima, const mln_value(I)& nlabels, - const util::array<mln_box(I)>& bboxes) - { - mln_precondition(data::compute(accu::meta::stat::max(), ima) == nlabels); - this->data_ = new internal::data< labeled_image<I> >(ima, nlabels, bboxes); - } - - - template <typename I> - inline - void - labeled_image<I>::init_(const I& ima, const mln_value(I)& nlabels) - { - mln_precondition(data::compute(accu::meta::stat::max(), ima) == nlabels); - this->data_ = new internal::data< labeled_image<I> >(ima, nlabels); - this->data_->bboxes_ = labeling::compute(accu::meta::shape::bbox(), - this->data_->ima_, - this->data_->nlabels_); - } - - template <typename I> - inline - void - labeled_image<I>::init_from_(const labeled_image<I>& model) - { - this->data_ - = new internal::data< labeled_image<I> >(duplicate(model.hook_data_()->ima_), - model.nlabels()); - this->data_->bboxes_ = model.hook_data_()->bboxes_; - } - - template <typename I> + template <typename I, typename E> template <typename F> inline void - labeled_image<I>::relabel(const Function_v2v<F>& f_) + labeled_image_base<I,E>::relabel(const Function_v2v<F>& f_) { const F& f = exact(f_); mln_value(I) new_nlabels; @@ -315,17 +230,18 @@ namespace mln
this->data_->nlabels_ = new_nlabels;
+ exact(this)->relabel_(f); + /// We may have merged or deleted labels. - update_(packed_relabel_fun); + update_data(packed_relabel_fun); }
- - template <typename I> + template <typename I, typename E> template <typename F> inline void - labeled_image<I>::relabel(const Function_v2b<F>& f_) + labeled_image_base<I,E>::relabel(const Function_v2b<F>& f_) { const F& f = exact(f_);
@@ -337,35 +253,24 @@ namespace mln
labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_, fv2v);
+ exact(this)->relabel_(f);
// Then, merge or delete bounding boxes according to this relabeling. - update_(fv2v); + update_data(fv2v); }
- template <typename I> + template <typename I, typename E> inline mln_value(I) - labeled_image<I>::nlabels() const + labeled_image_base<I,E>::nlabels() const { return this->data_->nlabels_; }
- // init_ - - template <typename I, typename J> - void init_(tag::image_t, labeled_image<I>& target, - const labeled_image<J>& model) - { - I ima; - init_(tag::image, ima, model); - target.init_(ima, model.nlabels()); - } - - - template <typename I> + template <typename I, typename E> void - labeled_image<I>::update_(const fun::i2v::array<mln_value(I)>& relabel_fun) + labeled_image_base<I,E>::update_data(const fun::i2v::array<mln_value(I)>& relabel_fun) { util::array<accu::shape::bbox<mln_psite(I)> > new_bboxes(static_cast<unsigned>(this->data_->nlabels_) + 1); @@ -377,55 +282,68 @@ namespace mln convert::from_to(new_bboxes, this->data_->bboxes_);
mln_assertion(new_bboxes.size() == this->data_->bboxes_.size()); + + exact(this)->update_data_(relabel_fun); }
- template <typename I> - const typename labeled_image<I>::bbox_t& - labeled_image<I>::bbox(const mln_value(I)& label) const + template <typename I, typename E> + const typename labeled_image_base<I,E>::bbox_t& + labeled_image_base<I,E>::bbox(const mln_value(I)& label) const { return this->data_->bboxes_[label]; }
- template <typename I> - const util::array<typename labeled_image<I>::bbox_t>& - labeled_image<I>::bboxes() const + template <typename I, typename E> + const util::array<typename labeled_image_base<I,E>::bbox_t>& + labeled_image_base<I,E>::bboxes() const { return this->data_->bboxes_; }
- template <typename I> + template <typename I, typename E> p_if<mln_box(I), fun::eq_v2b_expr_<pw::value_<I>, pw::cst_<mln_value(I)> > > - labeled_image<I>::subdomain(const mln_value(I)& label) const + labeled_image_base<I,E>::subdomain(const mln_value(I)& label) const { return ((this->data_->ima_ | bbox(label)) | (pw::value(this->data_->ima_) == pw::cst(label))).domain(); }
- // Make routines.
- namespace make + template <typename I, typename E> + template <typename F> + void + labeled_image_base<I,E>::relabel_(const Function_v2v<F>& f) { + (void) f; + // No-Op. + }
- template <typename I> - mln::labeled_image<I> - labeled_image(const Image<I>& ima, const mln_value(I)& nlabels) - { - mln_precondition(exact(ima).is_valid()); - mln::labeled_image<I> tmp(exact(ima), nlabels); - return tmp; - } - - } // end of namespace mln::make + template <typename I, typename E> + template <typename F> + void + labeled_image_base<I,E>::relabel_(const Function_v2b<F>& f) + { + (void) f; + // No-Op. + }
+ template <typename I, typename E> + void + labeled_image_base<I,E>::update_data_( + const fun::i2v::array<mln_value(I)>& relabel_fun) + { + (void) relabel_fun; + // No-Op. + }
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
-#endif // ! MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_HH +#endif // ! MLN_CORE_IMAGE_IMORPH_LABELED_IMAGE_BASE_HH