* mln/world/kn/holes.hh,
* mln/world/kn/internal/get_background_label.hh,
* mln/world/kn/saturate.hh,
* tests/world/kn/holes.cc,
* tests/world/kn/saturate.cc: New.
* tests/world/kn/Makefile.am: New targets.
---
milena/ChangeLog | 12 ++
...{fill_0_1_faces_internal_border.hh => holes.hh} | 68 ++++++-----
.../mln/world/kn/internal/get_background_label.hh | 122 ++++++++++++++++++++
...ll_0_1_faces_internal_border.hh => saturate.hh} | 70 ++++++-----
milena/tests/world/kn/Makefile.am | 4 +
.../{k1/fill_1_from_2_faces.cc => kn/holes.cc} | 88 +++++++--------
.../{k1/fill_1_from_2_faces.cc => kn/saturate.cc} | 89 +++++++--------
7 files changed, 295 insertions(+), 158 deletions(-)
copy milena/mln/world/kn/{fill_0_1_faces_internal_border.hh => holes.hh} (58%)
create mode 100644 milena/mln/world/kn/internal/get_background_label.hh
copy milena/mln/world/kn/{fill_0_1_faces_internal_border.hh => saturate.hh} (57%)
copy milena/tests/world/{k1/fill_1_from_2_faces.cc => kn/holes.cc} (59%)
copy milena/tests/world/{k1/fill_1_from_2_faces.cc => kn/saturate.cc} (58%)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index cc55293..45480d5 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,15 @@
+2012-10-26 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Add kn::holes() and kn::saturate().
+
+ * mln/world/kn/holes.hh,
+ * mln/world/kn/internal/get_background_label.hh,
+ * mln/world/kn/saturate.hh,
+ * tests/world/kn/holes.cc,
+ * tests/world/kn/saturate.cc: New.
+
+ * tests/world/kn/Makefile.am: New targets.
+
2012-10-25 Guillaume Lazzara <z(a)lrde.epita.fr>
Fix preconditions.
diff --git a/milena/mln/world/kn/fill_0_1_faces_internal_border.hh
b/milena/mln/world/kn/holes.hh
similarity index 58%
copy from milena/mln/world/kn/fill_0_1_faces_internal_border.hh
copy to milena/mln/world/kn/holes.hh
index 915a69a..dad04cd 100644
--- a/milena/mln/world/kn/fill_0_1_faces_internal_border.hh
+++ b/milena/mln/world/kn/holes.hh
@@ -25,12 +25,17 @@
/// \file
///
-/// \brief Fill 0 and 1 faces border with a value in a KN 2D image.
+/// \brief
-#ifndef MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
-# define MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
+#ifndef MLN_WORLD_KN_SATURATE_HH
+# define MLN_WORLD_KN_SATURATE_HH
-# include <mln/inner_border/fill.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/labeling/background.hh>
+# include <mln/data/fill.hh>
+# include <mln/pw/all.hh>
+# include <mln/world/kn/internal/get_background_label.hh>
namespace mln
@@ -42,44 +47,45 @@ namespace mln
namespace kn
{
- /*! \brief Fill 0 and 1 faces border with a value in a KN 2D image.
- \param[in,out] inout A 2D image immersed in KN.
- \param[in] v The border value.
-
- Example with \p v=1:
-
- . - . - . 1 1 1 1 1
- | o | o | 1 o | o 1
- . - . - . -> 1 - . - 1
- | o | o | 1 o | o 1
- . - . - . 1 1 1 1 1
-
- */
template <typename I>
- void fill_0_1_faces_internal_border(Image<I>& inout,
- const mln_value(I)& v);
-
+ mln_concrete(I)
+ holes(const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
+ template <typename I>
+ mln_concrete(I)
+ holes(const Image<I>& input_)
+ {
+ trace::entering("mln::world::kn::holes");
+ mlc_equal(mln_trait_image_kind(I),
+ mln::trait::image::kind::binary)::check();
+ mln_precondition(exact(input_).is_valid());
- // Facade
+ const I& input = exact(input_);
+ unsigned n_labels;
+ mln_ch_value(I,unsigned)
+ lab = labeling::background(input, c4(), n_labels);
- template <typename I>
- void fill_0_1_faces_internal_border(Image<I>& inout_,
- const mln_value(I)& v)
- {
- trace::entering("mln::world::kn::fill_0_1_faces_internal_border");
+ bool has_bg_label;
+ unsigned bg = internal::get_background_label(lab, has_bg_label);
+
+ mln_concrete(I) output(input.domain());
- mln_precondition(exact(inout_).is_valid());
- I& inout = exact(inout_);
+ if (! has_bg_label)
+ {
+ data::fill(output, false);
+ return output;
+ }
- inner_border::fill(inout, v);
+ data::fill(output, pw::value(lab) != pw::cst(bg)
+ && pw::value(lab) != pw::cst(literal::zero));
- trace::exiting("mln::world::kn::fill_0_1_faces_internal_border");
+ trace::exiting("mln::world::kn::holes");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
@@ -90,4 +96,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
+#endif // ! MLN_WORLD_KN_SATURATE_HH
diff --git a/milena/mln/world/kn/internal/get_background_label.hh
b/milena/mln/world/kn/internal/get_background_label.hh
new file mode 100644
index 0000000..a993b5a
--- /dev/null
+++ b/milena/mln/world/kn/internal/get_background_label.hh
@@ -0,0 +1,122 @@
+// Copyright (C) 2012 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.
+
+/// \file
+///
+/// \brief Look for background label in the borders of a labeled
+/// image.
+
+#ifndef MLN_WORLD_KN_INTERNAL_GET_BACKGROUND_LABEL_HH
+# define MLN_WORLD_KN_INTERNAL_GET_BACKGROUND_LABEL_HH
+
+# include <mln/core/concept/image.hh>
+
+namespace mln
+{
+
+ namespace world
+ {
+
+ namespace kn
+ {
+
+ namespace internal
+ {
+
+ /// \brief Look for background label in the borders of a
+ /// labeled image.
+ template <typename I>
+ mln_value(I)
+ get_background_label(const Image<I>& lab, bool& has_bg_label);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ mln_value(I)
+ get_background_label(const Image<I>& lab_, bool& has_bg_label)
+ {
+ trace::entering("mln::world::kn::internal::get_background_label");
+ mln_precondition(exact(lab_).is_valid());
+
+ const I& lab = exact(lab_);
+
+ mln_box(I) dom = lab.domain();
+ def::coord
+ min_row = dom.pmin().row(),
+ max_row = dom.pmax().row(),
+ min_col = dom.pmin().col(),
+ max_col = dom.pmax().col();
+
+ has_bg_label = false;
+ for (def::coord col = min_col; col <= max_col; ++col)
+ {
+ // first row
+ if (lab.at_(min_row, col) != 0)
+ {
+ has_bg_label = true;
+ return lab.at_(min_row, col);
+ }
+ // last row
+ if (lab.at_(max_row, col) != 0)
+ {
+ has_bg_label = true;
+ return lab.at_(max_row, col);
+ }
+ }
+ if (! has_bg_label)
+ {
+ for (def::coord row = min_row; row <= max_row; ++row)
+ {
+ // first col
+ if (lab.at_(row, min_col) != 0)
+ {
+ has_bg_label = true;
+ return lab.at_(row, min_col);
+ }
+ // last col
+ if (lab.at_(row, max_col) != 0)
+ {
+ has_bg_label = true;
+ return lab.at_(row, max_col);
+ }
+ }
+ }
+
+ trace::exiting("mln::world::kn::internal::get_background_label");
+ return 0;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::world::kn::internal
+
+ } // end of namespace mln::world::kn
+
+ } // end of namespace mln::world
+
+} // end of namespace mln
+
+#endif // ! MLN_WORLD_KN_INTERNAL_GET_BACKGROUND_LABEL_HH
diff --git a/milena/mln/world/kn/fill_0_1_faces_internal_border.hh
b/milena/mln/world/kn/saturate.hh
similarity index 57%
copy from milena/mln/world/kn/fill_0_1_faces_internal_border.hh
copy to milena/mln/world/kn/saturate.hh
index 915a69a..3677333 100644
--- a/milena/mln/world/kn/fill_0_1_faces_internal_border.hh
+++ b/milena/mln/world/kn/saturate.hh
@@ -25,12 +25,17 @@
/// \file
///
-/// \brief Fill 0 and 1 faces border with a value in a KN 2D image.
+/// \brief Saturate a cut of an image.
-#ifndef MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
-# define MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
+#ifndef MLN_WORLD_KN_SATURATE_HH
+# define MLN_WORLD_KN_SATURATE_HH
-# include <mln/inner_border/fill.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/labeling/background.hh>
+# include <mln/data/fill.hh>
+# include <mln/pw/all.hh>
+# include <mln/world/kn/internal/get_background_label.hh>
namespace mln
@@ -42,44 +47,45 @@ namespace mln
namespace kn
{
- /*! \brief Fill 0 and 1 faces border with a value in a KN 2D image.
-
- \param[in,out] inout A 2D image immersed in KN.
- \param[in] v The border value.
-
- Example with \p v=1:
-
- . - . - . 1 1 1 1 1
- | o | o | 1 o | o 1
- . - . - . -> 1 - . - 1
- | o | o | 1 o | o 1
- . - . - . 1 1 1 1 1
-
- */
+ /// \brief Saturate a cut of an image.
template <typename I>
- void fill_0_1_faces_internal_border(Image<I>& inout,
- const mln_value(I)& v);
-
+ mln_concrete(I)
+ saturate(const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
+ template <typename I>
+ mln_concrete(I)
+ saturate(const Image<I>& input_)
+ {
+ trace::entering("mln::world::kn::saturate");
+ mlc_equal(mln_trait_image_kind(I),
+ mln::trait::image::kind::binary)::check();
+ mln_precondition(exact(input_).is_valid());
- // Facade
+ const I& input = exact(input_);
+ unsigned n_labels;
+ mln_ch_value(I,unsigned)
+ lab = labeling::background(input, c4(), n_labels);
- template <typename I>
- void fill_0_1_faces_internal_border(Image<I>& inout_,
- const mln_value(I)& v)
- {
- trace::entering("mln::world::kn::fill_0_1_faces_internal_border");
+ bool has_bg_label;
+ unsigned bg = internal::get_background_label(lab, has_bg_label);
+
+ mln_concrete(I) output;
+ initialize(output, input);
- mln_precondition(exact(inout_).is_valid());
- I& inout = exact(inout_);
+ if (! has_bg_label)
+ {
+ data::fill(output, true);
+ return output;
+ }
- inner_border::fill(inout, v);
+ data::fill(output, pw::value(lab) != pw::cst(bg));
- trace::exiting("mln::world::kn::fill_0_1_faces_internal_border");
+ trace::exiting("mln::world::kn::saturate");
+ return output;
}
# endif // ! MLN_INCLUDE_ONLY
@@ -90,4 +96,4 @@ namespace mln
} // end of namespace mln
-#endif // ! MLN_WORLD_KN_FILL_0_1_FACES_INTERNAL_BORDER_HH
+#endif // ! MLN_WORLD_KN_SATURATE_HH
diff --git a/milena/tests/world/kn/Makefile.am b/milena/tests/world/kn/Makefile.am
index 866ae00..2a89e48a 100644
--- a/milena/tests/world/kn/Makefile.am
+++ b/milena/tests/world/kn/Makefile.am
@@ -23,6 +23,7 @@ check_PROGRAMS = \
fill_1_from_2_faces \
fill_1_from_aux_2_faces \
fill_2_from_1_faces \
+ holes \
immerse \
immerse_with_inner_border \
is_0_face \
@@ -32,6 +33,7 @@ check_PROGRAMS = \
is_1_face_horizontal \
is_2_face \
level \
+ saturate \
un_immerse
fill_0_1_faces_internal_border_SOURCES = fill_0_1_faces_internal_border.cc
@@ -40,6 +42,7 @@ fill_0_from_2_faces_SOURCES = fill_0_from_2_faces.cc
fill_1_from_2_faces_SOURCES = fill_1_from_2_faces.cc
fill_1_from_aux_2_faces_SOURCES = fill_1_from_aux_2_faces.cc
fill_2_from_1_faces_SOURCES = fill_2_from_1_faces.cc
+holes_SOURCES = holes.cc
immerse_SOURCES = immerse.cc
immerse_with_inner_border_SOURCES = immerse_with_inner_border.cc
is_0_face_SOURCES = is_0_face.cc
@@ -49,6 +52,7 @@ is_1_face_vertical_SOURCES = is_1_face_vertical.cc
is_1_face_horizontal_SOURCES = is_1_face_horizontal.cc
is_2_face_SOURCES = is_2_face.cc
level_SOURCES = level.cc
+saturate_SOURCES = saturate.cc
un_immerse_SOURCES = un_immerse.cc
diff --git a/milena/tests/world/k1/fill_1_from_2_faces.cc
b/milena/tests/world/kn/holes.cc
similarity index 59%
copy from milena/tests/world/k1/fill_1_from_2_faces.cc
copy to milena/tests/world/kn/holes.cc
index 4045674..9bba24f 100644
--- a/milena/tests/world/k1/fill_1_from_2_faces.cc
+++ b/milena/tests/world/kn/holes.cc
@@ -26,61 +26,55 @@
/// \file
#include <mln/core/image/image2d.hh>
-#include <mln/make/box2d.hh>
+#include <mln/world/kn/holes.hh>
#include <mln/data/compare.hh>
-#include <mln/accu/math/sum.hh>
-#include <mln/world/k1/fill_1_from_2_faces.hh>
-#include <mln/border/fill.hh>
-
-
-namespace mln
-{
-
- struct sum_t : Function_vv2v<sum_t>
- {
- typedef int result;
-
- int operator()(const int& v1, const int& v2) const
- {
- return v1 + v2;
- }
-
- };
-
-}
-
-
int main()
{
using namespace mln;
- int refvals[5][5] = {
- {1, 3, 1, 3, 1},
- {3, 3, 6, 3, 3},
- {1, 6, 1, 6, 1},
- {3, 3, 6, 3, 3},
- {1, 3, 1, 3, 1}
- };
- image2d<int> ref = make::image(refvals, point2d(-1, -1));
-
- int vals[5][5] = {
- {1, 0, 1, 0, 1 },
- {0, 3, 0, 3, 0 },
- {1, 0, 1, 0, 1 },
- {0, 3, 0, 3, 0 },
- {1, 0, 1, 0, 1 }
- };
- image2d<int> imakn = make::image(vals, point2d(-1, -1));
+ {
+ bool vals[][5] = {
+ {0, 0, 1, 1, 1},
+ {1, 0, 1, 0, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ima = make::image(vals);
+ bool refvals[][5] = {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 1, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}
+ };
+ image2d<bool> ref = make::image(refvals);
+
+ image2d<bool> out = world::kn::holes(ima);
+ mln_assertion(out == ref);
+ }
- /// Make sure the border is set to 0 to get deterministic results.
- border::fill(imakn, 0);
- // Overload with function
{
- sum_t f;
- world::k1::fill_1_from_2_faces(imakn, f);
- mln_assertion(ref == imakn);
+ bool vals[][5] = {
+ {1, 1, 1, 1, 1},
+ {1, 0, 1, 0, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ima = make::image(vals);
+ bool refvals[][5] = {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}
+ };
+ image2d<bool> ref = make::image(refvals);
+
+ image2d<bool> out = world::kn::holes(ima);
+ mln_assertion(out == ref);
}
-
}
diff --git a/milena/tests/world/k1/fill_1_from_2_faces.cc
b/milena/tests/world/kn/saturate.cc
similarity index 58%
copy from milena/tests/world/k1/fill_1_from_2_faces.cc
copy to milena/tests/world/kn/saturate.cc
index 4045674..33b0f79 100644
--- a/milena/tests/world/k1/fill_1_from_2_faces.cc
+++ b/milena/tests/world/kn/saturate.cc
@@ -26,61 +26,54 @@
/// \file
#include <mln/core/image/image2d.hh>
-#include <mln/make/box2d.hh>
+#include <mln/world/kn/saturate.hh>
#include <mln/data/compare.hh>
-#include <mln/accu/math/sum.hh>
-#include <mln/world/k1/fill_1_from_2_faces.hh>
-#include <mln/border/fill.hh>
-
-
-namespace mln
-{
-
- struct sum_t : Function_vv2v<sum_t>
- {
- typedef int result;
-
- int operator()(const int& v1, const int& v2) const
- {
- return v1 + v2;
- }
-
- };
-
-}
-
-
int main()
{
using namespace mln;
- int refvals[5][5] = {
- {1, 3, 1, 3, 1},
- {3, 3, 6, 3, 3},
- {1, 6, 1, 6, 1},
- {3, 3, 6, 3, 3},
- {1, 3, 1, 3, 1}
- };
- image2d<int> ref = make::image(refvals, point2d(-1, -1));
-
- int vals[5][5] = {
- {1, 0, 1, 0, 1 },
- {0, 3, 0, 3, 0 },
- {1, 0, 1, 0, 1 },
- {0, 3, 0, 3, 0 },
- {1, 0, 1, 0, 1 }
- };
- image2d<int> imakn = make::image(vals, point2d(-1, -1));
-
- /// Make sure the border is set to 0 to get deterministic results.
- border::fill(imakn, 0);
-
- // Overload with function
{
- sum_t f;
- world::k1::fill_1_from_2_faces(imakn, f);
- mln_assertion(ref == imakn);
+ bool vals[][5] = {
+ {0, 0, 1, 1, 1},
+ {1, 0, 1, 0, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ima = make::image(vals);
+ bool refvals[][5] = {
+ {0, 0, 1, 1, 1},
+ {1, 0, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ref = make::image(refvals);
+
+ image2d<bool> out = world::kn::saturate(ima);
+ mln_assertion(out == ref);
}
+ {
+ bool vals[][5] = {
+ {1, 1, 1, 1, 1},
+ {1, 0, 1, 0, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ima = make::image(vals);
+ bool refvals[][5] = {
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1},
+ {1, 1, 1, 1, 1}
+ };
+ image2d<bool> ref = make::image(refvals);
+
+ image2d<bool> out = world::kn::saturate(ima);
+ mln_assertion(out == ref);
+ }
}
--
1.7.2.5