* 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(a)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(a)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
--
1.5.6.5