https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Clean up 'labeling' and fix pbm i/o.
* doc/examples: New directory.
* tests/labeling_blobs.cc: Rename as...
* tests/labeling/blobs.cc: ...this.
* tests/labeling_algo.cc: Rename as...
* doc/examples/labeling_algo.cc: ...this.
* tests/labeling_level_fast.cc: Rename as...
* tests/labeling/level.cc: ...this.
* tests/labeling_regional_maxima.cc: Rename as...
* tests/labeling/regional_maxima.cc: ...this.
* tests/labeling_foreground.cc: Rename as...
* tests/labeling/foreground.cc: ...this.
* tests/labeling_estimate.cc: Remove; meaningless.
* mln/labeling/estimate.hh: Rename as...
* sandbox/geraud/estimate.hh: ...this.
* tests/labeling/background.cc: New.
* tests/labeling/flat_zones.cc: New.
* tests/labeling/regional_minima.cc: New.
* tests/labeling/Makefile.am: Update.
* mln/canvas/labeling.hh,
* mln/labeling/blobs.hh,
* mln/labeling/flat_zones.hh,
* mln/labeling/level.hh,
* mln/labeling/regional_minima.hh,
* mln/labeling/foreground.hh,
* mln/labeling/regional_maxima.hh,
* mln/labeling/background.hh: Clean up.
* mln/labeling/all.hh: Update.
* mln/labeling/base.hh: Remove.
* mln/labeling/level.spe.hh: New.
* tests/value/rgb8.cc: Add comment.
* mln/trait/value/kind.hh: Add comment about tags' hierarchy.
* mln/core/internal/set_of.hh (element): Fix precondition.
* mln/value/rgb.hh (operator metal::vec): New; experimental.
* mln/fun/v2v/saturate.hh: Uncomment.
* mln/io/pbm/save.hh (save_),
* mln/io/pbm/load.hh (load_ascii, load_raw_2d): Swap 0 and 1.
* img/tiny.pgm: Rename as...
* img/small.pgm: ...this.
* img/tiny.pgm: New 16x16 lena reduction.
* img/README: New.
img/README | 8 +
mln/canvas/labeling.hh | 116 +++++++++++++++----------
mln/core/internal/set_of.hh | 2
mln/fun/v2v/saturate.hh | 2
mln/io/pbm/load.hh | 5 -
mln/io/pbm/save.hh | 2
mln/labeling/all.hh | 2
mln/labeling/background.hh | 19 +++-
mln/labeling/blobs.hh | 54 ++++++++---
mln/labeling/flat_zones.hh | 103 +++++++++++++++-------
mln/labeling/foreground.hh | 15 +++
mln/labeling/level.hh | 145 ++++++++++++-------------------
mln/labeling/level.spe.hh | 175 ++++++++++++++++++++++++++++++++++++++
mln/labeling/regional_maxima.hh | 103 +++++++++++++++-------
mln/labeling/regional_minima.hh | 105 +++++++++++++++-------
mln/trait/value/kind.hh | 7 +
mln/value/rgb.hh | 2
sandbox/geraud/estimate.hh | 39 +++++---
tests/labeling/Makefile.am | 19 ++++
tests/labeling/background.cc | 48 ++++++++++
tests/labeling/blobs.cc | 40 +-------
tests/labeling/flat_zones.cc | 65 ++++++++++++++
tests/labeling/foreground.cc | 36 +------
tests/labeling/level.cc | 34 +++----
tests/labeling/regional_maxima.cc | 17 +--
tests/labeling/regional_minima.cc | 52 +++++++++++
tests/value/rgb8.cc | 5 +
27 files changed, 861 insertions(+), 359 deletions(-)
Index: tests/value/rgb8.cc
--- tests/value/rgb8.cc (revision 1598)
+++ tests/value/rgb8.cc (working copy)
@@ -50,6 +50,11 @@
v.blue() = 2;
rgb8 c(0, 1, 2);
+ // FIXME: Do not compile because we lack ops!
+ // mln_sum_(rgb8) sum;
+ // sum + c;
+ // c = c + c;
+
std::cout << c << std::endl;
std::cout << v << std::endl;
Index: tests/labeling/regional_maxima.cc
--- tests/labeling/regional_maxima.cc (revision 1528)
+++ tests/labeling/regional_maxima.cc (working copy)
@@ -25,18 +25,15 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling_regional_maxima.cc
+/*! \file tests/labeling/regional_maxima.cc
*
* \brief Test on mln::labeling::regional_maxima.
*/
#include <mln/core/image2d.hh>
-#include <mln/core/neighb2d.hh>
#include <mln/value/int_u8.hh>
-
+#include <mln/core/neighb2d.hh>
#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
-
#include <mln/labeling/regional_maxima.hh>
@@ -45,13 +42,9 @@
using namespace mln;
using value::int_u8;
- image2d<int_u8>
- lena = io::pgm::load("../img/lena.pgm"),
- out(lena.domain());
+ image2d<int_u8> lena =
io::pgm::load<int_u8>("../../img/tiny.pgm");
unsigned n;
- labeling::regional_maxima(lena, c4(), out, n);
- mln_assertion(n = 255);
-
- io::pgm::save(out, "out.pgm");
+ labeling::regional_maxima(lena, c4(), n);
+ mln_assertion(n = 25);
}
Index: tests/labeling/background.cc
--- tests/labeling/background.cc (revision 0)
+++ tests/labeling/background.cc (revision 0)
@@ -0,0 +1,48 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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 this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library 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.
+
+/*! \file tests/labeling/background.cc
+ *
+ * \brief Test on mln::labeling::background.
+ */
+
+#include <mln/core/image2d.hh>
+#include <mln/io/pbm/load.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/labeling/background.hh>
+#include <mln/logical/not.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ image2d<bool> pic = io::pbm::load("../../img/picasso.pbm");
+ unsigned n;
+ labeling::background(logical::not_(pic), c4(), n);
+ mln_assertion(n = 33);
+}
Index: tests/labeling/blobs.cc
--- tests/labeling/blobs.cc (revision 1528)
+++ tests/labeling/blobs.cc (working copy)
@@ -25,51 +25,23 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling_blob.cc
+/*! \file tests/labeling/blobs.cc
*
- * \brief Test on mln::labeling::blob.
+ * \brief Test on mln::labeling::blobs.
*/
#include <mln/core/image2d.hh>
-#include <mln/core/cast_image.hh>
+#include <mln/io/pbm/load.hh>
#include <mln/core/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/pw/all.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
#include <mln/labeling/blobs.hh>
-#include <mln/level/transform.hh>
-
-
-struct fold_t : public mln::Function_v2v< fold_t >
-{
- typedef mln::value::int_u8 result;
- result operator()(unsigned i) const { return i = 0 ? 0 : i % 255 + 1; }
-};
-
int main()
{
using namespace mln;
- using value::int_u8;
-
- image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm");
+ image2d<bool> pic = io::pbm::load("../../img/picasso.pbm");
unsigned n;
- io::pgm::save(cast_image<int_u8>( labeling::blobs((pw::value(lena) >
pw::cst(127u)) | lena.domain(),
- c4(), n) ),
- "out.pgm");
- mln_assertion(n = 14);
-
-// image2d<int_u8>
-// lena = io::pgm::load("../img/lena.pgm"),
-// out;
-// unsigned n;
-// image2d<unsigned> labels = labeling::blobs((pw::value(lena) >
pw::cst(127u)) | lena.domain(),
-// c8(), n);
-// mln_assertion(n = 528);
-// io::pgm::save( level::transform(labels, fold_t()),
-// "out.pgm" );
+ labeling::blobs(pic, c4(), n);
+ mln_assertion(n = 33);
}
Index: tests/labeling/flat_zones.cc
--- tests/labeling/flat_zones.cc (revision 0)
+++ tests/labeling/flat_zones.cc (revision 0)
@@ -0,0 +1,65 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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 this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library 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.
+
+/*! \file tests/labeling/flat_zones.cc
+ *
+ * \brief Test on mln::labeling::flat_zones.
+ */
+
+#include <mln/core/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/labeling/flat_zones.hh>
+
+#include <mln/labeling/blobs.hh>
+#include <mln/pw/all.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> lena =
io::pgm::load<int_u8>("../../img/tiny.pgm");
+
+ unsigned n;
+ image2d<unsigned> labels = labeling::flat_zones(lena, c4(), n);
+ mln_assertion(n = 247);
+
+ {
+ unsigned n_ = 0;
+ for (unsigned i = 0; i <= 255; ++i)
+ {
+ unsigned n_i;
+ labeling::blobs((pw::value(lena) = pw::cst(i)) | lena.domain(),
+ c4(), n_i);
+ n_ += n_i;
+ }
+ mln_assertion(n_ = n);
+ }
+}
Index: tests/labeling/Makefile.am
--- tests/labeling/Makefile.am (revision 1598)
+++ tests/labeling/Makefile.am (working copy)
@@ -1,3 +1,22 @@
## Process this file through Automake to create Makefile.in -*- Makefile -*-
include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ background \
+ blobs \
+ flat_zones \
+ foreground \
+ level \
+ regional_maxima \
+ regional_minima
+
+background_SOURCES = background.cc
+blobs_SOURCES = blobs.cc
+flat_zones_SOURCES = flat_zones.cc
+foreground_SOURCES = foreground.cc
+level_SOURCES = level.cc
+regional_maxima_SOURCES = regional_maxima.cc
+regional_minima_SOURCES = regional_minima.cc
+
+TESTS = $(check_PROGRAMS)
Index: tests/labeling/level.cc
--- tests/labeling/level.cc (revision 1528)
+++ tests/labeling/level.cc (working copy)
@@ -25,21 +25,23 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling_level_fast.cc
+/*! \file tests/labeling/level.cc
*
* \brief Test on mln::labeling::level.
*/
#include <mln/core/image2d.hh>
-#include <mln/core/image1d.hh>
#include <mln/core/neighb2d.hh>
#include <mln/value/int_u8.hh>
-#include <mln/pw/all.hh>
-
#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
+
+#include <mln/accu/count.hh>
+#include <mln/accu/compute.hh>
#include <mln/labeling/level.hh>
-#include <mln/debug/iota.hh>
+#include <mln/level/paste.hh>
+#include <mln/pw/all.hh>
+#include <mln/core/image_if.hh>
+
#include <mln/debug/println.hh>
@@ -48,15 +50,15 @@
using namespace mln;
using value::int_u8;
- image2d<value::int_u8> i1(5, 5);
- debug::iota(i1);
- i1(point2d(0, 2)) = i1(point2d(1, 2)) = i1(point2d(1, 3)) = i1(point2d(2, 3)) =
i1(point2d(2, 4)) = 2;
- i1(point2d(2, 0)) = i1(point2d(3, 0)) = 2;
- debug::println(i1);
-
- unsigned n;
- image2d<unsigned> out = labeling::level(i1, 2, c4(), n);
+ image2d<int_u8> lena =
io::pgm::load<int_u8>("../../img/tiny.pgm");
+ image2d<bool> lvl(lena.domain());
- std::cout << "n = " << n << std::endl;
- debug::println(out);
+ unsigned n, npixels = 0;
+ for (unsigned l = 0; l <= 255; ++l)
+ {
+ image2d<unsigned> labels = labeling::level(lena, l, c4(), n);
+ unsigned npix = accu::compute< accu::count >(labels | (pw::value(labels) !=
pw::cst(0)));
+ npixels += npix;
+ }
+ mln_assertion(npixels = lena.npoints());
}
Index: tests/labeling/foreground.cc
--- tests/labeling/foreground.cc (revision 1528)
+++ tests/labeling/foreground.cc (working copy)
@@ -25,49 +25,23 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling_foreground.cc
+/*! \file tests/labeling/foreground.cc
*
* \brief Test on mln::labeling::foreground.
*/
#include <mln/core/image2d.hh>
+#include <mln/io/pbm/load.hh>
#include <mln/core/neighb2d.hh>
-#include <mln/value/int_u8.hh>
-#include <mln/pw/all.hh>
-#include <mln/core/cast_image.hh>
-
-#include <mln/io/pgm/load.hh>
-#include <mln/io/pgm/save.hh>
#include <mln/labeling/foreground.hh>
-#include <mln/level/transform.hh>
-
-
-struct fold_t : public mln::Function_v2v< fold_t >
-{
- typedef mln::value::int_u8 result;
- result operator()(unsigned i) const { return i = 0 ? 0 : i % 255 + 1; }
-};
int main()
{
using namespace mln;
- using value::int_u8;
- image2d<int_u8> lena = io::pgm::load("../img/tiny.pgm");
+ image2d<bool> pic = io::pbm::load("../../img/picasso.pbm");
unsigned n;
- io::pgm::save(cast_image<int_u8>( labeling::foreground((pw::value(lena) >
pw::cst(127u)) | lena.domain(),
- c4(), n) ),
- "out.pgm");
- mln_assertion(n = 14);
-
-// image2d<int_u8>
-// lena = io::pgm::load("../img/lena.pgm"),
-// out;
-// unsigned n;
-// image2d<unsigned> labels = labeling::foreground((pw::value(lena) >
pw::cst(127u)) | lena.domain(),
-// c8(), n);
-// mln_assertion(n = 528);
-// io::pgm::save( level::transform(labels, fold_t()),
-// "out.pgm" );
+ labeling::foreground(pic, c4(), n);
+ mln_assertion(n = 33);
}
Index: tests/labeling/regional_minima.cc
--- tests/labeling/regional_minima.cc (revision 0)
+++ tests/labeling/regional_minima.cc (revision 0)
@@ -0,0 +1,52 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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 this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library 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.
+
+/*! \file tests/labeling/regional_minima.cc
+ *
+ * \brief Test on mln::labeling::regional_minima.
+ */
+
+#include <mln/core/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/pw/all.hh>
+#include <mln/labeling/regional_minima.hh>
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+ image2d<int_u8> lena =
io::pgm::load<int_u8>("../../img/tiny.pgm");
+
+ unsigned n;
+ labeling::regional_minima((pw::cst(255) - pw::value(lena)) | lena.domain(),
+ c4(), n);
+ mln_assertion(n = 25);
+}
Index: mln/trait/value/kind.hh
--- mln/trait/value/kind.hh (revision 1598)
+++ mln/trait/value/kind.hh (working copy)
@@ -56,6 +56,13 @@
struct logic : label { std::string name() const { return "kind::logic"; } };
struct binary : logic { std::string name() const { return "kind::binary"; }
};
+ // FIXME: Why not?
+ // label logic
+ // \ / \
+ // \ nary_logic \
+ // \ / \ \
+ // binary ternary fuzzy
+
struct data : any { std::string name() const { return "kind::data"; } };
};
Index: mln/core/internal/set_of.hh
--- mln/core/internal/set_of.hh (revision 1598)
+++ mln/core/internal/set_of.hh (working copy)
@@ -224,9 +224,9 @@
const E&
set_of_<E>::element(unsigned i) const
{
- assert(i < v_.size());
if (needs_update_)
update_();
+ mln_precondition(i < v_.size());
return v_[i];
}
Index: mln/value/rgb.hh
--- mln/value/rgb.hh (revision 1598)
+++ mln/value/rgb.hh (working copy)
@@ -125,6 +125,8 @@
rgb<n>(const metal::vec<3, unsigned>& rhs);
rgb<n>(const metal::vec<3, int_u<n> >& rhs);
+ operator metal::vec<3, float>() const { return this->v_; }
+
/// \{ Constructors with literals.
rgb<n>(const literal::white_t&);
rgb<n>(const literal::black_t&);
Index: mln/fun/v2v/saturate.hh
--- mln/fun/v2v/saturate.hh (revision 1598)
+++ mln/fun/v2v/saturate.hh (working copy)
@@ -102,7 +102,7 @@
min_W = mln::value::cast<W>(min_);
max_W = mln::value::cast<W>(max_);
// FIXME
-// needs_update_ = false;
+ needs_update_ = false;
}
// FIXME: Below we need something more powerful that mlc_converts_to
Index: mln/io/pbm/save.hh
--- mln/io/pbm/save.hh (revision 1598)
+++ mln/io/pbm/save.hh (working copy)
@@ -95,7 +95,7 @@
for_all(p)
{
c <<= 1;
- c += (ima(p) = true ? 1 : 0); // FIXME: Swap.
+ c += (ima(p) = true ? 0 : 1); // In pbm, '0' means 'white' so
'object', thus 'true'!
if (++col >= ncols)
{
c <<= (8 - stride - 1);
Index: mln/io/pbm/load.hh
--- mln/io/pbm/load.hh (revision 1598)
+++ mln/io/pbm/load.hh (working copy)
@@ -87,7 +87,8 @@
{
unsigned value;
file >> value;
- ima(p) = value;
+ mln_assertion(value = 0 || value = 1);
+ ima(p) = (value = 0); // In pbm, '0' means 'white' so
'object', thus 'true'!
// FIXME: Test alt code below.
// file >> ima(p);
}
@@ -116,7 +117,7 @@
{
if (i % 8 = 0)
file.read((char*)(&c), 1);
- ima(p) = c & 128;
+ ima(p) = !(c & 128);
c *= 2;
++i;
}
Index: mln/canvas/labeling.hh
--- mln/canvas/labeling.hh (revision 1598)
+++ mln/canvas/labeling.hh (working copy)
@@ -34,9 +34,9 @@
* image.
*/
+# include <mln/core/concept/image.hh>
# include <mln/level/fill.hh>
-# include <mln/level/sort_points.hh>
-# include <mln/convert/to_window.hh>
+# include <mln/convert/to_window.hh> // FIXME: to_upper_window
namespace mln
@@ -50,35 +50,52 @@
template <typename F>
struct labeling
{
+ // Functor.
F& f;
typedef typename F::I I;
typedef typename F::N N;
- typedef typename F::O O;
+ typedef typename F::L L;
typedef typename F::S S;
- typedef mln_point(I) point;
- // aux:
- mln_ch_value(O, bool) deja_vu;
- mln_ch_value(O, point) parent;
+ // Local type.
+ typedef mln_psite(I) point;
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+
+ // Output.
+ mln_ch_value(I, L) output;
+ L nlabels;
+ bool status;
+
+ // Ctor.
labeling(F& f)
: f(f)
{
- run();
+ trace::entering("canvas::labeling");
+
+ init();
+ f.init(); // Client initialization.
+ pass_1();
+ pass_2();
+
+ trace::exiting("canvas::labeling");
}
- void run()
- {
- // init
+
+ void init()
{
initialize(deja_vu, f.input);
mln::level::fill(deja_vu, false);
initialize(parent, f.input);
- f.nlabels = 0;
- f.init();
+ initialize(output, f.input);
+ mln::level::fill(output, 0); // FIXME: Use literal::zero.
+ nlabels = 0;
}
- // first pass
+
+ void pass_1()
{
mln_fwd_piter(S) p(f.s);
mln_niter(N) n(f.nbh, p);
@@ -95,7 +112,7 @@
}
}
- // second pass
+ void pass_2()
{
mln_bkd_piter(S) p(f.s);
for_all(p) if (f.handles(p))
@@ -104,21 +121,22 @@
{
if (f.labels(p))
{
- if (f.nlabels = mln_max(mln_value(O)))
+ if (nlabels = mln_max(L))
{
- f.status = false;
+ status = false;
return;
}
- f.output(p) = ++f.nlabels;
+ output(p) = ++nlabels;
}
}
else
- f.output(p) = f.output(parent(p));
+ output(p) = output(parent(p));
}
- f.status = true;
+ status = true;
}
- } // end of run()
+
+ // Auxiliary methods.
void make_set(const point& p)
{
@@ -152,41 +170,52 @@
};
- // FIXME: Fast version.
template <typename F>
- struct labeling_fast
+ struct labeling_fastest
{
+ // Functor.
F& f;
typedef typename F::I I;
typedef typename F::N N;
- typedef typename F::O O;
+ typedef typename F::L L;
+
+ // Auxiliary data.
+ mln_ch_value(I, unsigned) parent;
- // aux:
- mln_ch_value(O, unsigned) parent;
+ // Output.
+ mln_ch_value(I, L) output;
+ L nlabels;
+ bool status;
- labeling_fast(F& f)
+ // Ctor.
+ labeling_fastest(F& f)
: f(f)
{
- run();
+ trace::entering("canvas::labeling_fastest");
+
+ init();
+ f.init(); // Client initialization.
+ pass_1();
+ pass_2();
+
+ trace::exiting("canvas::labeling_fastest");
}
- void run()
- {
- // init
+ void init()
{
initialize(parent, f.input);
- f.nlabels = 0;
- f.init();
- // make_set for all points:
for (unsigned p = 0; p < parent.ncells(); ++p)
- parent[p] = p;
+ parent[p] = p; // make_set
+ initialize(output, f.input);
+ mln::level::fill(output, 0); // FIXME: Use literal::zero.
+ nlabels = 0;
}
- // first pass
+ void pass_1()
{
mln_bkd_pixter(const I) p(f.input);
@@ -205,30 +234,31 @@
}
}
- // second pass
+ void pass_2()
{
mln_fwd_pixter(const I) p(f.input);
+
for_all(p) if (f.handles(p))
{
if (is_root(p))
{
if (f.labels(p))
{
- if (f.nlabels = mln_max(mln_value(O)))
+ if (nlabels = mln_max(L))
{
- f.status = false;
+ status = false;
return;
}
- f.output[p] = ++f.nlabels;
+ output[p] = ++nlabels;
}
}
else
- f.output[p] = f.output[parent[p]];
+ output[p] = output[parent[p]];
}
- f.status = true;
+ status = true;
}
- } // end of run()
+ // Auxiliary methods.
bool is_root(unsigned p) const
{
Index: mln/labeling/blobs.hh
--- mln/labeling/blobs.hh (revision 1598)
+++ mln/labeling/blobs.hh (working copy)
@@ -30,8 +30,8 @@
/*! \file mln/labeling/blobs.hh
*
- * \brief Connected component labeling of the image objects at a given
- * blobs.
+ * \brief Connected component labeling of the binary objects of a binary
+ * image using a queue-based algorithm.
*/
# include <mln/core/concept/image.hh>
@@ -55,6 +55,8 @@
* \param[out] nlabels The number of labels.
* \return The label image.
*
+ * \pre The input image has to be binary (checked at compile-time).
+ *
* A fast queue is used so that the algorithm is not recursive and
* can handle large binary objects (blobs).
*/
@@ -69,22 +71,13 @@
namespace impl
{
- // ...
-
- } // end of namespace mln::labeling::impl
-
-
- // Facade.
+ namespace generic
+ {
template <typename I, typename N>
- inline
mln_ch_value(I, unsigned)
- blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
unsigned& nlabels)
+ blobs_(const I& input, const N& nbh, unsigned& nlabels)
{
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
- mln_precondition(input.has_data());
-
typedef mln_psite(I) P;
P cur;
@@ -125,6 +118,39 @@
return output;
}
+ } // end of namespace mln::labeling::impl::generic
+
+
+ template <typename I, typename N>
+ mln_ch_value(I, unsigned)
+ blobs_(const I& input, const N& nbh, unsigned& nlabels)
+ {
+ // The only implementation is the generic one.
+ return generic::blobs_(input, nbh, nlabels);
+ }
+
+ } // end of namespace mln::labeling::impl
+
+
+ // Facade.
+
+ template <typename I, typename N>
+ inline
+ mln_ch_value(I, unsigned)
+ blobs(const Image<I>& input_, const Neighborhood<N>& nbh_,
unsigned& nlabels)
+ {
+ trace::entering("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.has_data());
+
+ mln_ch_value(I, unsigned) output = impl::blobs_(input, nbh, nlabels);
+
+ trace::exiting("labeling::blobs");
+ return output;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::labeling
Index: mln/labeling/flat_zones.hh
--- mln/labeling/flat_zones.hh (revision 1598)
+++ mln/labeling/flat_zones.hh (working copy)
@@ -33,7 +33,9 @@
* \brief Connected component labeling of the flat zones of an image.
*/
-# include <mln/labeling/base.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/canvas/labeling.hh>
namespace mln
@@ -46,15 +48,14 @@
*
* \param[in] input The input image.
* \param[in] nbh The neighborhood to consider.
- * \param[out] output The label image.
* \param[out] nlabels The number of labels.
- *
- * \return The number of labels.
+ * \return The label image.
*/
- template <typename I, typename N, typename O>
- bool flat_zones(const Image<I>& input, const Neighborhood<N>&
nbh,
- Image<O>& output,
- unsigned& nlabels);
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ flat_zones(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels);
+
# ifndef MLN_INCLUDE_ONLY
@@ -62,47 +63,87 @@
namespace impl
{
- template <typename I_, typename N_, typename O_>
- struct flat_zones_ : base_<I_,N_,O_>
+ // Flat zone functor for the labeling canvas.
+
+ template <typename I_, typename N_, typename L_>
+ struct flat_zones_functor
{
- typedef mln_point(I_) P;
+ typedef mln_psite(I_) P;
// requirements from mln::canvas::labeling:
- typedef mln_pset(I_) S;
+ typedef I_ I;
+ typedef N_ N;
+ typedef L_ L;
+ typedef mln_pset(I) S;
+
+ const I& input;
+ const N& nbh;
const S& s;
- mln_value(O) nlabels;
- bool status;
- inline
- bool equiv(const P& n, const P&) const { return input(n) = input(p); }
+ bool handles(const P&) const { return true; }
+ bool equiv(const P& n, const P& p) const { return input(n) = input(p); }
+
+ void init() {}
+ bool labels(const P&) const { return true; }
+ void do_no_union(const P&, const P&) {}
+ void init_attr(const P&) {}
+ void merge_attr(const P&, const P&) {}
// end of requirements
- inline
- flat_zones_(const I_& input, const N_& nbh, O_& output)
- : base_<I_,N_,O_>(input, nbh, output),
+ flat_zones_functor(const I_& input, const N_& nbh)
+ : input(input),
+ nbh(nbh),
s(input.domain())
{}
};
+
+ // Generic implementation.
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ flat_zones_(const I& input, const N& nbh, L& nlabels)
+ {
+ trace::entering("labeling::impl::generic::flat_zones_");
+
+ typedef flat_zones_functor<I,N,L> F;
+ F f(input, nbh);
+ canvas::labeling<F> run(f);
+ nlabels = run.nlabels;
+
+ trace::exiting("labeling::impl::generic::flat_zones_");
+ return run.output;
+ }
+
+ } // end of namespace mln::labeling::impl::generic
+
+
} // end of namespace mln::labeling::impl
+
// Facade.
- template <typename I, typename N, typename O>
- inline
- bool flat_zones(const Image<I>& input, const Neighborhood<N>&
nbh,
- Image<O>& output,
- unsigned& nlabels)
- {
- mln_precondition(exact(output).domain() = exact(input).domain());
- typedef impl::flat_zones_<I,N,O> F;
- F f(exact(input), exact(nbh), exact(output));
- canvas::labeling<F> run(f);
- nlabels = f.nlabels;
- return f.status;
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ flat_zones(const Image<I>& input_, const Neighborhood<N>&
nbh_,
+ L& nlabels)
+ {
+ trace::entering("labeling::flat_zones");
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(input.has_data());
+
+ // Calls the only (generic) impl.
+ mln_ch_value(I, L) output = impl::generic::flat_zones_(input, nbh, nlabels);
+
+ trace::exiting("labeling::flat_zones");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/labeling/level.hh
--- mln/labeling/level.hh (revision 1598)
+++ mln/labeling/level.hh (working copy)
@@ -35,10 +35,12 @@
*/
# include <mln/core/concept/image.hh>
-# include <mln/labeling/base.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/canvas/labeling.hh>
# include <mln/level/fill.hh>
-# include <mln/border/adjust.hh>
-# include <mln/value/other.hh>
+
+// The 'fastest' specialization is in:
+# include <mln/labeling/level.spe.hh>
@@ -57,10 +59,11 @@
* \param[out] nlabels The number of labels.
* \return The label image.
*/
- template <typename I, typename N>
- mln_ch_value(I, unsigned)
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
level(const Image<I>& input, const mln_value(I)& val, const
Neighborhood<N>& nbh,
- unsigned& nlabels);
+ L& nlabels);
+
# ifndef MLN_INCLUDE_ONLY
@@ -68,125 +71,91 @@
namespace impl
{
- // Functors.
+ // Generic functor.
- template <typename I_, typename N_, typename O_>
- struct level_t : base_<I_,N_,O_>
+ template <typename I_, typename N_, typename L_>
+ struct level_functor
{
- typedef mln_point(I_) P;
+ typedef mln_psite(I_) P;
// requirements from mln::canvas::labeling:
- typedef mln_pset(I_) S;
+ typedef I_ I;
+ typedef N_ N;
+ typedef L_ L;
+ typedef mln_pset(I) S;
+
+ const I& input;
+ const N& nbh;
const S& s;
- inline
- void init() { mln::level::fill(this->output, 0); } //
FIXME: use literal::zero
- inline
bool handles(const P& p) const { return input(p) = val; }
- inline
bool equiv(const P& n, const P&) const { return input(n) = val; }
+ void init() {}
+ bool labels(const P&) const { return true; }
+ void do_no_union(const P&, const P&) {}
+ void init_attr(const P&) {}
+ void merge_attr(const P&, const P&) {}
+
// end of requirements
const mln_value(I_)& val;
- inline
- level_t(const I_& input, const mln_value(I_)& val, const N_& nbh, O_&
output)
- : base_<I_,N_,O_>(input, nbh, output),
+ level_functor(const I_& input, const mln_value(I_)& val, const N_& nbh)
+ : input(input),
+ nbh(nbh),
s(input.domain()),
val(val)
{}
};
- // Routines.
- template <typename I, typename N>
- inline
- mln_ch_value(I, unsigned)
- level_(trait::image::speed::any, const I& input,
- const mln_value(I)& val, const Neighborhood<N>& nbh,
- unsigned& nlabels)
- {
- typedef mln_ch_value(I, unsigned) O;
- O output;
- initialize(output, input);
+ // Generic implementation.
- typedef impl::level_t<I,N,O> F;
- F f(input, val, exact(nbh), output);
- canvas::labeling<F> run(f);
-
- nlabels = f.nlabels;
- // FIXME: Handle f.status
- return output;
- }
-
- // FIXME: Add fast versions.
-
- template <typename I_, typename N_, typename O_>
- struct level_fast_t : labeling::impl::base_fast_<I_,N_,O_>
+ namespace generic
{
- typedef mln_point(I_) P;
-
- // typedef mln_pset(I_) S;
- // const S& s;
-
- inline
- void init() { mln::level::fill(this->output, 0); }
- inline
- bool handles(unsigned p) const { return this->input[p] = val; }
- inline
- bool equiv(unsigned n, unsigned) const { return this->input[n] = val; }
-
- const mln_value(I_)& val;
- inline
- level_fast_t(const I_& input, const mln_value(I_)& val, const N_& nbh,
O_& output)
- : labeling::impl::base_fast_<I_,N_,O_>(input, nbh, output),
- // s(input.domain()),
- val(val)
- {}
- };
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level_(const I& input, const mln_value(I)& val, const N& nbh,
+ L& nlabels)
+ {
+ trace::entering("labeling::impl::generic::level_");
+ typedef level_functor<I,N,L> F;
+ F f(input, val, nbh);
+ canvas::labeling<F> run(f);
- template <typename I, typename N>
- inline
- mln_ch_value(I, unsigned)
- level_(trait::image::speed::fastest, const I& input,
- const mln_value(I)& val, const Neighborhood<N>& nbh,
- unsigned& nlabels)
- {
- typedef mln_ch_value(I, unsigned) O;
- typedef level_fast_t<I,N,O> F;
-
- border::adjust(input, exact(nbh).delta());
- O output;
- initialize(output, input);
- mln_assertion(output.border() = input.border());
+ nlabels = run.nlabels;
+ // FIXME: Handle run.status
- F f(input, val, exact(nbh), output);
- canvas::labeling_fast<F> run(f);
+ trace::exiting("labeling::impl::generic::level_");
+ return run.output;
+ }
- // FIXME: Handle f.status
+ } // end of namespace mln::labeling::impl::generic
- nlabels = f.nlabels;
- return output;
- }
} // end of namespace mln::labeling::impl
+
// Facade.
- template <typename I, typename N>
- inline
- mln_ch_value(I, unsigned)
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
level(const Image<I>& input, const mln_value(I)& val, const
Neighborhood<N>& nbh,
- unsigned& nlabels)
+ L& nlabels)
{
+ trace::entering("labeling::level");
mln_precondition(exact(input).has_data());
- return impl::level_(mln_trait_image_speed(I)(), exact(input),
- val, nbh, nlabels);
+
+ mln_ch_value(I, L) output = impl::level_(mln_trait_image_speed(I)(),
+ exact(input), val, exact(nbh), nlabels);
+
+ trace::exiting("labeling::level");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/labeling/all.hh
--- mln/labeling/all.hh (revision 1598)
+++ mln/labeling/all.hh (working copy)
@@ -47,7 +47,7 @@
}
# include <mln/labeling/background.hh>
-# include <mln/labeling/base.hh>
+# include <mln/labeling/blobs.hh>
# include <mln/labeling/estimate.hh>
# include <mln/labeling/flat_zones.hh>
# include <mln/labeling/foreground.hh>
Index: mln/labeling/regional_minima.hh
--- mln/labeling/regional_minima.hh (revision 1598)
+++ mln/labeling/regional_minima.hh (working copy)
@@ -34,7 +34,10 @@
* image.
*/
-# include <mln/labeling/base.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/canvas/labeling.hh>
+# include <mln/level/fill.hh>
# include <mln/level/sort_points.hh>
@@ -49,14 +52,14 @@
*
* \param[in] input The input image.
* \param[in] nbh The neighborhood to consider.
- * \param[out] output The label image.
- * \param[out] nlabels The number of labels.
+ * \param[out] nlabels The number of labeled regions.
+ * \return The label image.
*
- * \return The number of labels.
*/
- template <typename I, typename N, typename O>
- bool regional_minima(const Image<I>& input, const
Neighborhood<N>& nbh,
- Image<O>& output, unsigned& nlabels);
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_minima(const Image<I>& input, const Neighborhood<N>&
nbh,
+ L& nlabels);
@@ -65,58 +68,92 @@
namespace impl
{
- template <typename I_, typename N_, typename O_>
- struct regional_minima_ : base_<I_,N_,O_>
+ // Generic functor.
+
+ template <typename I_, typename N_, typename L_>
+ struct regional_minima_functor
{
- typedef mln_point(I_) P;
+ typedef mln_psite(I_) P;
// requirements from mln::canvas::labeling:
+ typedef I_ I;
+ typedef N_ N;
+ typedef L_ L;
typedef p_array<P> S;
+
+ const I& input;
+ const N& nbh;
S s;
- inline
- void init() { mln::level::fill(this->output, 0);
- level::fill(attr, true); }
- inline
+ void init() { level::fill(attr, true); }
+ bool handles(const P&) const { return true; }
bool labels(const P& p) const { return attr(p); }
- inline
bool equiv(const P& n, const P& p) const { return input(n) = input(p); }
- inline
void do_no_union(const P& n, const P& p) { mln_invariant(input(n) <
input(p));
attr(p) = false; }
- inline
+ void init_attr(const P&) {}
void merge_attr(const P& r, const P& p) { attr(p) = attr(p) && attr(r);
}
// end of requirements
- mln_ch_value(O_, bool) attr;
+ mln_ch_value(I, bool) attr;
- inline
- regional_minima_(const I_& input, const N_& nbh, O_& output)
- : base_<I_,N_,O_>(input, nbh, output),
- s(level::sort_points_increasing(input)),
- attr(output.domain())
+ regional_minima_functor(const I_& input, const N_& nbh)
+ : input(input),
+ nbh(nbh),
+ s(level::sort_points_increasing(input)), // FIXME: sort_psites_increasing
+ attr(input.domain())
{
}
};
+
+ // Generic implementation.
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_minima_(const I& input, const N& nbh,
+ L& nlabels)
+ {
+ trace::entering("labeling::impl::generic::regional_minima_");
+
+ typedef impl::regional_minima_functor<I,N,L> F;
+ F f(input, nbh);
+ canvas::labeling<F> run(f);
+ nlabels = run.nlabels;
+
+ trace::exiting("labeling::impl::generic::regional_minima_");
+ return run.output;
+ }
+
+ } // end of namespace mln::labeling::impl::generic
+
+
} // end of namespace mln::labeling::impl
+
// Facade.
- template <typename I, typename N, typename O>
- inline
- bool regional_minima(const Image<I>& input, const
Neighborhood<N>& nbh,
- Image<O>& output, unsigned& nlabels)
- {
- mln_precondition(exact(output).domain() = exact(input).domain());
- typedef impl::regional_minima_<I,N,O> F;
- F f(exact(input), exact(nbh), exact(output));
- canvas::labeling<F> run(f);
- nlabels = f.nlabels;
- return f.status;
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_minima(const Image<I>& input_, const Neighborhood<N>&
nbh_,
+ L& nlabels)
+ {
+ trace::entering("labeling::regional_minima");
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(input.has_data());
+
+ // Calls the only (generic) impl.
+ mln_ch_value(I, L) output = impl::generic::regional_minima_(input, nbh, nlabels);
+
+ trace::exiting("labeling::regional_minima");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/labeling/foreground.hh
--- mln/labeling/foreground.hh (revision 1598)
+++ mln/labeling/foreground.hh (working copy)
@@ -50,6 +50,13 @@
* \param[in] nbh The neighborhood to consider.
* \param[out] nlabels The number of labels.
* \return The label image.
+ *
+ * \pre The input image has to be binary (checked at compile-time).
+ *
+ * This routine actually calls mln::labeling::level with the level
+ * value set to \c true.
+ *
+ * \see mln::labeling::level
*/
template <typename I, typename N>
mln_ch_value(I, unsigned)
@@ -65,8 +72,14 @@
foreground(const Image<I>& input, const Neighborhood<N>& nbh,
unsigned& nlabels)
{
+ trace::entering("labeling::foreground");
+ mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check();
mln_precondition(exact(input).has_data());
- return labeling::level(input, true, nbh, nlabels);
+
+ mln_ch_value(I, unsigned) output = labeling::level(input, true, nbh, nlabels);
+
+ trace::exiting("labeling::foreground");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/labeling/regional_maxima.hh
--- mln/labeling/regional_maxima.hh (revision 1598)
+++ mln/labeling/regional_maxima.hh (working copy)
@@ -34,7 +34,10 @@
* image.
*/
-# include <mln/labeling/base.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/canvas/labeling.hh>
+# include <mln/level/fill.hh>
# include <mln/level/sort_points.hh>
@@ -49,14 +52,14 @@
*
* \param[in] input The input image.
* \param[in] nbh The neighborhood to consider.
- * \param[out] output The label image.
* \param[out] nlabels The number of labeled regions.
+ * \return The label image.
*
- * \return The number of labels.
*/
- template <typename I, typename N, typename O>
- bool regional_maxima(const Image<I>& input, const
Neighborhood<N>& nbh,
- Image<O>& output, unsigned& nlabels);
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_maxima(const Image<I>& input, const Neighborhood<N>&
nbh,
+ L& nlabels);
@@ -65,58 +68,92 @@
namespace impl
{
- template <typename I_, typename N_, typename O_>
- struct regional_maxima_ : base_<I_,N_,O_>
+ // Generic functor.
+
+ template <typename I_, typename N_, typename L_>
+ struct regional_maxima_functor
{
- typedef mln_point(I_) P;
+ typedef mln_psite(I_) P;
// requirements from mln::canvas::labeling:
+ typedef I_ I;
+ typedef N_ N;
+ typedef L_ L;
typedef p_array<P> S;
+
+ const I& input;
+ const N& nbh;
S s;
- inline
- void init() { mln::level::fill(this->output, 0);
- level::fill(attr, true); }
- inline
+ void init() { level::fill(attr, true); }
+ bool handles(const P&) const { return true; }
bool labels(const P& p) const { return attr(p); }
- inline
bool equiv(const P& n, const P& p) const { return input(n) = input(p); }
- inline
void do_no_union(const P& n, const P& p) { mln_invariant(input(n) >
input(p));
attr(p) = false; }
- inline
+ void init_attr(const P&) {}
void merge_attr(const P& r, const P& p) { attr(p) = attr(p) && attr(r);
}
// end of requirements
- mln_ch_value(O_, bool) attr;
+ mln_ch_value(I, bool) attr;
- inline
- regional_maxima_(const I_& input, const N_& nbh, O_& output)
- : base_<I_,N_,O_>(input, nbh, output),
- s(level::sort_points_decreasing(input)),
- attr(output.domain())
+ regional_maxima_functor(const I_& input, const N_& nbh)
+ : input(input),
+ nbh(nbh),
+ s(level::sort_points_decreasing(input)), // FIXME: sort_psites_decreasing
+ attr(input.domain())
{
}
};
+
+ // Generic implementation.
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_maxima_(const I& input, const N& nbh,
+ L& nlabels)
+ {
+ trace::entering("labeling::impl::generic::regional_maxima_");
+
+ typedef impl::regional_maxima_functor<I,N,L> F;
+ F f(input, nbh);
+ canvas::labeling<F> run(f);
+ nlabels = run.nlabels;
+
+ trace::exiting("labeling::impl::generic::regional_maxima_");
+ return run.output;
+ }
+
+ } // end of namespace mln::labeling::impl::generic
+
+
} // end of namespace mln::labeling::impl
+
// Facade.
- template <typename I, typename N, typename O>
- inline
- bool regional_maxima(const Image<I>& input, const
Neighborhood<N>& nbh,
- Image<O>& output, unsigned& nlabels)
- {
- mln_precondition(exact(output).domain() = exact(input).domain());
- typedef impl::regional_maxima_<I,N,O> F;
- F f(exact(input), exact(nbh), exact(output));
- canvas::labeling<F> run(f);
- nlabels = f.nlabels;
- return f.status;
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ regional_maxima(const Image<I>& input_, const Neighborhood<N>&
nbh_,
+ L& nlabels)
+ {
+ trace::entering("labeling::regional_maxima");
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(input.has_data());
+
+ // Calls the only (generic) impl.
+ mln_ch_value(I, L) output = impl::generic::regional_maxima_(input, nbh, nlabels);
+
+ trace::exiting("labeling::regional_maxima");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: mln/labeling/level.spe.hh
--- mln/labeling/level.spe.hh (revision 0)
+++ mln/labeling/level.spe.hh (revision 0)
@@ -0,0 +1,175 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library 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 this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library 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_LEVEL_SPE_HH
+# define MLN_LABELING_LEVEL_SPE_HH
+
+/*! \file mln/labeling/level.spe.hh
+ *
+ * \brief Specialization for mln::labeling::level.
+ */
+
+# include <mln/border/adjust.hh>
+# include <mln/border/fill.hh>
+# include <mln/value/other.hh>
+
+
+
+namespace mln
+{
+
+ namespace labeling
+ {
+
+ /*! Connected component labeling of the image objects at a given
+ * level.
+ *
+ * \param[in] input The input image.
+ * \param[in] val The level to consider for the labeling.
+ * \param[in] nbh The neighborhood.
+ * \param[out] nlabels The number of labels.
+ * \return The label image.
+ */
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level(const Image<I>& input, const mln_value(I)& val, const
Neighborhood<N>& nbh,
+ L& nlabels);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ // Fwd decl of the Generic version.
+
+ namespace generic
+ {
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level_(const I& input, const mln_value(I)& val, const N& nbh,
+ L& nlabels);
+
+ } // end of namespace mln::labeling::impl::generic
+
+
+
+ // Fastest functor.
+
+ template <typename I_, typename N_, typename L_>
+ struct level_fastest_functor
+ {
+ // requirements from mln::canvas::labeling:
+
+ typedef I_ I;
+ typedef N_ N;
+ typedef L_ L;
+ typedef mln_pset(I) S;
+
+ const I& input;
+ const N& nbh;
+ const S& s;
+
+ bool handles(unsigned p) const { return input[p] = val; }
+ bool equiv(unsigned n, unsigned) const { return input[n] = val; }
+
+ void init() {}
+ bool labels(unsigned) const { return true; }
+ void do_no_union(unsigned, unsigned) {}
+ void init_attr(unsigned) {}
+ void merge_attr(unsigned, unsigned) {}
+
+ // end of requirements
+
+ const mln_value(I_)& val;
+
+ level_fastest_functor(const I_& input, const mln_value(I_)& val, const N_&
nbh)
+ : input(input),
+ nbh(nbh),
+ s(input.domain()),
+ val(val)
+ {}
+ };
+
+
+ // Fastest routine.
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level_fastest_(const I& input, const mln_value(I)& val, const N& nbh,
+ L& nlabels)
+ {
+ trace::entering("labeling::impl::level_fastest_");
+
+ border::adjust(input, nbh.delta());
+ border::fill(input, value::other(val));
+
+ typedef level_fastest_functor<I,N,L> F;
+ F f(input, val, nbh);
+ canvas::labeling_fastest<F> run(f);
+
+ nlabels = run.nlabels;
+ // FIXME: Handle run.status
+
+ trace::exiting("labeling::impl::level_fastest_");
+ return run.output;
+ }
+
+
+ // Disjunction between "fastest" and "not fastest".
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level_(trait::image::speed::any,
+ const I& input, const mln_value(I)& val, const N& nbh,
+ L& nlabels)
+ {
+ return generic::level_(input, val, nbh, nlabels);
+ }
+
+ template <typename I, typename N, typename L>
+ mln_ch_value(I, L)
+ level_(trait::image::speed::fastest,
+ const I& input, const mln_value(I)& val, const N& nbh,
+ L& nlabels)
+ {
+ return level_fastest_(input, val, nbh, nlabels);
+ }
+
+
+ } // end of namespace mln::labeling::impl
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::labeling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LABELING_LEVEL_SPE_HH
Index: mln/labeling/background.hh
--- mln/labeling/background.hh (revision 1598)
+++ mln/labeling/background.hh (working copy)
@@ -43,13 +43,20 @@
namespace labeling
{
- /*! Connected component labeling of the background in a binary
- * image.
+ /*! Connected component labeling of the background part in a
+ * binary image.
*
* \param[in] input The input image.
* \param[in] nbh The neighborhood to consider.
* \param[out] nlabels The number of labels.
* \return The label image.
+ *
+ * \pre The input image has to be binary (checked at compile-time).
+ *
+ * This routine actually calls mln::labeling::level with the level
+ * value set to \c false.
+ *
+ * \see mln::labeling::level
*/
template <typename I, typename N>
mln_ch_value(I, unsigned)
@@ -65,8 +72,14 @@
background(const Image<I>& input, const Neighborhood<N>& nbh,
unsigned& nlabels)
{
+ trace::entering("labeling::background");
+ mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check();
mln_precondition(exact(input).has_data());
- return labeling::level(input, false, nbh, nlabels);
+
+ mln_ch_value(I, unsigned) output = labeling::level(input, false, nbh, nlabels);
+
+ trace::exiting("labeling::background");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
Index: img/README
--- img/README (revision 0)
+++ img/README (revision 0)
@@ -0,0 +1,8 @@
+ -*- outline -*-
+
+* tiny.pgm
+
+lena 16x16, graylevel / 8bit
+
+it was obtained by running the command:
+convert -geometry 3.125% lena.pgm tiny.pgm
Index: sandbox/geraud/estimate.hh
--- sandbox/geraud/estimate.hh (revision 1593)
+++ sandbox/geraud/estimate.hh (working copy)
@@ -33,8 +33,13 @@
* \brief Compute the estimate pixel value.
*/
-# include <mln/core/image_if_value.hh>
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/canvas/labeling.hh>
+
# include <mln/accu/compute.hh>
+// # include <mln/core/image_if_value.hh>
+
namespace mln
@@ -43,28 +48,36 @@
namespace labeling
{
- /*! \brief FIXME: Compute an estimate over the pixels of image \p
- * input with value \p val.
+ /*! \brief Label a binary image and compute some estimations over
+ * the components.
*
* \param[in] input The image.
- * \param[in] val value.
- * \result The estimate value.
+ *
+ * The free parameter \c A is a type of accumulator.
+ *
+ * FIXME: Not yet impled.
*/
template <typename A, typename I>
- mln_accu_with(A, util::pix<I>)::result
- estimate(const Image<I>& input, const mln_value(I)& val);
+ void
+ estimate(const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
template <typename A, typename I>
- inline
- mln_accu_with(A, util::pix<I>)::result
- estimate(const Image<I>& input, const mln_value(I)& val)
+ void
+ estimate(const Image<I>& input)
{
-// void* v = (input | val);
-// return 0;
- return accu::compute<A>(input | val);
+ trace::entering("labeling::estimate");
+ mlc_equal(mln_trait_image_kind(I), mln::trait::image::kind::binary)::check();
+ mln_precondition(exact(input).has_data());
+
+ std::cerr << "Sorry: mln::labeling::estimate is not yet
implemented!" << std::endl;
+
+ // FIXME: Was:
+ // mln_accu_with(A, util::pix<I>)::result res = accu::compute<A>(input
| val);
+
+ trace::exiting("labeling::estimate");
}
# endif // ! MLN_INCLUDE_ONLY