https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add the morphological sum attribute.
* mln/morpho/attribute/sum.hh: New.
* mln/morpho/attribute/volume.hh (area): New .
* mln/morpho/attribute/card.hh: Layout.
(take_as_init): New overload for util::pix.
* mln/morpho/attribute/all.hh: Update.
* tests/morpho/attribute/sum.cc: New.
* tests/morpho/attribute/volume.cc: New.
* tests/morpho/attribute/Makefile.am: Update.
mln/morpho/attribute/all.hh | 2
mln/morpho/attribute/card.hh | 30 +++++++---
mln/morpho/attribute/sum.hh | 111 +++++++++++++++++++------------------
mln/morpho/attribute/volume.hh | 11 +++
tests/morpho/attribute/Makefile.am | 6 +-
tests/morpho/attribute/sum.cc | 53 +++++++++++++++++
tests/morpho/attribute/volume.cc | 48 ++++++++++++++++
7 files changed, 198 insertions(+), 63 deletions(-)
Index: mln/morpho/attribute/sum.hh
--- mln/morpho/attribute/sum.hh (revision 3367)
+++ mln/morpho/attribute/sum.hh (working copy)
@@ -25,16 +25,19 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_MORPHO_ATTRIBUTE_CARD_HH
-# define MLN_MORPHO_ATTRIBUTE_CARD_HH
+#ifndef MLN_MORPHO_ATTRIBUTE_SUM_HH
+# define MLN_MORPHO_ATTRIBUTE_SUM_HH
-/// \file mln/morpho/attribute/card.hh
+/// \file mln/morpho/attribute/sum.hh
///
-/// Define an accumulator that computes the cardinality of a
-/// component.
+/// Define an accumulator that computes the sum of component values.
# include <mln/accu/internal/base.hh>
+# include <mln/trait/value_.hh> // For mln_sum.
+# include <mln/value/builtin/all.hh> // In the case of summing builtin values.
+# include <mln/literal/zero.hh> // For initialization.
+
namespace mln
{
@@ -44,7 +47,7 @@
namespace morpho {
namespace attribute {
- template <typename I> class card;
+ template <typename I, typename S> class sum;
}
}
@@ -54,13 +57,13 @@
namespace trait
{
- template <typename I>
- struct accumulator_< morpho::attribute::card<I> >
+ template <typename I, typename S>
+ struct accumulator_< morpho::attribute::sum<I,S> >
{
typedef accumulator::has_untake::no has_untake;
typedef accumulator::has_set_value::no has_set_value;
typedef accumulator::has_stop::no has_stop;
- typedef accumulator::when_pix::use_none when_pix;
+ typedef accumulator::when_pix::use_v when_pix;
};
} // end of namespace mln::trait
@@ -72,116 +75,118 @@
namespace attribute
{
- /// Cardinality accumulator class.
+ /// Suminality accumulator class.
- template <typename I>
- class card : public mln::accu::internal::base< unsigned, card<I> >
+ template <typename I, typename S = mln_sum(mln_value(I))>
+ class sum : public mln::accu::internal::base< S, sum<I,S> >
{
- typedef mln::accu::internal::base< unsigned, card<I> > super_;
+ typedef mln::accu::internal::base< S, sum<I> > super_;
public:
- typedef mln_psite(I) argument;
+ typedef mln_value(I) argument;
- card();
+ sum();
/// Manipulators.
/// \{
void init();
- void take(const argument& s);
- void take(const card<I>& other);
-
+ void take(const argument& v);
void take(const util::pix<I>& px);
+ void take(const sum<I,S>& other);
- void take();
- void take_as_init();
- using super_::take_as_init;
+ void take_as_init(const argument& v);
+ void take_as_init(const util::pix<I>& px);
/// \}
/// Get the value of the accumulator.
- unsigned to_result() const;
+ S to_result() const;
/// Check whether this accu is able to return a result.
- /// Always true here.
+ /// Return always true.
bool is_valid() const;
protected:
- /// The value.
- unsigned c_;
+
+ /// The sum value.
+ S s_;
};
# ifndef MLN_INCLUDE_ONLY
- template <typename I>
+ template <typename I, typename S>
inline
- card<I>::card()
+ sum<I,S>::sum()
{
init();
}
- template <typename I>
+ template <typename I, typename S>
inline
void
- card<I>::init()
+ sum<I,S>::init()
{
- c_ = 0;
+ s_ = literal::zero;
}
- template <typename I>
+ // take.
+
+ template <typename I, typename S>
inline
void
- card<I>::take(const argument&)
+ sum<I,S>::take(const argument& v)
{
- take();
+ s_ += v;
}
- template <typename I>
+ template <typename I, typename S>
inline
void
- card<I>::take(const card<I>& other)
+ sum<I,S>::take(const util::pix<I>& px)
{
- c_ += other.c_;
+ take(px.v());
}
- template <typename I>
+ template <typename I, typename S>
inline
void
- card<I>::take(const util::pix<I>&)
+ sum<I,S>::take(const sum<I,S>& other)
{
- take();
+ s_ += other.s_;
}
- template <typename I>
+ // take_as_init.
+
+ template <typename I, typename S>
inline
void
- card<I>::take()
+ sum<I,S>::take_as_init(const argument& v)
{
- ++c_;
+ s_ = v;
}
- template <typename I>
+ template <typename I, typename S>
inline
void
- card<I>::take_as_init()
+ sum<I,S>::take_as_init(const util::pix<I>& px)
{
- init();
- take();
+ take_as_init(px.v());
}
- template <typename I>
+ template <typename I, typename S>
inline
- unsigned
- card<I>::to_result() const
+ S
+ sum<I,S>::to_result() const
{
- return c_;
+ return s_;
}
- template <typename I>
+ template <typename I, typename S>
inline
bool
- card<I>::is_valid() const
+ sum<I,S>::is_valid() const
{
return true;
}
@@ -195,4 +200,4 @@
} // end of namespace mln
-#endif // ! MLN_MORPHO_ATTRIBUTE_CARD_HH
+#endif // ! MLN_MORPHO_ATTRIBUTE_SUM_HH
Index: mln/morpho/attribute/volume.hh
--- mln/morpho/attribute/volume.hh (revision 3367)
+++ mln/morpho/attribute/volume.hh (working copy)
@@ -103,6 +103,9 @@
/// Always true here.
bool is_valid() const;
+ /// Give the area.
+ unsigned area() const;
+
protected:
/// The current level.
mln_value(I) level_;
@@ -197,6 +200,14 @@
template <typename I>
inline
+ unsigned
+ volume<I>::area() const
+ {
+ return area_;
+ }
+
+ template <typename I>
+ inline
bool
volume<I>::is_valid() const
{
Index: mln/morpho/attribute/all.hh
--- mln/morpho/attribute/all.hh (revision 3367)
+++ mln/morpho/attribute/all.hh (working copy)
@@ -46,6 +46,8 @@
# include <mln/morpho/attribute/card.hh>
+# include <mln/morpho/attribute/sum.hh>
+# include <mln/morpho/attribute/volume.hh>
#endif // ! MLN_MORPHO_ATTRIBUTE_ALL_HH
Index: mln/morpho/attribute/card.hh
--- mln/morpho/attribute/card.hh (revision 3367)
+++ mln/morpho/attribute/card.hh (working copy)
@@ -88,13 +88,13 @@
/// \{
void init();
+ void take();
void take(const argument& s);
- void take(const card<I>& other);
-
void take(const util::pix<I>& px);
+ void take(const card<I>& other);
- void take();
void take_as_init();
+ void take_as_init(const util::pix<I>& px);
using super_::take_as_init;
/// \}
@@ -129,20 +129,22 @@
c_ = 0;
}
+ // take.
+
template <typename I>
inline
void
- card<I>::take(const argument&)
+ card<I>::take()
{
- take();
+ ++c_;
}
template <typename I>
inline
void
- card<I>::take(const card<I>& other)
+ card<I>::take(const argument&)
{
- c_ += other.c_;
+ take();
}
template <typename I>
@@ -156,11 +158,13 @@
template <typename I>
inline
void
- card<I>::take()
+ card<I>::take(const card<I>& other)
{
- ++c_;
+ c_ += other.c_;
}
+ // take_as_init.
+
template <typename I>
inline
void
@@ -172,6 +176,14 @@
template <typename I>
inline
+ void
+ card<I>::take_as_init(const util::pix<I>&)
+ {
+ take_as_init();
+ }
+
+ template <typename I>
+ inline
unsigned
card<I>::to_result() const
{
Index: tests/morpho/attribute/sum.cc
--- tests/morpho/attribute/sum.cc (revision 0)
+++ tests/morpho/attribute/sum.cc (revision 0)
@@ -0,0 +1,53 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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/morpho/attribute/sum.cc
+///
+/// Test on mln::morpho::attribute::sum.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/morpho/attribute/sum.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d<int> I;
+ I ima(3, 3);
+
+ point2d p(0, 0);
+ ima(p) = 17;
+
+ util::pix<I> px(ima, p);
+
+ morpho::attribute::sum<I> s;
+ s.take(px);
+ s.take(px);
+ s.take(px);
+ mln_assertion(s == 51);
+}
Index: tests/morpho/attribute/Makefile.am
--- tests/morpho/attribute/Makefile.am (revision 3367)
+++ tests/morpho/attribute/Makefile.am (working copy)
@@ -3,8 +3,12 @@
include $(top_srcdir)/milena/tests/tests.mk
check_PROGRAMS = \
- card
+ card \
+ sum \
+ volume
card_SOURCES = card.cc
+sum_SOURCES = sum.cc
+volume_SOURCES = volume.cc
TESTS = $(check_PROGRAMS)
Index: tests/morpho/attribute/volume.cc
--- tests/morpho/attribute/volume.cc (revision 0)
+++ tests/morpho/attribute/volume.cc (revision 0)
@@ -0,0 +1,48 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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/morpho/attribute/volume.cc
+///
+/// Test on mln::morpho::attribute::volume.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/morpho/attribute/volume.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d<int> I;
+ I ima(3, 3);
+
+ util::pix<I> px(ima, point2d(0,0));
+
+ morpho::attribute::volume<I> v;
+ v.take(px);
+ mln_assertion(v == 1);
+}
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a label wrapper in fun::l2l.
* mln/fun/l2l/wrap.hh: New.
* mln/fun/l2l/all.hh: Update.
* tests/fun/l2l: New directory.
* tests/fun/Makefile.am: Update.
* tests/fun/l2l/wrap.cc: New.
* tests/fun/l2l/Makefile.am: New.
mln/fun/l2l/all.hh | 4 +-
mln/fun/l2l/wrap.hh | 87 ++++++++++++++++++++++++++++++++++++++++++++++
tests/fun/Makefile.am | 2 -
tests/fun/l2l/Makefile.am | 10 +++++
tests/fun/l2l/wrap.cc | 58 ++++++++++++++++++++++++++++++
5 files changed, 159 insertions(+), 2 deletions(-)
Index: mln/fun/l2l/all.hh
--- mln/fun/l2l/all.hh (revision 3366)
+++ mln/fun/l2l/all.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -49,6 +50,7 @@
# include <mln/fun/l2l/relabel.hh>
+# include <mln/fun/l2l/wrap.hh>
Index: mln/fun/l2l/wrap.hh
--- mln/fun/l2l/wrap.hh (revision 0)
+++ mln/fun/l2l/wrap.hh (revision 0)
@@ -0,0 +1,87 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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_FUN_L2L_WRAP_HH
+# define MLN_FUN_L2L_WRAP_HH
+
+/// \file mln/fun/l2l/wrap.hh
+///
+/// Function to wrap labels such as 0 -> 0 and [1, lmax] maps to [1,
+/// Lmax] (using modulus).
+///
+/// \todo Prefer not to cast towards 'unsigned long'; use a procedure
+/// such as enc(l) that can work on 'unsigned', 'int_u8', 'label<n>', and
+/// also other label types.
+
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace l2l
+ {
+
+ template <typename L>
+ struct wrap : public Function_l2l< wrap<L> >
+ {
+ public:
+
+ typedef L result;
+
+ template <typename L_>
+ L operator()(const L_& l_) const;
+
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename L>
+ template <typename L_>
+ inline
+ L
+ wrap<L>::operator()(const L_& l_) const
+ {
+ mlc_converts_to(L_, unsigned long)::check();
+ unsigned long l = static_cast<unsigned long>(l_);
+ return l == 0ul ? L(0ul) : L(1 + (l - 1) % 255);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::l2l
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_L2L_WRAP_HH
Index: tests/fun/Makefile.am
--- tests/fun/Makefile.am (revision 3366)
+++ tests/fun/Makefile.am (working copy)
@@ -2,4 +2,4 @@
include $(top_srcdir)/milena/tests/tests.mk
-SUBDIRS = i2v p2b p2p p2v v2v vv2v x2x
+SUBDIRS = i2v p2b l2l p2p p2v v2v vv2v x2x
Index: tests/fun/l2l/Makefile.am
--- tests/fun/l2l/Makefile.am (revision 0)
+++ tests/fun/l2l/Makefile.am (revision 0)
@@ -0,0 +1,10 @@
+## Process this file through Automake to create Makefile.in -*- Makefile -*-
+
+include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ wrap
+
+wrap_SOURCES = wrap.cc
+
+TESTS = $(check_PROGRAMS)
Index: tests/fun/l2l/wrap.cc
--- tests/fun/l2l/wrap.cc (revision 0)
+++ tests/fun/l2l/wrap.cc (revision 0)
@@ -0,0 +1,58 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// 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/fun/l2l/wrap.cc
+///
+/// Test on mln::fun::l2l::wrap.
+
+#include <mln/fun/l2l/wrap.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_16.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ fun::l2l::wrap<value::int_u8> f;
+
+ value::label_16
+ l0 = 0,
+ l1 = 1,
+ l255 = 255,
+ l256 = 256,
+ l510 = 510,
+ l511 = 511;
+
+ mln_assertion( f(l0) == 0 );
+ mln_assertion( f(l1) == 1 );
+ mln_assertion( f(l255) == 255 );
+ mln_assertion( f(l256) == 1 );
+ mln_assertion( f(l510) == 255 );
+ mln_assertion( f(l511) == 1 );
+}
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-12 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add fill_holes() function in new file.
* mln/labeling/fill_holes.hh: Implement fill_holes().
---
fill_holes.hh | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
Index: trunk/milena/mln/labeling/fill_holes.hh
===================================================================
--- trunk/milena/mln/labeling/fill_holes.hh (revision 0)
+++ trunk/milena/mln/labeling/fill_holes.hh (revision 3365)
@@ -0,0 +1,118 @@
+// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
+// Laboratory (LRDE)
+//
+// 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_FILL_HOLES_HH
+# define MLN_LABELING_FILL_HOLES_HH
+
+/// \file mln/labeling/fill_holes.hh
+///
+/// Filling holes of a single object in a binary image.
+
+# include <mln/labeling/background.hh>
+# include <mln/labeling/compute.hh>
+
+# include <mln/accu/count.hh>
+
+# include <mln/value/int_u8.hh>
+
+
+namespace mln
+{
+
+ namespace labeling
+ {
+
+ /// Filling holes of a single object in a binary image.
+ ///
+ /// \param[in] input The input image.
+ /// \param[in] nbh The connexity of the background.
+ /// \param[out] nlabels The number of labels.
+ /// \return The binary image with a simple object without holes.
+ ///
+ /// \pre The input image has to be binary (checked at compile-time).
+ ///
+ /// This routine actually calls mln::labeling::background
+ ///
+ /// \see mln::labeling::background
+ ///
+ template <typename I, typename N, typename L>
+ I
+ fill_holes(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I, typename N, typename L>
+ inline
+ I
+ fill_holes(const Image<I>& input, const Neighborhood<N>& nbh,
+ L& nlabels)
+ {
+ trace::entering("labeling::fill_holes");
+
+ 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());
+
+ using value::int_u8;
+
+ mln_ch_value(I, bool) output;
+ initialize(output, input);
+ data::fill(output, false);
+
+ accu::count<int_u8> a_;
+ mln_ch_value(I, L) lbls = labeling::background(input, nbh, nlabels);
+ util::array<unsigned> arr = labeling::compute(a_, input, lbls, nlabels);
+ int bg_count = 0;
+ int bg_lbl = 0;
+
+ for (int i = 0; i < arr.nelements(); ++i)
+ {
+ if (arr[i] > bg_count)
+ {
+ bg_count = arr[i];
+ bg_lbl = i;
+ }
+ }
+
+ data::fill((output | pw::value(lbls) != bg_lbl).rw(), true);
+
+ trace::exiting("labeling::fill_holes");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::labeling
+
+} // end of namespace mln
+
+
+#endif // ! MLN_LABELING_FILL_HOLES_HH