---
milena/ChangeLog | 4 +
milena/mln/core/image/imorph/labeled_image.hh | 110 ++++++++++++++++--------
2 files changed, 77 insertions(+), 37 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6d54e86..6cea6f0 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,9 @@
2009-08-21 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+ * mln/core/image/imorph/labeled_image.hh: Improve relabeling.
+
+2009-08-21 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
+
* mln/labeling/pack.hh: Add new overloads.
2009-08-21 Guillaume Lazzara <lazzara(a)lrde.epita.fr>
diff --git a/milena/mln/core/image/imorph/labeled_image.hh
b/milena/mln/core/image/imorph/labeled_image.hh
index 5672e92..8e27163 100644
--- a/milena/mln/core/image/imorph/labeled_image.hh
+++ b/milena/mln/core/image/imorph/labeled_image.hh
@@ -55,6 +55,11 @@
# endif // ! NDEBUG
+# include <mln/accu/shape/bbox.hh>
+# include <mln/labeling/relabel.hh>
+# include <mln/make/relabelfun.hh>
+
+
namespace mln
{
@@ -75,6 +80,8 @@ namespace mln
struct data< labeled_image<I> >
{
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_;
@@ -141,6 +148,11 @@ namespace mln
/// 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);
/// @}
/// Deferred initialization from a labeled image \p ima and the number
@@ -153,11 +165,11 @@ namespace mln
/// Relabel according to a function.
/// @{
//
- /// Labels may be removed and the labeling may not be contiguous
- /// afterwards.
- /// FIXME: currently the labels are packed after relabeling for
- /// performance reasons. Do we want to be less restrictive?
- /// \sa pack_().
+ /// 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);
//
@@ -167,14 +179,11 @@ namespace mln
void relabel(const Function_v2b<F>& f);
/// @}
- /// Pack labeling. Relabel if the labeling is not contiguous.
- void pack_();
-
/// Return the number of labels;
mln_value(I) nlabels() const;
/// Update bounding boxes information.
- void update_();
+ 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;
@@ -229,6 +238,15 @@ namespace mln
{
}
+ template <typename I>
+ 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)
+ {
+ }
+
+
} // end of namespace mln::internal
@@ -247,12 +265,24 @@ namespace mln
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->update_();
+ this->data_->bboxes_ = labeling::compute(accu::meta::shape::bbox(),
+ this->data_->ima_,
+ this->data_->nlabels_);
}
template <typename I>
@@ -273,18 +303,23 @@ namespace mln
labeled_image<I>::relabel(const Function_v2v<F>& f_)
{
const F& f = exact(f_);
- labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_, 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);
- /// We MUST be sure that the labeling is contiguous in order to compute
- /// attributes.
- ///FIXME: do we want to be less restrictive?
- pack_();
+ this->data_->nlabels_ = new_nlabels;
- /// FIXME: could be highly improved: reorder the attributes according to
- /// the function f.
- this->update_();
+ /// We may have merged or deleted labels.
+ update_(packed_relabel_fun);
}
+
+
template <typename I>
template <typename F>
inline
@@ -292,25 +327,19 @@ namespace mln
labeled_image<I>::relabel(const Function_v2b<F>& f_)
{
const F& f = exact(f_);
- labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_, f);
- /// FIXME: could be highly improved: reorder the attributes according to
- /// the function f.
- this->update_();
- }
+ // 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_);
- template <typename I>
- inline
- void
- labeled_image<I>::pack_()
- {
- labeling::pack_inplace(this->data_->ima_, this->data_->nlabels_);
+ labeling::relabel_inplace(this->data_->ima_, this->data_->nlabels_,
fv2v);
- /// FIXME: could be highly improved: reorder the attributes according to
- /// the way the labels are packed.
- this->update_();
- }
+ // Then, merge or delete bounding boxes according to this relabeling.
+ update_(fv2v);
+ }
template <typename I>
inline
@@ -335,11 +364,18 @@ namespace mln
template <typename I>
void
- labeled_image<I>::update_()
+ labeled_image<I>::update_(const fun::i2v::array<mln_value(I)>&
relabel_fun)
{
- this->data_->bboxes_ = labeling::compute(accu::meta::shape::bbox(),
- this->data_->ima_,
- this->data_->nlabels_);
+ 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());
}
--
1.5.6.5