* mln/world/k1/fill_1_from_2_faces.hh: Fix initialization of the
accumulator.
* mln/world/k1/immerse_with.hh,
* mln/world/kn/fill_1_from_2_faces.hh: Add an overload with functions.
* mln/world/k2/fill_non_primary_from_primary_2_faces.hh: Cast to a
specific type.
* mln/world/kn/fill_1_from_aux_2_faces.hh: Initialize the accumulator.
* mln/world/kn/internal/get_background_label.hh: Use mln::geom
routines.
* tests/world/k1/immerse_with.cc: Improve test.
* tests/world/k2/fill_non_primary_from_primary_2_faces.cc: Make
use of new functions.
* tests/world/kn/accu/max_interval.cc,
* tests/world/kn/accu/min_interval.cc: Fix test.
---
milena/ChangeLog | 26 +++++++++++++
milena/mln/world/k1/fill_1_from_2_faces.hh | 13 ++++--
milena/mln/world/k1/immerse_with.hh | 40 ++++++++++++++++++++
.../k2/fill_non_primary_from_primary_2_faces.hh | 10 +++--
milena/mln/world/kn/fill_1_from_2_faces.hh | 33 ++++++++++++++--
milena/mln/world/kn/fill_1_from_aux_2_faces.hh | 15 ++++---
.../mln/world/kn/internal/get_background_label.hh | 13 ++++--
milena/tests/world/k1/immerse_with.cc | 25 +++++++-----
.../k2/fill_non_primary_from_primary_2_faces.cc | 37 ++----------------
milena/tests/world/kn/accu/max_interval.cc | 13 +++---
milena/tests/world/kn/accu/min_interval.cc | 13 +++---
11 files changed, 158 insertions(+), 80 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 6c1f276..f93a95b 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,31 @@
2012-10-26 Guillaume Lazzara <z(a)lrde.epita.fr>
+ Various fixes.
+
+ * mln/world/k1/fill_1_from_2_faces.hh: Fix initialization of the
+ accumulator.
+
+ * mln/world/k1/immerse_with.hh,
+ * mln/world/kn/fill_1_from_2_faces.hh: Add an overload with functions.
+
+ * mln/world/k2/fill_non_primary_from_primary_2_faces.hh: Cast to a
+ specific type.
+
+ * mln/world/kn/fill_1_from_aux_2_faces.hh: Initialize the accumulator.
+
+ * mln/world/kn/internal/get_background_label.hh: Use mln::geom
+ routines.
+
+ * tests/world/k1/immerse_with.cc: Improve test.
+
+ * tests/world/k2/fill_non_primary_from_primary_2_faces.cc: Make
+ use of new functions.
+
+ * tests/world/kn/accu/max_interval.cc,
+ * tests/world/kn/accu/min_interval.cc: Fix test.
+
+2012-10-26 Guillaume Lazzara <z(a)lrde.epita.fr>
+
Handle border effects while computing 1-faces values.
* mln/world/kn/internal/fill_primary_2_faces_from_input.hh:
diff --git a/milena/mln/world/k1/fill_1_from_2_faces.hh
b/milena/mln/world/k1/fill_1_from_2_faces.hh
index b8bf9cd..3db133f 100644
--- a/milena/mln/world/k1/fill_1_from_2_faces.hh
+++ b/milena/mln/world/k1/fill_1_from_2_faces.hh
@@ -34,7 +34,6 @@
# include <mln/world/kn/is_1_face_vertical.hh>
# include <mln/world/kn/is_1_face_horizontal.hh>
-
namespace mln
{
@@ -70,6 +69,8 @@ namespace mln
void fill_1_from_2_faces(Image<I>& inout, const
Function_vv2v<F>& f);
/// \overload
+ /// This implementation do not read values outside of the image
+ /// domain.
template <typename I, typename A>
void fill_1_from_2_faces(Image<I>& inout, const Accumulator<A>&
accu);
@@ -89,7 +90,8 @@ namespace mln
I& inout = exact(inout_);
const F& f = exact(f_);
- mln_piter(I) p(inout.domain());
+ mln_box(I) b = inout.domain();
+ mln_piter(I) p(b);
for_all(p)
if (kn::is_1_face_vertical(p))
inout(p) = f(inout(p + left), inout(p + right));
@@ -106,13 +108,13 @@ namespace mln
mln_precondition(exact(inout_).is_valid());
I& inout = exact(inout_);
- A accu(accu_);
+ A accu(exact(accu_));
- mln_box(I) b = inout.domain();
- mln_piter(I) p(b);
+ mln_piter(I) p(inout.domain());
for_all(p)
if (kn::is_1_face_vertical(p))
{
+ accu.init();
if (inout.domain().has(p + left))
accu.take(inout(p + left));
if (inout.domain().has(p + right))
@@ -121,6 +123,7 @@ namespace mln
}
else if (kn::is_1_face_horizontal(p))
{
+ accu.init();
if (inout.domain().has(p + up))
accu.take(inout(p + up));
if (inout.domain().has(p + down))
diff --git a/milena/mln/world/k1/immerse_with.hh b/milena/mln/world/k1/immerse_with.hh
index d52bbe7..aa9658b 100644
--- a/milena/mln/world/k1/immerse_with.hh
+++ b/milena/mln/world/k1/immerse_with.hh
@@ -67,10 +67,21 @@ namespace mln
0-faces are valued with function \p f4, considering a
4-connexity with its 1-face neighbors.
+ Inner-border 0 and 1 faces are initialized with \p
+ default_value.
*/
template <typename I, typename V, typename F2, typename F4>
mln_ch_value(I, V)
immerse_with(const Image<I>& ima, const V& new_value_type,
+ const V& default_value,
+ const Function_vv2v<F2>& f_1faces,
+ const Function_vvvv2v<F4>& f_0faces);
+
+ /// \overload
+ /// 0 and 1 faces in the inner border are not initialized.
+ template <typename I, typename V, typename F2, typename F4>
+ mln_ch_value(I, V)
+ immerse_with(const Image<I>& ima, const V& new_value_type,
const Function_vv2v<F2>& f_1faces,
const Function_vvvv2v<F4>& f_0faces);
@@ -106,6 +117,35 @@ namespace mln
return output;
}
+ template <typename I, typename V, typename F2, typename F4>
+ mln_ch_value(I, V)
+ immerse_with(const Image<I>& ima_, const V& new_value_type,
+ const V& default_value,
+ const Function_vv2v<F2>& f_1faces_,
+ const Function_vvvv2v<F4>& f_0faces_)
+ {
+ trace::entering("mln::world::k1::immerse_with");
+ mln_precondition(exact(ima_).is_valid());
+
+ // FIXME: we cannot write that test because we rely on
+ // safe_convert. So, even though some types may not
+ // have conversions available by default, conversion
+ // may work...
+ //mlc_converts_to(mln_result(F2), V)::check();
+ //mlc_converts_to(mln_result(F4), V)::check();
+
+ const I& ima = exact(ima_);
+ const F2& f_1faces = exact(f_1faces_);
+ const F4& f_0faces = exact(f_0faces_);
+
+ mln_ch_value(I,V) output = k1::immerse(ima, new_value_type, default_value);
+ k1::fill_1_from_2_faces(output, f_1faces);
+ k1::fill_0_from_1_faces(output, f_0faces);
+
+ trace::exiting("mln::world::k1::immerse_with");
+ return output;
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::world::k1
diff --git a/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
b/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
index 8bf7f84..0f8d71c 100644
--- a/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
+++ b/milena/mln/world/k2/fill_non_primary_from_primary_2_faces.hh
@@ -116,25 +116,27 @@ namespace mln
const F2& f_intermediate = exact(f_intermediate_);
const F4& f_center = exact(f_center_);
+ typedef mln_value(I) VI;
typedef mln_argument(F2) V2;
typedef mln_argument(F4) V4;
- mln_piter(I) p(ima.domain());
+ mln_box(I) b = ima.domain();
+ mln_piter(I) p(b);
for_all(p)
if (is_non_primary_2_face_vertical(p))
{
- ima(p) = kn::safe_cast(
+ ima(p) = kn::safe_cast_to<VI>(
f_intermediate(kn::safe_cast_to<V2>(ima(p + 2 * left)),
kn::safe_cast_to<V2>(ima(p + 2 * right))));
}
else if (is_non_primary_2_face_horizontal(p))
{
- ima(p) = kn::safe_cast(
+ ima(p) = kn::safe_cast_to<VI>(
f_intermediate(kn::safe_cast_to<V2>(ima(p + 2 * up)),
kn::safe_cast_to<V2>(ima(p + 2 * down))));
}
else if (is_non_primary_2_face_center(p))
{
- ima(p) = kn::safe_cast(
+ ima(p) = kn::safe_cast_to<VI>(
f_center(kn::safe_cast_to<V4>(ima(p + 2 * up_left)),
kn::safe_cast_to<V4>(ima(p + 2 * up_right)),
kn::safe_cast_to<V4>(ima(p + 2 * down_left)),
diff --git a/milena/mln/world/kn/fill_1_from_2_faces.hh
b/milena/mln/world/kn/fill_1_from_2_faces.hh
index 3a8b93c..0c024b3 100644
--- a/milena/mln/world/kn/fill_1_from_2_faces.hh
+++ b/milena/mln/world/kn/fill_1_from_2_faces.hh
@@ -34,7 +34,6 @@
# include <mln/world/kn/is_1_face_vertical.hh>
# include <mln/world/kn/is_1_face_horizontal.hh>
-
namespace mln
{
@@ -69,6 +68,12 @@ namespace mln
template <typename I, typename A>
void fill_1_from_2_faces(Image<I>& inout, const Accumulator<A>&
accu);
+ /// \overload
+ /// This implementation duplicate 2-faces in border in order to
+ /// be able to read values outside of the image domain.
+ template <typename I, typename F>
+ void fill_1_from_2_faces(Image<I>& inout, const
Function_vv2v<F>& f);
+
# ifndef MLN_INCLUDE_ONLY
@@ -83,11 +88,9 @@ namespace mln
mln_precondition(exact(inout_).is_valid());
I& inout = exact(inout_);
- (void) accu_;
- A accu = A();
- mln_box(I) b = inout.domain();
- mln_piter(I) p(b);
+ A accu(exact(accu_));
+ mln_piter(I) p(inout.domain());
for_all(p)
if (kn::is_1_face_vertical(p))
{
@@ -112,6 +115,26 @@ namespace mln
}
+ template <typename I, typename F>
+ void fill_1_from_2_faces(Image<I>& inout_, const
Function_vv2v<F>& f_)
+ {
+ trace::entering("mln::world::kn::fill_1_from_2_faces");
+
+ mln_precondition(exact(inout_).is_valid());
+ I& inout = exact(inout_);
+ const F& f = exact(f_);
+
+ mln_piter(I) p(inout.domain());
+ for_all(p)
+ if (kn::is_1_face_vertical(p))
+ inout(p) = f(inout(p + left), inout(p + right));
+ else if (is_1_face_horizontal(p))
+ inout(p) = f(inout(p + up), inout(p + down));
+
+ trace::exiting("mln::world::kn::fill_1_from_2_faces");
+ }
+
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::world::kn
diff --git a/milena/mln/world/kn/fill_1_from_aux_2_faces.hh
b/milena/mln/world/kn/fill_1_from_aux_2_faces.hh
index b9cbffe..987e3b7 100644
--- a/milena/mln/world/kn/fill_1_from_aux_2_faces.hh
+++ b/milena/mln/world/kn/fill_1_from_aux_2_faces.hh
@@ -35,7 +35,6 @@
# include <mln/world/kn/is_1_face_vertical.hh>
# include <mln/world/kn/is_1_face_horizontal.hh>
-
namespace mln
{
@@ -52,6 +51,11 @@ namespace mln
\param[in] aux A 2D image with the same domain as \p inout.
\param[in,out] f A functor computing a result from two values.
+ Warning: \p aux borders must have been initialized with
+ kn::border::duplicate_2_faces or have been immersed in Kn in
+ order to get valid values for 1-faces located in the
+ inner-border.
+
This function use the following neighborhoods:
* In case of vertical 1 faces:
@@ -71,7 +75,7 @@ namespace mln
*/
template <typename I, typename J, typename F>
void fill_1_from_aux_2_faces(Image<I>& inout, const Image<J>&
aux,
- Function_vv2v<F>& f);
+ Function_vv2v<F>& f);
/// \overload
template <typename I, typename J, typename A>
@@ -87,7 +91,7 @@ namespace mln
template <typename I, typename J, typename F>
void fill_1_from_aux_2_faces(Image<I>& inout_, const Image<J>&
aux_,
- Function_vv2v<F>& f_)
+ Function_vv2v<F>& f_)
{
trace::entering("mln::world::kn::fill_1_from_aux_2_faces");
@@ -111,7 +115,7 @@ namespace mln
template <typename I, typename J, typename A>
void fill_1_from_aux_2_faces(Image<I>& inout_, const Image<J>&
aux_,
- const Accumulator<A>& accu_)
+ const Accumulator<A>& accu_)
{
trace::entering("mln::world::kn::fill_1_from_aux_2_faces");
@@ -120,9 +124,8 @@ namespace mln
mln_precondition(exact(inout_).domain() == exact(aux_).domain());
I& inout = exact(inout_);
const J& aux = exact(aux_);
- (void) accu_;
- A accu = A();
+ A accu(exact(accu_));
mln_box(I) b = inout.domain();
mln_piter(I) p(b);
for_all(p)
diff --git a/milena/mln/world/kn/internal/get_background_label.hh
b/milena/mln/world/kn/internal/get_background_label.hh
index a993b5a..bdd2bf0 100644
--- a/milena/mln/world/kn/internal/get_background_label.hh
+++ b/milena/mln/world/kn/internal/get_background_label.hh
@@ -32,6 +32,10 @@
# define MLN_WORLD_KN_INTERNAL_GET_BACKGROUND_LABEL_HH
# include <mln/core/concept/image.hh>
+# include <mln/geom/min_row.hh>
+# include <mln/geom/min_col.hh>
+# include <mln/geom/max_row.hh>
+# include <mln/geom/max_col.hh>
namespace mln
{
@@ -63,12 +67,11 @@ namespace mln
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();
+ min_row = geom::min_row(lab),
+ max_row = geom::max_row(lab),
+ min_col = geom::min_col(lab),
+ max_col = geom::max_col(lab);
has_bg_label = false;
for (def::coord col = min_col; col <= max_col; ++col)
diff --git a/milena/tests/world/k1/immerse_with.cc
b/milena/tests/world/k1/immerse_with.cc
index 3b7e8fc..c6d4af7 100644
--- a/milena/tests/world/k1/immerse_with.cc
+++ b/milena/tests/world/k1/immerse_with.cc
@@ -29,8 +29,8 @@
#include <mln/world/k1/immerse_with.hh>
#include <mln/data/compare.hh>
#include <mln/border/fill.hh>
-#include <mln/fun/vv2v/max.hh>
-#include <mln/fun/vvvv2v/max.hh>
+#include <mln/fun/vv2v/sum.hh>
+#include <mln/fun/vvvv2v/sum.hh>
int main()
{
@@ -41,22 +41,25 @@ int main()
{3, 4}
};
image2d<int> ima = make::image(ivals);
- border::fill(ima, 0); // Make sure there is not border effect.
+ border::fill(ima, 0); // FIXME: to be removed when 0-face
+ // computation will handle borders.
int fvals[][5] = {
- {1, 1, 2, 2, 2},
- {1, 1, 2, 2, 2},
- {3, 3, 4, 4, 4},
- {3, 3, 4, 4, 4},
- {3, 3, 4, 4, 4}
+ {0, 2, 0, 4, 0},
+ {2, 1, 3, 2, 4},
+ {0, 4, 20, 6, 0},
+ {6, 3, 7, 4, 8},
+ {0, 6, 0, 8, 0}
};
image2d<int> ref = make::image(fvals, point2d(-1,-1));
+
{
image2d<long>
- immersed = world::k1::immerse_with(ima, long(),
- fun::vv2v::max<long>(),
- fun::vvvv2v::max<long>());
+ immersed = world::k1::immerse_with(ima, long(), 0l,
+ fun::vv2v::sum<long>(),
+ fun::vvvv2v::sum<long>());
+
mln_assertion(immersed == ref);
}
diff --git a/milena/tests/world/k2/fill_non_primary_from_primary_2_faces.cc
b/milena/tests/world/k2/fill_non_primary_from_primary_2_faces.cc
index c83a613..7a17f80 100644
--- a/milena/tests/world/k2/fill_non_primary_from_primary_2_faces.cc
+++ b/milena/tests/world/k2/fill_non_primary_from_primary_2_faces.cc
@@ -26,41 +26,12 @@
/// \file
#include <mln/core/image/image2d.hh>
-#include <mln/make/box2d.hh>
#include <mln/data/compare.hh>
#include <mln/accu/math/sum.hh>
+#include <mln/fun/vv2v/sum.hh>
+#include <mln/fun/vvvv2v/sum.hh>
#include <mln/world/k2/fill_non_primary_from_primary_2_faces.hh>
-namespace mln
-{
-
- struct sum4_t : Function_vvvv2v<sum4_t>
- {
- typedef int argument;
- typedef int result;
-
- int operator()(const int& v1, const int& v2, const int& v3, const
int& v4) const
- {
- return v1 + v2 + v3 + v4;
- }
-
- };
-
- struct sum2_t : Function_vv2v<sum2_t>
- {
- typedef int argument;
- typedef int result;
-
- int operator()(const int& v1, const int& v2) const
- {
- return v1 + v2;
- }
-
- };
-
-}
-
-
int main()
{
@@ -98,7 +69,9 @@ int main()
// Overload with function
{
image2d<int> ima = make::image(vals, point2d(-1,-1));
- world::k2::fill_non_primary_from_primary_2_faces(ima, sum2_t(), sum4_t());
+ fun::vv2v::sum<int> f2;
+ fun::vvvv2v::sum<int> f4;
+ world::k2::fill_non_primary_from_primary_2_faces(ima, f2, f4);
mln_assertion(ref == ima);
}
diff --git a/milena/tests/world/kn/accu/max_interval.cc
b/milena/tests/world/kn/accu/max_interval.cc
index 9686ad7..304266a 100644
--- a/milena/tests/world/kn/accu/max_interval.cc
+++ b/milena/tests/world/kn/accu/max_interval.cc
@@ -40,12 +40,6 @@ void doit(const mln::value::interval<T>& inter)
}
{
- M m;
- m.init();
- mln_assertion(m.to_result() == mln_min(T));
- }
-
- {
M m(inter);
m.init();
m.take(6);
@@ -105,4 +99,11 @@ int main()
doit(inter);
}
+ // Checking default return value.
+ {
+ mln::world::kn::accu::max_interval<int> m;
+ m.init();
+ mln_assertion(m.to_result() == mln_min(int));
+ }
+
}
diff --git a/milena/tests/world/kn/accu/min_interval.cc
b/milena/tests/world/kn/accu/min_interval.cc
index 7b5a0e2..84c5bd5 100644
--- a/milena/tests/world/kn/accu/min_interval.cc
+++ b/milena/tests/world/kn/accu/min_interval.cc
@@ -40,12 +40,6 @@ void doit(const mln::value::interval<T>& inter)
}
{
- M m;
- m.init();
- mln_assertion(m.to_result() == mln_max(T));
- }
-
- {
M m(inter);
m.init();
m.take(6);
@@ -105,4 +99,11 @@ int main()
doit(inter);
}
+ // Checking default return value.
+ {
+ mln::world::kn::accu::min_interval<int> m;
+ m.init();
+ mln_assertion(m.to_result() == mln_max(int));
+ }
+
}
--
1.7.2.5