
--- scribo/ChangeLog | 4 + scribo/core/object_image.hh | 347 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 347 insertions(+), 4 deletions(-) diff --git a/scribo/ChangeLog b/scribo/ChangeLog index 2897a58..a5c7fea 100644 --- a/scribo/ChangeLog +++ b/scribo/ChangeLog @@ -1,5 +1,9 @@ 2009-12-14 Guillaume Lazzara <z@lrde.epita.fr> + * core/object_image.hh: Make use of mln::labeled_image_base. + +2009-12-14 Guillaume Lazzara <z@lrde.epita.fr> + Improve linking routines. * core/anchors.hh: New. Add anchor types. diff --git a/scribo/core/object_image.hh b/scribo/core/object_image.hh index a920680..5eaae67 100644 --- a/scribo/core/object_image.hh +++ b/scribo/core/object_image.hh @@ -28,11 +28,350 @@ /// \file /// -/// FIXME. +/// \brief Definition of a morpher on a labeled image. -# include <mln/core/image/imorph/labeled_image.hh> +# include <mln/core/internal/labeled_image_base.hh> -# define object_image(L) \ - labeled_image<L> +# include <mln/core/routine/duplicate.hh> + +# include <mln/util/array.hh> + +# include <mln/data/compute.hh> + +# include <mln/accu/center.hh> +# include <mln/accu/shape/bbox.hh> +# include <mln/accu/stat/max.hh> + +# include <mln/labeling/compute.hh> + +namespace mln +{ + + // Forward declarations. + template <typename I> struct object_image; + + namespace internal + { + using namespace mln; + + /// Data structure for \c mln::object_image<I>. + template <typename I> + struct data< object_image<I> > + : data< labeled_image_base<I, object_image<I> > > + { + typedef data< labeled_image_base<I, object_image<I> > > super_; + typedef mln_psite(I) ms_t; + typedef mln_result(accu::center<mln_site(I)>) accu_res_t; + + 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, + const util::array<ms_t>& mass_centers); + data(const I& ima, const mln_value(I)& nlabels, + const util::array<mln_box(I)>& bboxes, + const util::array<accu_res_t>& mass_centers); + + mutable util::array<ms_t> mass_centers_; + + util::array<accu::center<mln_psite(I)> > tmp_accus_; + }; + + } // end of namespace mln::internal + + + namespace trait + { + + template <typename I> + struct image_< object_image<I> > + : image_< labeled_image_base< I, object_image<I> > > + { + }; + + } // end of namespace mln::trait + + + + /// 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 object_image + : public mln::labeled_image_base<I, object_image<I> > + { + typedef mln::labeled_image_base<I, object_image<I> > super_; + + public: + + /// Skeleton. + typedef object_image< tag::image_<I> > skeleton; + + /// Mass center type. + typedef typename internal::data< object_image<I> >::ms_t ms_t; + typedef mln_result(accu::center<mln_site(I)>) accu_res_t; + + /// Constructors + /// @{ + /// Constructor without argument. + object_image(); + + /// Constructor from an image \p ima and the number of labels \p nlabels. + object_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. + template <typename P> + object_image(const I& ima, const mln_value(I)& nlabels, + const util::array<mln_box(I)>& bboxes, + const util::array<P>& mass_centers); + /// @} + + /// 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 object_image. + void init_from_(const object_image<I>& model); + + /// Return an array of mass centers. + const util::array<ms_t>& mass_centers() const; + + /// Return the mass center of an object with label \p label. + const mln_psite(I)& mass_center(const mln_value(I)& label) const; + + /// Return the underlying labeled image + const I& labeled_image_() const; + + /// Update mass centers when objects are merged. + void init_update_data_(); + void prepare_update_data_(const mln_value(I)& lbl, + const mln_value(I)& new_lbl); + void update_data_(const fun::i2v::array<mln_value(I)>& relabel_fun); + }; + + + // init_ + + //FIXME: not enough generic? We would like 'J' instead of + // 'object_image<I>'. + template <typename I, typename J> + void init_(tag::image_t, object_image<I>& target, + const object_image<J>& model); + + + + namespace make + { + + template <typename I> + mln::object_image<I> + object_image(const Image<I>& ima, const mln_value(I)& nlabels); + + } // end of namespace mln::make + + + + +# ifndef MLN_INCLUDE_ONLY + + + // internal::data< object_image<I> > + + namespace internal + { + + + // data< object_image<I> > + + template <typename I> + inline + data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels) + : super_(ima, nlabels) + { + } + + template <typename I> + inline + data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels, + const util::array<mln_box(I)>& bboxes, + const util::array<ms_t>& mass_centers) + : super_(ima, nlabels, bboxes), mass_centers_(mass_centers) + { + } + + + template <typename I> + inline + data< object_image<I> >::data(const I& ima, const mln_value(I)& nlabels, + const util::array<mln_box(I)>& bboxes, + const util::array<accu_res_t>& mass_centers) + : super_(ima, nlabels, bboxes) + { + convert::from_to(mass_centers, mass_centers_); + } + + + } // end of namespace mln::internal + + + template <typename I> + inline + object_image<I>::object_image() + { + } + + template <typename I> + inline + object_image<I>::object_image(const I& ima, const mln_value(I)& nlabels) + { + init_(ima, nlabels); + } + + template <typename I> + template <typename P> + inline + object_image<I>::object_image(const I& ima, const mln_value(I)& nlabels, + const util::array<mln_box(I)>& bboxes, + const util::array<P>& mass_centers) + { + mln_precondition(data::compute(accu::meta::stat::max(), ima) == nlabels); + this->data_ = new internal::data< object_image<I> >(ima, nlabels, + bboxes, mass_centers); + } + + + template <typename I> + inline + void + object_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< object_image<I> >(ima, nlabels); + + // FIXME: could be improved! + this->data_->bboxes_ = labeling::compute(accu::meta::shape::bbox(), + this->data_->ima_, + this->data_->nlabels_); + convert::from_to(labeling::compute(accu::meta::center(), + this->data_->ima_, + this->data_->nlabels_), + this->data_->mass_centers_); + } + + + template <typename I> + inline + void + object_image<I>::init_from_(const object_image<I>& model) + { + typedef internal::data< object_image<I> > data_t; + this->data_ + = new data_t(duplicate(model.hook_data_()->ima_), + model.nlabels(), + model.hook_data_()->bboxes_, + model.hook_data_()->mass_centers_); + } + + + template <typename I> + inline + const util::array<typename object_image<I>::ms_t>& + object_image<I>::mass_centers() const + { + return this->data_->mass_centers_; + } + + template <typename I> + inline + const mln_psite(I)& + object_image<I>::mass_center(const mln_value(I)& label) const + { + return this->data_->mass_centers_(label); + } + + + template <typename I> + inline + const I& + object_image<I>::labeled_image_() const + { + return this->data_->ima_; + } + + template <typename I> + inline + void + object_image<I>::init_update_data_() + { + // this->nlabels_ is supposed to be updated when this method is + // called. + this->data_->tmp_accus_.resize(static_cast<unsigned>(this->data_->nlabels_) + 1); + } + + + template <typename I> + inline + void + object_image<I>::prepare_update_data_(const mln_value(I)& lbl, + const mln_value(I)& new_lbl) + { + this->data_->tmp_accus_[new_lbl].take(this->data_->mass_centers_[lbl]); + } + + + template <typename I> + inline + void + object_image<I>::update_data_( + const fun::i2v::array<mln_value(I)>& relabel_fun) + { + (void) relabel_fun; + convert::from_to(this->data_->tmp_accus_, this->data_->mass_centers_); + } + + + // init_ + + template <typename I, typename J> + void init_(tag::image_t, object_image<I>& target, + const object_image<J>& model) + { + I ima; + init_(tag::image, ima, model); + target.init_(ima, model.nlabels()); + } + + + // Make routines. + + namespace make + { + + template <typename I> + mln::object_image<I> + object_image(const Image<I>& ima, const mln_value(I)& nlabels) + { + mln_precondition(exact(ima).is_valid()); + mln::object_image<I> tmp(exact(ima), nlabels); + return tmp; + } + + } // end of namespace mln::make + + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln + +# define object_image(L) mln::object_image<L> #endif // ! SCRIBO_CORE_OBJECT_IMAGE_HH -- 1.5.6.5