* mln/canvas/labeling/blobs.hh: Add a fastest version and make it
support graylevel images.
* mln/labeling/blobs.hh,
* mln/labeling/blobs_and_compute.hh: Add support for graylevel images.
* tests/labeling/blobs.cc,
* tests/labeling/blobs_and_compute.cc: Add a test for graylevel images.
* tests/labeling/Makefile.am: Remove all_blobs target.
* mln/labeling/all_blobs.hh,
* tests/labeling/all_blobs.cc: Remove.
---
milena/ChangeLog | 18 ++++
milena/mln/canvas/labeling/blobs.hh | 136 ++++++++++++++++++++++++++--
milena/mln/labeling/all_blobs.hh | 127 --------------------------
milena/mln/labeling/blobs.hh | 65 ++++++++++----
milena/mln/labeling/blobs_and_compute.hh | 83 +++++++++++++++--
milena/tests/labeling/Makefile.am | 1 -
milena/tests/labeling/all_blobs.cc | 63 -------------
milena/tests/labeling/blobs.cc | 26 +++++-
milena/tests/labeling/blobs_and_compute.cc | 55 ++++++++---
9 files changed, 329 insertions(+), 245 deletions(-)
delete mode 100644 milena/mln/labeling/all_blobs.hh
delete mode 100644 milena/tests/labeling/all_blobs.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 4949cad..1f9c705 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,23 @@
2013-04-18 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Add support for graylevel images in labeling::blobs.
+
+ * mln/canvas/labeling/blobs.hh: Add a fastest version and make it
+ support graylevel images.
+
+ * mln/labeling/blobs.hh,
+ * mln/labeling/blobs_and_compute.hh: Add support for graylevel images.
+
+ * tests/labeling/blobs.cc,
+ * tests/labeling/blobs_and_compute.cc: Add a test for graylevel images.
+
+ * tests/labeling/Makefile.am: Remove all_blobs target.
+
+ * mln/labeling/all_blobs.hh,
+ * tests/labeling/all_blobs.cc: Remove.
+
+2013-04-18 Guillaume Lazzara <z(a)lrde.epita.fr>
+
* mln/core/internal/pixel_impl.hh: Add change_offset().
2013-04-17 Guillaume Lazzara <z(a)lrde.epita.fr>
diff --git a/milena/mln/canvas/labeling/blobs.hh b/milena/mln/canvas/labeling/blobs.hh
index 4a643ce..f913901 100644
--- a/milena/mln/canvas/labeling/blobs.hh
+++ b/milena/mln/canvas/labeling/blobs.hh
@@ -90,9 +90,15 @@ namespace mln
template <typename I, typename N, typename L, typename F>
mln_ch_value(I, L)
- blobs(const Image<I>& input_, const N& nbh, L& nlabels, F&
functor)
+ blobs(const Image<I>& input_, const Neighborhood<N>& nbh_, L&
nlabels, F& functor)
{
+ mln_trace("mln::canvas::labeling::impl::generic::blobs");
+
const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
typedef mln_psite(I) P;
@@ -108,20 +114,24 @@ namespace mln
initialize(output, input);
data::fill(output, zero);
- //extension::fill(input, false);
+ // No initialization needed in border since we look into
+ // the image domain for the neighborhood.
+ //
+ // extension::fill(input, functor.neutral_value()); // <--
functor.neutral_value()
functor.init(); // <-- functor.init()
// Loop.
mln_piter(I) p(input.domain());
for_all(p)
- if (functor.handles(input(p)) && output(p) == zero) // Object point, not
labeled yet.
+ if (functor.handles(input(p)) // <-- functor.handles()
+ && output(p) == zero) // Object point, not labeled yet.
{
// Label this point component.
if (nlabels == mln_max(L))
{
- mln_trace_warning("labeling aborted! Too many labels \
-for this label type: nlabels > max(label_type).");
+ mln_trace_warning("labeling aborted! Too many labels "
+ "for this label type: nlabels > max(label_type).");
return output;
}
@@ -157,10 +167,119 @@ for this label type: nlabels > max(label_type).");
} // end of namespace mln::labeling::impl::generic
+ template <typename I, typename N, typename L, typename F>
+ mln_ch_value(I, L)
+ blobs_fastest(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ L& nlabels, F& functor)
+ {
+ mln_trace("mln::canvas::labeling::impl::blobs_fastest");
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_precondition(input.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ typedef mln_psite(I) P;
+
+ mln_pixter(const I) cur(input);
+ mln_nixter(const I,N) n(cur, nbh);
+ p_queue_fast<unsigned> qu;
+ const L zero = literal::zero;
+
+ // Initialization.
+ nlabels = literal::zero;
+ typedef mln_ch_value(I, L) out_t;
+ out_t output;
+ initialize(output, input);
+ data::fill(output, zero);
+
+ extension::fill(input, functor.neutral_value()); // <-- functor.neutral_value()
+
+ functor.init(); // <-- functor.init()
+
+ // Loop.
+ mln_pixter(const I) p(input);
+ for_all(p)
+ if (functor.handles(p.val()) // <-- functor.handles()
+ && output.element(p.offset()) == zero) // Object point, not labeled yet.
+ {
+ // Label this point component.
+ if (nlabels == mln_max(L))
+ {
+ mln_trace_warning("labeling aborted! Too many labels "
+ "for this label type: nlabels > max(label_type).");
+
+ return output;
+ }
+ ++nlabels;
+ functor.new_label(nlabels); // <-- functor.new_label()
+ mln_invariant(qu.is_empty());
+ qu.push(p.offset());
+ output.element(p.offset()) = nlabels;
+ functor.process_p_(p.offset()); // <-- functor.process_p_()
+ do
+ {
+ cur.change_offset(qu.front());
+ qu.pop();
+ for_all(n)
+ if (p.val() == n.val() && output.element(n.offset()) == zero)
+ {
+ mln_invariant(! qu.compute_has(n.offset()));
+ qu.push(n.offset());
+ output.element(n) = nlabels;
+ functor.process_n_(n.offset()); // <-- functor.process_n_()
+ }
+ }
+ while (! qu.is_empty());
+ }
+
+ functor.finalize(); // <-- functor.finalize()
+
+ return output;
+ }
+
} // end of namespace mln::canvas::labeling::impl
+ // Dispatch
+
+ namespace internal
+ {
+
+ template <typename I, typename N, typename L, typename F>
+ inline
+ mln_ch_value(I, L)
+ blobs_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels, F& functor, mln::trait::image::speed::any)
+ {
+ return impl::generic::blobs(input, nbh, nlabels, functor);
+ }
+
+ template <typename I, typename N, typename L, typename F>
+ inline
+ mln_ch_value(I, L)
+ blobs_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels, F& functor, mln::trait::image::speed::fastest)
+ {
+ return impl::blobs_fastest(input, nbh, nlabels, functor);
+ }
+
+ template <typename I, typename N, typename L, typename F>
+ inline
+ mln_ch_value(I, L)
+ blobs_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels, F& functor)
+ {
+ typedef mln_trait_image_speed(I) speed;
+ return blobs_dispatch(input, nbh, nlabels, functor, speed());
+ }
+
+ } // end of namespace mln::canvas::labeling::internal
+
+
+
// Facade.
template <typename I, typename N, typename L, typename F>
@@ -169,16 +288,15 @@ for this label type: nlabels > max(label_type).");
blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
L& nlabels, F& functor)
{
- mln_trace("labeling::blobs");
- // mlc_equal(mln_trait_image_kind(I),
- // mln::trait::image::kind::binary)::check();
+ mln_trace("mln::canvas::labeling::blobs");
+
const I& input = exact(input_);
const N& nbh = exact(nbh_);
mln_precondition(input.is_valid());
// The only implementation is the generic one.
mln_ch_value(I, L)
- output = impl::generic::blobs(input, nbh, nlabels, functor);
+ output = internal::blobs_dispatch(input, nbh, nlabels, functor);
return output;
}
diff --git a/milena/mln/labeling/all_blobs.hh b/milena/mln/labeling/all_blobs.hh
deleted file mode 100644
index 96e5a09..0000000
--- a/milena/mln/labeling/all_blobs.hh
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (C) 2007, 2008, 2009, 2012, 2013 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 <http://www.gnu.org/licenses/>.
-//
-// 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_LABELING_ALL_BLOBS_HH
-# define MLN_LABELING_ALL_BLOBS_HH
-
-/// \file
-///
-/// Connected component labeling of the homogeneous regions of an
-/// image using a queue-based algorithm.
-///
-/// \todo Handle abort in a nice way...
-
-# include <mln/core/concept/image.hh>
-# include <mln/core/concept/neighborhood.hh>
-
-# include <mln/canvas/labeling/blobs.hh>
-
-
-namespace mln
-{
-
- namespace labeling
- {
-
- /*! \brief Connected component labeling of the homogeneous regions
- * of an image.
-
- \param[in] input The input image.
- \param[in] nbh The connexity of the objects.
- \param[out] nlabels The Number of labels. Its value is set in the
- algorithms.
- \return The label image.
-
- A fast queue is used so that the algorithm is not recursive and
- can handle large objects (blobs).
-
- \ingroup labeling
- */
- template <typename I, typename N, typename L>
- mln_ch_value(I, L)
- all_blobs(const Image<I>& input, const Neighborhood<N>& nbh,
- L& nlabels);
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-
- namespace internal
- {
-
- /*! \brief Functor not computing anything. To be passed to the
- labeling blobs canvas.
- */
- template <typename I, typename L>
- struct label_values_functor
- {
- void init() {}
-
- bool handles(const mln_value(I)&) { return true; }
-
- void new_label(const mln_value(L)&) {}
-
- void process_p(const mln_site(L)&) {}
-
- void process_n(const mln_site(L)&) {}
-
- void finalize() {}
- };
-
- } // end of namespace mln::labeling::internal
-
-
-
- // Facade.
-
- template <typename I, typename N, typename L>
- inline
- mln_ch_value(I, L)
- all_blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
- L& nlabels)
- {
- mln_trace("labeling::all_blobs");
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
- mln_precondition(input.is_valid());
-
- typedef mln_ch_value(I,L) out_t;
- internal::label_values_functor<I, out_t> functor;
- out_t
- output = canvas::labeling::blobs(input, nbh, nlabels, functor);
-
- return output;
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::labeling
-
-} // end of namespace mln
-
-
-#endif // ! MLN_LABELING_ALL_BLOBS_HH
diff --git a/milena/mln/labeling/blobs.hh b/milena/mln/labeling/blobs.hh
index 81073d1..d3c672d 100644
--- a/milena/mln/labeling/blobs.hh
+++ b/milena/mln/labeling/blobs.hh
@@ -33,8 +33,6 @@
/// image using a queue-based algorithm.
///
/// \todo Handle abort in a nice way...
-///
-/// \todo Add a 2nd version precising the 'value' to label.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
@@ -48,27 +46,41 @@ namespace mln
namespace labeling
{
- /*! \brief Connected component labeling of the binary objects of a
- binary image.
+ /*! \brief Connected component labeling of the objects of an
+ * image.
\param[in] input The input image.
\param[in] nbh The connexity of the objects.
\param[out] nlabels The Number of labels. Its value is set in the
algorithms.
- \return The label image.
-
- \pre The input image has to be binary (checked at compile-time).
+ \param[in] background_value The value to be considered as
+ background and not to be labeled.
+ \return A labeled image.
A fast queue is used so that the algorithm is not recursive and
- can handle large binary objects (blobs).
+ can handle large objects (blobs).
\ingroup labeling
*/
template <typename I, typename N, typename L>
mln_ch_value(I, L)
blobs(const Image<I>& input, const Neighborhood<N>& nbh,
- L& nlabels);
+ L& nlabels, const mln_value(I)& background_value);
+
+ /*! \overload
+ \brief Connected component labeling of the objects of an
+ image.
+
+ background_value is set to literal::zero.
+
+ \ingroup labeling
+ */
+ template <typename I, typename N, typename L>
+ inline
+ mln_ch_value(I, L)
+ blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
+ L& nlabels);
# ifndef MLN_INCLUDE_ONLY
@@ -83,11 +95,14 @@ namespace mln
template <typename I, typename L>
struct label_value_functor
{
- label_value_functor(const mln_value(I)& value) : value_(value) {}
+ label_value_functor(const mln_value(I)& background_value)
+ : background_value_(background_value) {}
void init() {}
- bool handles(const mln_value(I)& v) { return v == value_; }
+ mln_value(I) neutral_value() const { return this->background_value_; }
+
+ bool handles(const mln_value(I)& v) const { return v != this->background_value_;
}
void new_label(const mln_value(L)&) {}
@@ -97,7 +112,15 @@ namespace mln
void finalize() {}
- mln_value(I) value_;
+
+ // Fastest interface
+
+ void process_p_(unsigned) {}
+
+ void process_n_(unsigned) {}
+
+
+ mln_value(I) background_value_;
};
} // end of namespace mln::labeling::internal
@@ -110,23 +133,33 @@ namespace mln
inline
mln_ch_value(I, L)
blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
- L& nlabels)
+ L& nlabels, const mln_value(I)& background_value)
{
mln_trace("labeling::blobs");
- mlc_equal(mln_trait_image_kind(I),
- mln::trait::image::kind::binary)::check();
+
const I& input = exact(input_);
const N& nbh = exact(nbh_);
mln_precondition(input.is_valid());
typedef mln_ch_value(I,L) out_t;
- internal::label_value_functor<I, out_t> functor(true);
+ internal::label_value_functor<I, out_t> functor(background_value);
out_t
output = canvas::labeling::blobs(input, nbh, nlabels, functor);
return output;
}
+ template <typename I, typename N, typename L>
+ inline
+ mln_ch_value(I, L)
+ blobs(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels)
+ {
+ return blobs(input, nbh, nlabels,
+ static_cast<mln_value(I)>(literal::zero));
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::labeling
diff --git a/milena/mln/labeling/blobs_and_compute.hh
b/milena/mln/labeling/blobs_and_compute.hh
index f7d2f76..2b7b445 100644
--- a/milena/mln/labeling/blobs_and_compute.hh
+++ b/milena/mln/labeling/blobs_and_compute.hh
@@ -35,7 +35,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
-# include <mln/labeling/blobs.hh>
+# include <mln/canvas/labeling/blobs.hh>
# include <mln/labeling/compute.hh>
# include <mln/util/couple.hh>
@@ -52,6 +52,8 @@ namespace mln
\param[in] nbh A neighborhood used for labeling.
\param[in,out] nlabels The number of labels found.
\param[in] accu An accumulator to be computed while labeling.
+ \param[in] background_value The value to be considered as
+ background and not to be labeled.
\return The labeled image, computed attributes for each regions
and an array of the accumulators used to compute the
@@ -64,8 +66,21 @@ namespace mln
util::couple<util::array<mln_result(A)>,
util::array<A> > >
blobs_and_compute(const Image<I>& input, const Neighborhood<N>&
nbh,
- L& nlabels, const Accumulator<A>& accu);
+ L& nlabels, const Accumulator<A>& accu,
+ const mln_value(I)& background_value);
+ /*! \brief Label an image and compute given accumulators.
+
+ background_value is set to literal::zero.
+
+ \ingroup labeling
+ */
+ template <typename I, typename N, typename L, typename A>
+ util::couple<mln_ch_value(I,L),
+ util::couple<util::array<mln_result(A)>,
+ util::array<A> > >
+ blobs_and_compute(const Image<I>& input, const Neighborhood<N>&
nbh,
+ L& nlabels, const Accumulator<A>& accu);
# ifndef MLN_INCLUDE_ONLY
@@ -87,8 +102,10 @@ namespace mln
typedef util::couple<util::array<accu_result>,
util::array<A> > result;
- compute_functor(const mln_value(L)& nlabels)
- : nlabels_(nlabels)
+ compute_functor(const mln_value(L)& nlabels, const I& input,
+ const mln_value(I)& background_value)
+ : nlabels_(nlabels), input_(input),
+ background_value_(background_value)
{
}
@@ -100,9 +117,15 @@ namespace mln
}
inline
+ mln_value(I) neutral_value() const
+ {
+ return background_value_;
+ }
+
+ inline
bool handles(const mln_value(I)& v)
{
- return v;
+ return v != background_value_;
}
inline
@@ -131,6 +154,21 @@ namespace mln
}
+ // Fastest interface
+
+ inline
+ void process_p_(const unsigned p)
+ {
+ process__(accu_argument(), p);
+ }
+
+ inline
+ void process_n_(const unsigned n)
+ {
+ process__(accu_argument(), n);
+ }
+
+
private:
inline
void process__(const mln_psite(L)&, const mln_site(L)& p)
@@ -144,6 +182,19 @@ namespace mln
accus_[current_lbl_].take(current_lbl_);
}
+ inline
+ void process__(const mln_psite(L)&, const unsigned p)
+ {
+ accus_[current_lbl_].take(input_.point_at_offset(p));
+ }
+
+ inline
+ void process__(const mln_value(L)&, const unsigned)
+ {
+ accus_[current_lbl_].take(current_lbl_);
+ }
+
+
template <typename V>
inline
void process__(const V&, const mln_site(L)&)
@@ -156,6 +207,8 @@ namespace mln
util::array<A> accus_;
mln_value(L) current_lbl_;
mln_value(L) nlabels_;
+ const I input_;
+ mln_value(I) background_value_;
};
} // end of namespace mln::labeling::internal
@@ -170,18 +223,18 @@ namespace mln
util::couple<util::array<mln_result(A)>,
util::array<A> > >
blobs_and_compute(const Image<I>& input, const Neighborhood<N>&
nbh,
- L& nlabels, const Accumulator<A>& accu)
+ L& nlabels, const Accumulator<A>& accu,
+ const mln_value(I)& background_value)
{
mln_trace("labeling::blobs_and_compute");
(void) accu;
- mlc_equal(mln_trait_image_kind(I),
- mln::trait::image::kind::binary)::check();
mln_precondition(exact(input).is_valid());
+ mln_precondition(exact(nbh).is_valid());
typedef mln_ch_value(I,L) out_t;
typedef internal::compute_functor<I,out_t,A> func_t;
- func_t functor(nlabels);
+ func_t functor(nlabels, exact(input), background_value);
out_t
output = canvas::labeling::blobs(input, nbh, nlabels, functor);
@@ -193,6 +246,18 @@ namespace mln
}
+ template <typename I, typename N, typename L, typename A>
+ util::couple<mln_ch_value(I,L),
+ util::couple<util::array<mln_result(A)>,
+ util::array<A> > >
+ blobs_and_compute(const Image<I>& input, const Neighborhood<N>&
nbh,
+ L& nlabels, const Accumulator<A>& accu)
+ {
+ return blobs_and_compute(input, nbh, nlabels, accu,
+ static_cast<mln_value(I)>(literal::zero));
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
diff --git a/milena/tests/labeling/Makefile.am b/milena/tests/labeling/Makefile.am
index 9aa5416..1cabf25 100644
--- a/milena/tests/labeling/Makefile.am
+++ b/milena/tests/labeling/Makefile.am
@@ -22,7 +22,6 @@ EXTRA_DIST = \
check_PROGRAMS = \
- all_blobs \
background \
blobs \
blobs_and_compute \
diff --git a/milena/tests/labeling/all_blobs.cc b/milena/tests/labeling/all_blobs.cc
deleted file mode 100644
index 646227a..0000000
--- a/milena/tests/labeling/all_blobs.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2007, 2008, 2009, 2013 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 <http://www.gnu.org/licenses/>.
-//
-// 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.
-
-#include <mln/core/image/image2d.hh>
-#include <mln/io/pbm/load.hh>
-#include <mln/io/pgm/load.hh>
-#include <mln/core/alias/neighb2d.hh>
-#include <mln/labeling/all_blobs.hh>
-#include <mln/value/int_u8.hh>
-
-#include <mln/labeling/colorize.hh>
-#include <mln/io/ppm/save.hh>
-#include <mln/value/rgb8.hh>
-#include <mln/debug/println.hh>
-
-#include "tests/data.hh"
-
-
-int main()
-{
- using namespace mln;
-
- // Binary image
- {
- image2d<bool> pic;
- io::pbm::load(pic, MLN_IMG_DIR "/picasso.pbm");
- unsigned n;
- labeling::all_blobs(pic, c4(), n);
- mln_assertion(n == 142);
- }
-
- // Gray-level image
- {
- image2d<value::int_u8> pic;
- io::pgm::load(pic, MLN_IMG_DIR "/fly.pgm");
- unsigned n;
- labeling::all_blobs(pic, c4(), n);
- mln_assertion(n == 24);
- }
-}
diff --git a/milena/tests/labeling/blobs.cc b/milena/tests/labeling/blobs.cc
index c3f00bb..9e436b2 100644
--- a/milena/tests/labeling/blobs.cc
+++ b/milena/tests/labeling/blobs.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009, 2013 EPITA Research and Development
+// Laboratory (LRDE)
//
// This file is part of Olena.
//
@@ -25,8 +26,10 @@
#include <mln/core/image/image2d.hh>
#include <mln/io/pbm/load.hh>
+#include <mln/io/pgm/load.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/labeling/blobs.hh>
+#include <mln/value/int_u8.hh>
#include "tests/data.hh"
@@ -35,8 +38,21 @@ int main()
{
using namespace mln;
- image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
- unsigned n;
- labeling::blobs(pic, c4(), n);
- mln_assertion(n == 33);
+ // Binary image
+ {
+ image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ unsigned n;
+ labeling::blobs(pic, c4(), n);
+ mln_assertion(n == 33);
+ }
+
+ // Gray-level image
+ {
+ image2d<value::int_u8> pic;
+ io::pgm::load(pic, MLN_IMG_DIR "/fly.pgm");
+ unsigned n;
+ labeling::blobs(pic, c4(), n);
+
+ mln_assertion(n == 24);
+ }
}
diff --git a/milena/tests/labeling/blobs_and_compute.cc
b/milena/tests/labeling/blobs_and_compute.cc
index 47abd66..66e15c1 100644
--- a/milena/tests/labeling/blobs_and_compute.cc
+++ b/milena/tests/labeling/blobs_and_compute.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2009, 2010, 2011 EPITA Research and Development
+// Copyright (C) 2009, 2010, 2011, 2013 EPITA Research and Development
// Laboratory (LRDE)
//
// This file is part of Olena.
@@ -26,6 +26,7 @@
#include <mln/core/image/image2d.hh>
#include <mln/io/pbm/load.hh>
+#include <mln/io/pgm/load.hh>
#include <mln/core/alias/neighb2d.hh>
#include <mln/accu/center.hh>
#include <mln/labeling/blobs_and_compute.hh>
@@ -40,22 +41,46 @@ int main()
{
using namespace mln;
- image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
- value::label_8 n;
+ {
+ image2d<bool> pic = io::pbm::load(MLN_IMG_DIR "/picasso.pbm");
+ value::label_8 n;
- typedef image2d<value::label_8> L;
- typedef util::array<point2d> arr_t;
- typedef accu::center<point2d,point2d> accu_t;
- typedef util::array<accu_t> accu_arr_t;
- typedef util::couple<L,util::couple<arr_t, accu_arr_t> > res_t;
- res_t result = labeling::blobs_and_compute(pic, c4(), n,
- accu_t());
+ typedef image2d<value::label_8> L;
+ typedef util::array<point2d> arr_t;
+ typedef accu::center<point2d,point2d> accu_t;
+ typedef util::array<accu_t> accu_arr_t;
+ typedef util::couple<L,util::couple<arr_t, accu_arr_t> > res_t;
+ res_t result = labeling::blobs_and_compute(pic, c4(), n,
+ accu_t());
- mln_assertion(result.second().first().size() == 34);
- mln_assertion(result.second().second().size() == 34);
- mln_assertion(result.second().first()[1] == point2d(10,30));
- mln_assertion(result.second().second()[33] == point2d(311,67));
- mln_assertion(n == 33);
+ mln_assertion(result.second().first().size() == 34);
+ mln_assertion(result.second().second().size() == 34);
+ mln_assertion(result.second().first()[1] == point2d(10,30));
+ mln_assertion(result.second().second()[33] == point2d(311,67));
+ mln_assertion(n == 33);
+ }
+
+ {
+ image2d<value::label_8> pic;
+ io::pgm::load(pic, MLN_IMG_DIR "/fly.pgm");
+ value::label_8 n;
+
+
+ typedef image2d<value::label_8> L;
+ typedef util::array<point2d> arr_t;
+ typedef accu::center<point2d,point2d> accu_t;
+ typedef util::array<accu_t> accu_arr_t;
+ typedef util::couple<L,util::couple<arr_t, accu_arr_t> > res_t;
+ res_t result = labeling::blobs_and_compute(pic, c4(), n,
+ accu_t());
+
+ mln_assertion(result.second().first().size() == 25);
+ mln_assertion(result.second().second().size() == 25);
+ mln_assertion(result.second().first()[1] == point2d(0,0));
+ mln_assertion(result.second().second()[24] == point2d(4,4));
+ mln_assertion(n == 24);
+ }
+
}
--
1.7.2.5