Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
30 Sep '09
* mln/core/internal/complex_window_base.hh: Add missing inline
keywords.
(complex_window_base<D, G, F, B, E>::geom): New typedef.
(complex_window_base<D, G, F, B, E>::is_valid): Improve
documentation.
---
milena/ChangeLog | 10 ++++++++++
milena/mln/core/internal/complex_window_base.hh | 8 +++++++-
2 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3daaaa6..43d281c 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,13 @@
+2009-09-28 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Miscellaneous corrections to complex_window_base.
+
+ * mln/core/internal/complex_window_base.hh: Add missing inline
+ keywords.
+ (complex_window_base<D, G, F, B, E>::geom): New typedef.
+ (complex_window_base<D, G, F, B, E>::is_valid): Improve
+ documentation.
+
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
Add non-centered complex windows.
diff --git a/milena/mln/core/internal/complex_window_base.hh b/milena/mln/core/internal/complex_window_base.hh
index 559c9de..df08e6d 100644
--- a/milena/mln/core/internal/complex_window_base.hh
+++ b/milena/mln/core/internal/complex_window_base.hh
@@ -92,6 +92,8 @@ namespace mln
public:
/// Associated types.
/// \{
+ /// The geometry of the complex.
+ typedef G geom;
/// The type of psite corresponding to the window.
typedef complex_psite<D, G> psite;
/// The type of site corresponding to the window.
@@ -130,7 +132,7 @@ namespace mln
/// Is this window centered?
bool is_centered() const;
- /// Return true by default.
+ /// Is this window valid ? (Return true by default.)
bool is_valid() const;
/// \}
@@ -143,6 +145,7 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
template <unsigned D, typename G, typename F, typename B, typename E>
+ inline
complex_window_base<D, G, F, B, E>::complex_window_base(bool is_centered)
: is_centered_(is_centered)
{
@@ -150,6 +153,7 @@ namespace mln
template <unsigned D, typename G, typename F, typename B, typename E>
+ inline
bool
complex_window_base<D, G, F, B, E>::is_empty() const
{
@@ -157,6 +161,7 @@ namespace mln
}
template <unsigned D, typename G, typename F, typename B, typename E>
+ inline
bool
complex_window_base<D, G, F, B, E>::is_centered() const
{
@@ -164,6 +169,7 @@ namespace mln
}
template <unsigned D, typename G, typename F, typename B, typename E>
+ inline
bool
complex_window_base<D, G, F, B, E>::is_valid() const
{
--
1.6.3.1
1
0
* mln/core/image/complex_windows.hh (mln_gen_complex_window):
New (generator) macro.
(complex_lower_window)
(complex_higher_window)
(complex_lower_higher_window)
(complex_lower_dim_connected_n_face_window)
(complex_higher_dim_connected_n_face_window)
(complex_m_face_window):
New classes.
---
milena/ChangeLog | 14 ++++++
milena/mln/core/image/complex_windows.hh | 69 ++++++++++++++++++++++++++++-
2 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 2da5700..3daaaa6 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,19 @@
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+ Add non-centered complex windows.
+
+ * mln/core/image/complex_windows.hh (mln_gen_complex_window):
+ New (generator) macro.
+ (complex_lower_window)
+ (complex_higher_window)
+ (complex_lower_higher_window)
+ (complex_lower_dim_connected_n_face_window)
+ (complex_higher_dim_connected_n_face_window)
+ (complex_m_face_window):
+ New classes.
+
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
Prepare the factoring of complex windows generators.
* mln/core/image/complex_windows.hh
diff --git a/milena/mln/core/image/complex_windows.hh b/milena/mln/core/image/complex_windows.hh
index c2c21fb..b409282 100644
--- a/milena/mln/core/image/complex_windows.hh
+++ b/milena/mln/core/image/complex_windows.hh
@@ -29,11 +29,10 @@
/// \file
/// \brief Definitions of some windows of complex images.
+# include <mln/core/internal/complex_window_base.hh>
# include <mln/core/internal/complex_window_p_base.hh>
-# include <mln/topo/adj_lower_face_iter.hh>
-# include <mln/topo/adj_higher_face_iter.hh>
-# include <mln/topo/adj_lower_higher_face_iter.hh>
+# include <mln/topo/complex_iterators.hh>
/** \brief Generate a complex window class, as well as its traits,
@@ -77,6 +76,28 @@
}
+/** \brief Generate a (non-centered) complex window class, as well as
+ its traits.
+
+ \param Win The name of the class to generate.
+ \param Fwd_Complex_Iter The underlying forward iterator type.
+ \param Bkd_Complex_Iter The underlying backward iterator type.
+
+ The generated class inherits from
+
+ mln::internal::complex_window_base< D, G,
+ Fwd_Complex_Iter<D>,
+ Bkd_Complex_Iter<D>,
+ Win <D, G> >
+
+ where D and G are template parameters of the generated Win class. */
+# define mln_gen_complex_window(Win, Fwd_Complex_Iter, Bkd_Complex_Iter) \
+ mln_gen_complex_window_with_base(Win, \
+ Fwd_Complex_Iter, \
+ Bkd_Complex_Iter, \
+ mln::internal::complex_window_base)
+
+
/** \brief Generate a centered complex window class, as well as its traits.
\param Win The name of the class to generate.
@@ -102,6 +123,47 @@
namespace mln
{
+ /*-----------------------.
+ | Non-centered windows. |
+ `-----------------------*/
+
+ /// \brief Window centered on an n-face of complex returning its
+ /// adjacent (n-1)-faces.
+ mln_gen_complex_window(complex_lower_window,
+ topo::adj_lower_face_fwd_iter,
+ topo::adj_lower_face_bkd_iter);
+
+ /// \brief Window centered on an n-face of complex returning its
+ /// adjacent (n+1)-faces.
+ mln_gen_complex_window(complex_higher_window,
+ topo::adj_higher_face_fwd_iter,
+ topo::adj_higher_face_bkd_iter);
+
+ /// \brief Window centered on an n-face of complex returning its
+ /// adjacent (n-1)-faces and (n+1)-faces.
+ mln_gen_complex_window(complex_lower_higher_window,
+ topo::adj_lower_higher_face_fwd_iter,
+ topo::adj_lower_higher_face_bkd_iter);
+
+ /// \brief Window centered on an n-face of complex returning the
+ /// n-faces sharing an (n-1)-face with the center n-face.
+ mln_gen_complex_window(complex_lower_dim_connected_n_face_window,
+ topo::adj_lower_dim_connected_n_face_fwd_iter,
+ topo::adj_lower_dim_connected_n_face_bkd_iter);
+
+ /// \brief Window centered on an n-face of complex returning the
+ /// n-faces sharing an (n+1)-face with the center n-face.
+ mln_gen_complex_window(complex_higher_dim_connected_n_face_window,
+ topo::adj_higher_dim_connected_n_face_fwd_iter,
+ topo::adj_higher_dim_connected_n_face_bkd_iter);
+
+ /// \brief Window centered on an n-face of complex returning
+ /// the m-faces transitively adjacent to this center n-face.
+ mln_gen_complex_window(complex_m_face_window,
+ topo::adj_m_face_fwd_iter,
+ topo::adj_m_face_bkd_iter);
+
+
/*-------------------.
| Centered windows. |
`-------------------*/
@@ -149,6 +211,7 @@ namespace mln
} // end of namespace mln
# undef mln_gen_complex_window_p
+# undef mln_gen_complex_window
# undef mln_gen_complex_window_from_base
#endif // ! MLN_CORE_IMAGE_COMPLEX_WINDOWS_HH
--
1.6.3.1
1
0
30 Sep '09
* mln/core/image/complex_windows.hh
(mln_gen_complex_window_with_base): New macro.
Use it to factor...
(mln_gen_complex_window_p): ...this macro.
---
milena/ChangeLog | 9 +++++
milena/mln/core/image/complex_windows.hh | 51 +++++++++++++++++++++--------
2 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 5d91401..2da5700 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,14 @@
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+ Prepare the factoring of complex windows generators.
+
+ * mln/core/image/complex_windows.hh
+ (mln_gen_complex_window_with_base): New macro.
+ Use it to factor...
+ (mln_gen_complex_window_p): ...this macro.
+
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
Rename mln::complex_m_face_window as mln::complex_m_face_window_p.
* mln/core/image/complex_windows.hh: Here.
diff --git a/milena/mln/core/image/complex_windows.hh b/milena/mln/core/image/complex_windows.hh
index 30dcadc..c2c21fb 100644
--- a/milena/mln/core/image/complex_windows.hh
+++ b/milena/mln/core/image/complex_windows.hh
@@ -35,21 +35,21 @@
# include <mln/topo/adj_higher_face_iter.hh>
# include <mln/topo/adj_lower_higher_face_iter.hh>
-/** \brief Generate a centered complex window class, as well as its traits.
+
+/** \brief Generate a complex window class, as well as its traits,
+ using a given base class.
\param Win The name of the class to generate.
\param Fwd_Complex_Iter The underlying forward iterator type.
\param Bkd_Complex_Iter The underlying backward iterator type.
+ \param Base The name of the base class, with no parameter.
The generated class inherits from
- mln:: internal::complex_window_p_base< D, G,
- Fwd_Complex_Iter<D>,
- Bkd_Complex_Iter<D>,
- Win <D, G> >
+ Base < D, G, Fwd_Complex_Iter<D>, Bkd_Complex_Iter<D>, Win <D, G> >
where D and G are template parameters of the generated Win class. */
-# define mln_gen_complex_window_p(Win, Fwd_Complex_Iter, Bkd_Complex_Iter) \
+# define mln_gen_complex_window_with_base(Win, Fwd_Complex_Iter, Bkd_Complex_Iter, Base) \
/* Forward declaration. */ \
template <unsigned D, typename G> struct Win; \
\
@@ -58,10 +58,10 @@
{ \
template <unsigned D, typename G> \
struct window_< Win <D, G> > \
- : window_< mln::internal::complex_window_p_base< D, G, \
- Fwd_Complex_Iter<D>, \
- Bkd_Complex_Iter <D>, \
- Win <D, G> > > \
+ : window_< Base < D, G, \
+ Fwd_Complex_Iter<D>, \
+ Bkd_Complex_Iter <D>, \
+ Win <D, G> > > \
{ \
}; \
} \
@@ -69,14 +69,36 @@
/* Definition. */ \
template <unsigned D, typename G> \
struct Win \
- : internal::complex_window_p_base< D, G, \
- Fwd_Complex_Iter <D>, \
- Bkd_Complex_Iter <D>, \
- Win <D, G> > \
+ : Base < D, G, \
+ Fwd_Complex_Iter <D>, \
+ Bkd_Complex_Iter <D>, \
+ Win <D, G> > \
{ \
}
+/** \brief Generate a centered complex window class, as well as its traits.
+
+ \param Win The name of the class to generate.
+ \param Fwd_Complex_Iter The underlying forward iterator type.
+ \param Bkd_Complex_Iter The underlying backward iterator type.
+
+ The generated class inherits from
+
+ mln::internal::complex_window_p_base< D, G,
+ Fwd_Complex_Iter<D>,
+ Bkd_Complex_Iter<D>,
+ Win <D, G> >
+
+ where D and G are template parameters of the generated Win class. */
+# define mln_gen_complex_window_p(Win, Fwd_Complex_Iter, Bkd_Complex_Iter) \
+ mln_gen_complex_window_with_base(Win, \
+ Fwd_Complex_Iter, \
+ Bkd_Complex_Iter, \
+ mln::internal::complex_window_p_base)
+
+
+
namespace mln
{
@@ -127,5 +149,6 @@ namespace mln
} // end of namespace mln
# undef mln_gen_complex_window_p
+# undef mln_gen_complex_window_from_base
#endif // ! MLN_CORE_IMAGE_COMPLEX_WINDOWS_HH
--
1.6.3.1
1
0
[PATCH 04/22] Rename mln::complex_m_face_window as mln::complex_m_face_window_p.
by Roland Levillain 30 Sep '09
by Roland Levillain 30 Sep '09
30 Sep '09
* mln/core/image/complex_windows.hh: Here.
---
milena/ChangeLog | 6 ++++++
milena/mln/core/image/complex_windows.hh | 7 ++++---
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index c8c8fca..5d91401 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,11 @@
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+ Rename mln::complex_m_face_window as mln::complex_m_face_window_p.
+
+ * mln/core/image/complex_windows.hh: Here.
+
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
Refactor complex_window_p_base using complex_window_base.
* mln/core/internal/complex_window_p_base.hh
diff --git a/milena/mln/core/image/complex_windows.hh b/milena/mln/core/image/complex_windows.hh
index 906ac16..30dcadc 100644
--- a/milena/mln/core/image/complex_windows.hh
+++ b/milena/mln/core/image/complex_windows.hh
@@ -117,9 +117,10 @@ namespace mln
topo::adj_higher_dim_connected_n_face_fwd_iter,
topo::adj_higher_dim_connected_n_face_bkd_iter);
- /// \brief Window centered on an n-face of complex returning
- /// the m-faces transitively adjacent to this center n-face.
- mln_gen_complex_window_p(complex_m_face_window,
+ /// \brief Window centered on an n-face of complex returning the
+ /// m-faces transitively adjacent to this center n-face, as well as
+ /// this center n-face.
+ mln_gen_complex_window_p(complex_m_face_window_p,
topo::adj_m_face_fwd_iter,
topo::adj_m_face_bkd_iter);
--
1.6.3.1
1
0
[PATCH 03/22] Refactor complex_window_p_base using complex_window_base.
by Roland Levillain 30 Sep '09
by Roland Levillain 30 Sep '09
30 Sep '09
* mln/core/internal/complex_window_p_base.hh
(complex_window_p_base): Inherit from complex_window_p_base.
(trait::window_< mln::internal::complex_window_p_base<D, G, F, B, E>)
Adjust traits.
Remove all typedefs and methods.
(complex_window_p_base::complex_window_p_base): New ctor.
---
milena/ChangeLog | 15 +++
milena/mln/core/image/complex_windows.hh | 46 +++++----
milena/mln/core/internal/complex_window_p_base.hh | 103 ++++-----------------
3 files changed, 59 insertions(+), 105 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index aa0ac48..c8c8fca 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,20 @@
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+ Refactor complex_window_p_base using complex_window_base.
+
+ * mln/core/internal/complex_window_p_base.hh
+ (complex_window_p_base): Inherit from complex_window_p_base.
+ (trait::window_< mln::internal::complex_window_p_base<D, G, F, B, E>)
+ Adjust traits.
+ Remove all typedefs and methods.
+ (complex_window_p_base::complex_window_p_base): New ctor.
+ * mln/core/image/complex_windows.hh (mln_gen_complex_window):
+ Rename (internal) macro as..
+ (mln_gen_complex_window_p): ...this.
+ Adjust.
+
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
Introduce a base class for general complex windows.
* mln/core/internal/complex_window_base.hh: New.
diff --git a/milena/mln/core/image/complex_windows.hh b/milena/mln/core/image/complex_windows.hh
index 2f22470..906ac16 100644
--- a/milena/mln/core/image/complex_windows.hh
+++ b/milena/mln/core/image/complex_windows.hh
@@ -35,7 +35,7 @@
# include <mln/topo/adj_higher_face_iter.hh>
# include <mln/topo/adj_lower_higher_face_iter.hh>
-/** \brief Generate a complex window class, as well as its traits.
+/** \brief Generate a centered complex window class, as well as its traits.
\param Win The name of the class to generate.
\param Fwd_Complex_Iter The underlying forward iterator type.
@@ -49,7 +49,7 @@
Win <D, G> >
where D and G are template parameters of the generated Win class. */
-# define mln_gen_complex_window(Win, Fwd_Complex_Iter, Bkd_Complex_Iter) \
+# define mln_gen_complex_window_p(Win, Fwd_Complex_Iter, Bkd_Complex_Iter) \
/* Forward declaration. */ \
template <unsigned D, typename G> struct Win; \
\
@@ -80,47 +80,51 @@
namespace mln
{
+ /*-------------------.
+ | Centered windows. |
+ `-------------------*/
+
/// \brief Window centered on an n-face of complex returning its
/// adjacent (n-1)-faces as well as the center n-face.
- mln_gen_complex_window(complex_lower_window_p,
- topo::adj_lower_face_fwd_iter,
- topo::adj_lower_face_bkd_iter);
+ mln_gen_complex_window_p(complex_lower_window_p,
+ topo::adj_lower_face_fwd_iter,
+ topo::adj_lower_face_bkd_iter);
/// \brief Window centered on an n-face of complex returning its
/// adjacent (n+1)-faces as well as the center n-face.
- mln_gen_complex_window(complex_higher_window_p,
- topo::adj_higher_face_fwd_iter,
- topo::adj_higher_face_bkd_iter);
+ mln_gen_complex_window_p(complex_higher_window_p,
+ topo::adj_higher_face_fwd_iter,
+ topo::adj_higher_face_bkd_iter);
/// \brief Window centered on an n-face of complex returning its
/// adjacent (n-1)-faces and (n+1)-faces as well as the center
/// n-face.
- mln_gen_complex_window(complex_lower_higher_window_p,
- topo::adj_lower_higher_face_fwd_iter,
- topo::adj_lower_higher_face_bkd_iter);
+ mln_gen_complex_window_p(complex_lower_higher_window_p,
+ topo::adj_lower_higher_face_fwd_iter,
+ topo::adj_lower_higher_face_bkd_iter);
/// \brief Window centered on an n-face of complex returning the
/// n-faces sharing an (n-1)-face with the center n-face, as well as
/// this center n-face.
- mln_gen_complex_window(complex_lower_dim_connected_n_face_window_p,
- topo::adj_lower_dim_connected_n_face_fwd_iter,
- topo::adj_lower_dim_connected_n_face_bkd_iter);
+ mln_gen_complex_window_p(complex_lower_dim_connected_n_face_window_p,
+ topo::adj_lower_dim_connected_n_face_fwd_iter,
+ topo::adj_lower_dim_connected_n_face_bkd_iter);
/// \brief Window centered on an n-face of complex returning the
/// n-faces sharing an (n+1)-face with the center n-face, as well as
/// this center n-face.
- mln_gen_complex_window(complex_higher_dim_connected_n_face_window_p,
- topo::adj_higher_dim_connected_n_face_fwd_iter,
- topo::adj_higher_dim_connected_n_face_bkd_iter);
+ mln_gen_complex_window_p(complex_higher_dim_connected_n_face_window_p,
+ topo::adj_higher_dim_connected_n_face_fwd_iter,
+ topo::adj_higher_dim_connected_n_face_bkd_iter);
/// \brief Window centered on an n-face of complex returning
/// the m-faces transitively adjacent to this center n-face.
- mln_gen_complex_window(complex_m_face_window,
- topo::adj_m_face_fwd_iter,
- topo::adj_m_face_bkd_iter);
+ mln_gen_complex_window_p(complex_m_face_window,
+ topo::adj_m_face_fwd_iter,
+ topo::adj_m_face_bkd_iter);
} // end of namespace mln
-# undef mln_gen_complex_window
+# undef mln_gen_complex_window_p
#endif // ! MLN_CORE_IMAGE_COMPLEX_WINDOWS_HH
diff --git a/milena/mln/core/internal/complex_window_p_base.hh b/milena/mln/core/internal/complex_window_p_base.hh
index 3f04a6f..65e79e9 100644
--- a/milena/mln/core/internal/complex_window_p_base.hh
+++ b/milena/mln/core/internal/complex_window_p_base.hh
@@ -31,22 +31,14 @@
/// of a complex, based on a pair of (forward and backward) complex
/// iterators. The center (site) is part of the window.
-# include <mln/core/concept/window.hh>
-# include <mln/core/site_set/complex_psite.hh>
-# include <mln/core/image/complex_window_piter.hh>
+# include <mln/core/internal/complex_window_base.hh>
# include <mln/topo/centered_iter_adapter.hh>
-// FIXME: Factor with mln::internal::complex_neighborhood_base.
namespace mln
{
- // Forward declarations.
- template <typename I, typename G, typename W>
- class complex_window_fwd_piter;
- template <typename I, typename G, typename W>
- class complex_window_bkd_piter;
namespace internal
{
@@ -60,10 +52,12 @@ namespace mln
template <unsigned D, typename G, typename F, typename B, typename E>
struct window_< mln::internal::complex_window_p_base<D, G, F, B, E> >
+ : window_< mln::internal::complex_window_base
+ < D, G,
+ mln::topo::centered_fwd_iter_adapter<D, F>,
+ mln::topo::centered_bkd_iter_adapter<D, B>,
+ E > >
{
- typedef trait::window::size::unknown size;
- typedef trait::window::support::irregular support;
- typedef trait::window::definition::varying definition;
};
} // end of namespace mln::trait
@@ -81,64 +75,20 @@ namespace mln
\tparam B The underlying backward iterator type.
\tparam E The exact type. */
template <unsigned D, typename G, typename F, typename B, typename E>
- class complex_window_p_base : public Window<E>
+ class complex_window_p_base
+ : public complex_window_base
+ < D, G,
+ mln::topo::centered_fwd_iter_adapter<D, F>,
+ mln::topo::centered_bkd_iter_adapter<D, B>,
+ E >
{
- /// The complex iterators <em>on the adjacent faces only</em>
- /// (without the center point).
- /// \{
- typedef F adj_only_fwd_iter_;
- typedef B adj_only_bkd_iter_;
- /// \}
+ typedef complex_window_base< D, G,
+ topo::centered_fwd_iter_adapter<D, F>,
+ topo::centered_bkd_iter_adapter<D, B>,
+ E > super;
public:
- /// The associated complex iterators.
- /// \{
- typedef topo::centered_fwd_iter_adapter<D, adj_only_fwd_iter_>
- complex_fwd_iter;
-
- typedef topo::centered_bkd_iter_adapter<D, adj_only_bkd_iter_>
- complex_bkd_iter;
- /// \}
-
- public:
- /// Associated types.
- /// \{
- /// The type of psite corresponding to the window.
- typedef complex_psite<D, G> psite;
- /// The type of site corresponding to the window.
- typedef mln_site(psite) site;
-
- // FIXME: This is a dummy value.
- typedef void dpsite;
-
- /// \brief Site_Iterator type to browse the psites of the window
- /// w.r.t. the ordering of vertices.
- typedef
- complex_window_fwd_piter<complex_fwd_iter, G, E> fwd_qiter;
-
- /// \brief Site_Iterator type to browse the psites of the window
- /// w.r.t. the reverse ordering of vertices.
- typedef
- complex_window_bkd_piter<complex_bkd_iter, G, E> bkd_qiter;
-
- /// The default qiter type.
- typedef fwd_qiter qiter;
- /// \}
-
- public:
- /// Services.
- /// \{
- /* FIXME: mln::morpho::dilation requires these method from models
- of concept Window, but Window does not list them in its
- requirements. Who's guilty: morpho::dilation or Window? */
- /// Is this window empty? (Always returns \c false).
- bool is_empty() const;
- /// Is this window centered? (Always returns \c true).
- bool is_centered() const;
-
- /// Return true by default.
- bool is_valid() const;
- /// \}
+ complex_window_p_base();
};
@@ -146,24 +96,9 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
template <unsigned D, typename G, typename F, typename B, typename E>
- bool
- complex_window_p_base<D, G, F, B, E>::is_empty() const
- {
- return false;
- }
-
- template <unsigned D, typename G, typename F, typename B, typename E>
- bool
- complex_window_p_base<D, G, F, B, E>::is_centered() const
- {
- return true;
- }
-
- template <unsigned D, typename G, typename F, typename B, typename E>
- bool
- complex_window_p_base<D, G, F, B, E>::is_valid() const
+ complex_window_p_base<D, G, F, B, E>::complex_window_p_base()
+ : super(true)
{
- return true;
}
# endif // ! MLN_INCLUDE_ONLY
--
1.6.3.1
1
0
30 Sep '09
* mln/core/internal/complex_window_base.hh: New.
---
milena/ChangeLog | 6 +
milena/mln/core/internal/complex_window_base.hh | 179 +++++++++++++++++++++++
2 files changed, 185 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/core/internal/complex_window_base.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index c439a18..aa0ac48 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,11 @@
2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+ Introduce a base class for general complex windows.
+
+ * mln/core/internal/complex_window_base.hh: New.
+
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
Replace ad hoc code by Milena's in apps/graph-morpho.
* apps/graph-morpho/morpho.hh
diff --git a/milena/mln/core/internal/complex_window_base.hh b/milena/mln/core/internal/complex_window_base.hh
new file mode 100644
index 0000000..559c9de
--- /dev/null
+++ b/milena/mln/core/internal/complex_window_base.hh
@@ -0,0 +1,179 @@
+// Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_CORE_INTERNAL_COMPLEX_WINDOW_BASE_HH
+# define MLN_CORE_INTERNAL_COMPLEX_WINDOW_BASE_HH
+
+/// \file
+/// \brief Definition of a generic window of the face of a complex,
+/// based on a pair of (forward and backward) complex iterators.
+
+# include <mln/core/concept/window.hh>
+# include <mln/core/site_set/complex_psite.hh>
+# include <mln/core/image/complex_window_piter.hh>
+
+# include <mln/topo/centered_iter_adapter.hh>
+
+// FIXME: Factor with mln::internal::complex_neighborhood_base.
+
+
+namespace mln
+{
+ // Forward declarations.
+ template <typename I, typename G, typename W>
+ class complex_window_fwd_piter;
+ template <typename I, typename G, typename W>
+ class complex_window_bkd_piter;
+
+ namespace internal
+ {
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ class complex_window_base;
+ }
+
+
+ namespace trait
+ {
+
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ struct window_< mln::internal::complex_window_base<D, G, F, B, E> >
+ {
+ typedef trait::window::size::unknown size;
+ typedef trait::window::support::irregular support;
+ typedef trait::window::definition::varying definition;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace internal
+ {
+ /** \brief Generic window centered on the face of a complex, based
+ on an pair of (forward and backward) complex iterators. The
+ center (site) is part of the window.
+
+ \tparam D The dimension of the complex.
+ \tparam G The type of the geometry functor of the complex.
+ \tparam F The underlying forward iterator type.
+ \tparam B The underlying backward iterator type.
+ \tparam E The exact type. */
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ class complex_window_base : public Window<E>
+ {
+ public:
+ /// The associated complex iterators.
+ /// \{
+ typedef F complex_fwd_iter;
+ typedef B complex_bkd_iter;
+ /// \}
+
+ public:
+ /// Associated types.
+ /// \{
+ /// The type of psite corresponding to the window.
+ typedef complex_psite<D, G> psite;
+ /// The type of site corresponding to the window.
+ typedef mln_site(psite) site;
+
+ // FIXME: This is a dummy value.
+ typedef void dpsite;
+
+ /* FIXME: Ideally, the `is_centered' information should be
+ fetched from the iterators, but that's not an straighforward
+ task. */
+ complex_window_base(bool is_centered = false);
+
+ /// \brief Site_Iterator type to browse the psites of the window
+ /// w.r.t. the ordering of vertices.
+ typedef
+ complex_window_fwd_piter<complex_fwd_iter, G, E> fwd_qiter;
+
+ /// \brief Site_Iterator type to browse the psites of the window
+ /// w.r.t. the reverse ordering of vertices.
+ typedef
+ complex_window_bkd_piter<complex_bkd_iter, G, E> bkd_qiter;
+
+ /// The default qiter type.
+ typedef fwd_qiter qiter;
+ /// \}
+
+ public:
+ /// Services.
+ /// \{
+ /* FIXME: mln::morpho::dilation requires these method from models
+ of concept Window, but Window does not list them in its
+ requirements. Who's guilty: morpho::dilation or Window? */
+ /// Is this window empty? (Always returns \c false).
+ bool is_empty() const;
+ /// Is this window centered?
+ bool is_centered() const;
+
+ /// Return true by default.
+ bool is_valid() const;
+ /// \}
+
+ private:
+ bool is_centered_;
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ complex_window_base<D, G, F, B, E>::complex_window_base(bool is_centered)
+ : is_centered_(is_centered)
+ {
+ }
+
+
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ bool
+ complex_window_base<D, G, F, B, E>::is_empty() const
+ {
+ return false;
+ }
+
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ bool
+ complex_window_base<D, G, F, B, E>::is_centered() const
+ {
+ return is_centered_;
+ }
+
+ template <unsigned D, typename G, typename F, typename B, typename E>
+ bool
+ complex_window_base<D, G, F, B, E>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::internal
+
+} // end of namespace mln
+
+#endif // ! MLN_CORE_INTERNAL_COMPLEX_WINDOW_BASE_HH
--
1.6.3.1
1
0
30 Sep '09
* apps/graph-morpho/morpho.hh
(dilation(const mln::Image<I>&, const mln::Neighborhood<N>&))
(erosion(const mln::Image<I>&, const mln::Neighborhood<N>&)):
Remove functions.
(dilation_e2v(const mln::Image<I>&))
(erosion_v2e(const mln::Image<I>&))
(erosion_e2v(const mln::Image<I>&))
(dilation_v2e(const mln::Image<I>&)):
Use mln::dilation and mln::erosion instead of these ad hoc
dilation and erosion routines.
Use mln::image_if and mln::extend instead of the ad hoc
image_if_large.
---
milena/ChangeLog | 17 ++
milena/apps/graph-morpho/image_if_large.hh | 307 ----------------------------
milena/apps/graph-morpho/morpho.hh | 107 +++-------
3 files changed, 44 insertions(+), 387 deletions(-)
delete mode 100644 milena/apps/graph-morpho/image_if_large.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3ddf82a..c439a18 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,20 @@
+2009-09-25 Roland Levillain <roland(a)lrde.epita.fr>
+
+ Replace ad hoc code by Milena's in apps/graph-morpho.
+
+ * apps/graph-morpho/morpho.hh
+ (dilation(const mln::Image<I>&, const mln::Neighborhood<N>&))
+ (erosion(const mln::Image<I>&, const mln::Neighborhood<N>&)):
+ Remove functions.
+ (dilation_e2v(const mln::Image<I>&))
+ (erosion_v2e(const mln::Image<I>&))
+ (erosion_e2v(const mln::Image<I>&))
+ (dilation_v2e(const mln::Image<I>&)):
+ Use mln::dilation and mln::erosion instead of these ad hoc
+ dilation and erosion routines.
+ Use mln::image_if and mln::extend instead of the ad hoc
+ image_if_large.
+
2009-09-25 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Add test for dual input and fix p_transformed test.
diff --git a/milena/apps/graph-morpho/image_if_large.hh b/milena/apps/graph-morpho/image_if_large.hh
deleted file mode 100644
index 37c2d63..0000000
--- a/milena/apps/graph-morpho/image_if_large.hh
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright (C) 2007, 2008, 2009 EPITA Research and Development
-// Laboratory (LRDE)
-//
-// This file is part of Olena.
-//
-// Olena is free software: you can redistribute it and/or modify it under
-// the terms of the GNU General Public License as published by the Free
-// Software Foundation, version 2 of the License.
-//
-// Olena is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Olena. If not, see <http://www.gnu.org/licenses/>.
-//
-// As a special exception, you may use this file as part of a free
-// software project without restriction. Specifically, if other files
-// instantiate templates or use macros or inline functions from this
-// file, or you compile this file and link it with other files to produce
-// an executable, this file does not by itself cause the resulting
-// executable to be covered by the GNU General Public License. This
-// exception does not however invalidate any other reasons why the
-// executable file might be covered by the GNU General Public License.
-
-#ifndef APPS_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
-# define APPS_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
-
-/// \file
-///
-/// \brief Definition of a image which domain is restricted by a
-/// function 'site -> Boolean', but where routine has() returns true
-/// for sites of the underlying (morphed) image even if they are not
-/// validating the predicate.
-
-// FIXME: This file is a workaround for the lack of ``tolerant''
-// image_if, but there must be a better way.
-
-# include <mln/core/internal/image_domain_morpher.hh>
-# include <mln/core/site_set/p_if.hh>
-# include <mln/pw/all.hh>
-
-
-namespace mln
-{
-
- // Forward declaration.
- template <typename I, typename F> struct image_if_large;
-
-
- namespace internal
- {
-
- /// Data structure for \c mln::image_if_large<I,F>.
- template <typename I, typename F>
- struct data< image_if_large<I,F> >
- {
- data(I& ima, const F& f);
-
- I ima_;
- p_if<mln_domain(I), F> domain_;
- };
-
- } // end of namespace mln::internal
-
-
- namespace trait
- {
-
- template <typename I, typename F>
- struct image_< image_if_large<I,F> >
- : default_image_morpher< I,
- mln_value(I),
- image_if_large<I,F> >
- {
- typedef trait::image::category::domain_morpher category;
-
- // No extension of domain.
- typedef trait::image::ext_domain::none ext_domain;
- typedef trait::image::ext_value::irrelevant ext_value;
- typedef trait::image::ext_io::irrelevant ext_io;
-
- typedef trait::image::vw_io::none vw_io;
- typedef trait::image::vw_set::none vw_set;
- typedef trait::image::value_alignment::not_aligned value_alignment;
- typedef trait::image::value_storage::disrupted value_storage;
- };
-
- } // end of namespace mln::trait
-
-
-
- /// Image which domain is restricted by a function 'site ->
- /// Boolean', but where routine has() returns true for sites of the
- /// underlying (morphed) image even if they are not validating the
- /// predicate.
- ///
- /// \ingroup modimagedomainmorpher
- //
- template <typename I, typename F>
- struct image_if_large
- : public mln::internal::image_domain_morpher< I,
- p_if<mln_domain(I), F>,
- image_if_large<I, F> >
- {
- typedef image_if_large<I, F> self;
- typedef mln_psite(self) psite;
-
- /// Skeleton.
- typedef image_if_large< tag::image_<I>, tag::function_<F> > skeleton;
-
- /// Constructor without argument.
- image_if_large();
-
- /// Constructor from an image \p ima and a predicate \p f.
- image_if_large(I& ima, const F& f);
-
- void init_(I& ima, const F& f);
-
- /// \brief Redefined psite membership method, returning true for
- /// sites of the underlying (morphed) image even if they are not
- /// validating the predicate.
- ///
- /// This is the only difference with mln::image_if.
- bool has(const psite& p) const;
-
- /// Give the definition domain.
- const p_if<mln_domain(I), F>& domain() const;
-
- /// Const promotion via conversion.
- operator image_if_large<const I, F>() const;
- };
-
-
- // Image || Function_v2b.
-
- /// ima || f creates an image_if_large with the image ima and the function
- /// f.
- //
- template <typename I, typename F>
- image_if_large<I,F>
- operator || (Image<I>& ima, const Function_v2b<F>& f);
-
- /// ima || f creates an image_if_large with the image ima and the function
- /// f.
- //
- template <typename I, typename F>
- image_if_large<const I,F>
- operator || (const Image<I>& ima, const Function_v2b<F>& f);
-
-
-
- template <typename I, typename A>
- image_if_large< const I, fun::C<bool(*)(A)> >
- operator || (const Image<I>& ima, bool (*f)(A) );
-
- template <typename I, typename A>
- image_if_large< I, fun::C<bool(*)(A)> >
- operator || (Image<I>& ima, bool (*f)(A) );
-
-// // Construction helpers.
-
-// template <typename I, typename A>
-// image_if_large< const I, fun::C<bool(*)(A)> >
-// make_image_if_large(const Image<I>& ima, bool (*f)(A) );
-
-// template <typename I, typename A>
-// image_if_large< I, fun::C<bool(*)(A)> >
-// make_image_if_large(Image<I>& ima, bool (*f)(A) );
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
- // init_.
-
- template <typename I, typename F>
- void init_(tag::function_t, F& f, const image_if_large<I,F>& model)
- {
- f = model.domain().predicate();
- }
-
- template <typename I, typename F, typename J>
- void init_(tag::image_t, image_if_large<I,F>& target, const J& model)
- {
- I ima;
- init_(tag::image, ima, exact(model));
- F f;
- init_(tag::function, f, exact(model));
- target.init_(ima, f);
- }
-
- // internal::data< image_if_large<I,F> >
-
- namespace internal
- {
-
- template <typename I, typename F>
- inline
- data< image_if_large<I,F> >::data(I& ima, const F& f)
- : ima_(ima),
- domain_(ima.domain() | f)
- {
- }
-
- }
-
-
- // image_if_large<I,F>
-
- template <typename I, typename F>
- inline
- image_if_large<I,F>::image_if_large()
- {
- }
-
- template <typename I, typename F>
- inline
- image_if_large<I,F>::image_if_large(I& ima, const F& f)
- {
- init_(ima, f);
- }
-
- template <typename I, typename F>
- inline
- void
- image_if_large<I,F>::init_(I& ima, const F& f)
- {
- mln_precondition(! this->is_valid());
- this->data_ = new internal::data< image_if_large<I,F> >(ima, f);
- }
-
- template <typename I, typename F>
- inline
- bool
- image_if_large<I,F>::has(const typename image_if_large<I,F>::psite& p) const
- {
- mln_precondition(exact(this)->is_valid());
- // This method is more tolerant than mln::image_if's one (which
- // returns this->domain().has(p)).
- return this->data_->ima_.has(p);
- }
-
-
- template <typename I, typename F>
- inline
- const p_if<mln_domain(I), F>&
- image_if_large<I,F>::domain() const
- {
- mln_precondition(this->is_valid());
- return this->data_->domain_;
- }
-
- template <typename I, typename F>
- inline
- image_if_large<I,F>::operator image_if_large<const I,F>() const
- {
- mln_precondition(this->is_valid());
- image_if_large<const I,F> tmp(this->data_->ima_,
- this->data_->domain_.predicate());
- return tmp;
- }
-
-
- // Operators.
-
- template <typename I, typename F>
- inline
- image_if_large<I,F>
- operator || (Image<I>& ima, const Function_v2b<F>& f)
- {
- image_if_large<I,F> tmp(exact(ima), exact(f));
- return tmp;
- }
-
- template <typename I, typename F>
- inline
- image_if_large<const I, F>
- operator || (const Image<I>& ima, const Function_v2b<F>& f)
- {
- image_if_large<const I, F> tmp(exact(ima), exact(f));
- return tmp;
- }
-
-
- template <typename I, typename A>
- image_if_large< const I, fun::C<bool(*)(A)> >
- operator || (const Image<I>& ima, bool (*f)(A) )
- {
- return exact(ima) || convert::to_fun(f);
- }
-
- template <typename I, typename A>
- image_if_large< I, fun::C<bool(*)(A)> >
- operator || (Image<I>& ima, bool (*f)(A) )
- {
- return exact(ima) || convert::to_fun(f);
- }
-
-
-# endif // ! MLN_INCLUDE_ONLY
-
-} // end of namespace mln
-
-
-#endif // ! APPS_GRAPH_MORPHO_IMAGE_IF_LARGE_HH
diff --git a/milena/apps/graph-morpho/morpho.hh b/milena/apps/graph-morpho/morpho.hh
index 9a786da..bd883a0 100644
--- a/milena/apps/graph-morpho/morpho.hh
+++ b/milena/apps/graph-morpho/morpho.hh
@@ -41,6 +41,7 @@
# include <mln/core/image/dmorph/image_if.hh>
+# include <mln/core/routine/extend.hh>
# include <mln/core/routine/duplicate.hh>
# include <mln/core/site_set/p_n_faces_piter.hh>
@@ -53,7 +54,8 @@
# include <mln/data/paste.hh>
-# include "apps/graph-morpho/image_if_large.hh"
+# include <mln/morpho/dilation.hh>
+# include <mln/morpho/erosion.hh>
// FIXME: Instead of providing several implementation, move specific
// parts (neighborhoods, etc.) to a graph_traits class, and write
@@ -136,72 +138,6 @@ combine(const mln::Image<I>& vertices, const mln::Image<I>& edges)
| Dilations and erosions. |
`-------------------------*/
-/// A neighborhood-aware and graph-friendly version of the binary dilation.
-template <typename I, typename N>
-mln_concrete(I)
-dilation(const mln::Image<I>& input_, const mln::Neighborhood<N>& nbh_)
-{
- using namespace mln;
-
- typedef mln_concrete(I) O;
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- O output;
- initialize(output, input);
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- /* There is a slight difference with Milena's classical binary
- dilation here: instead of initializing OUTPUT with INPUT, we
- fill it with default (here, false) values. */
- output(p) = false;
- for_all(n) if (input.has(n))
- if (input(n) == true)
- {
- output(p) = true;
- break;
- }
- }
- return output;
-}
-
-
-/// A neighborhood-aware and graph-friendly version of the binary erosion.
-template <typename I, typename N>
-mln_concrete(I)
-erosion(const mln::Image<I>& input_, const mln::Neighborhood<N>& nbh_)
-{
- using namespace mln;
-
- typedef mln_concrete(I) O;
- const I& input = exact(input_);
- const N& nbh = exact(nbh_);
-
- O output;
- initialize(output, input);
-
- mln_piter(I) p(input.domain());
- mln_niter(N) n(nbh, p);
- for_all(p)
- {
- /* There is a slight difference with Milena's classical erosion
- here: instead of initializing OUTPUT with INPUT, we fill it
- with default (here, true) values. */
- output(p) = true;
- for_all(n) if (input.has(n))
- if (input(n) == false)
- {
- output(p) = false;
- break;
- }
- }
- return output;
-}
-
-
namespace impl
{
// ------------------------------------------ //
@@ -341,11 +277,6 @@ namespace impl
// Implementations on (mln::image2d-based) cubical 2-complexes. //
// ------------------------------------------------------------- //
- /* Note the operator `||' in the following routines: we have to use
- our own ``tolerant'' version of mln::image_if (namely
- mln::image_if_large) for these dilations and erosions to
- work. */
-
/// Dilation from edges to vertices (\f$\delta^\bullet\f$) on
/// an mln::image2d<T>-based cubical complex.
template <typename T>
@@ -353,10 +284,14 @@ namespace impl
mln::image2d<T>
dilation_e2v(const mln::image2d<T>& input)
{
+ using mln::world::inter_pixel::dim2::is_pixel;
+ using mln::world::inter_pixel::v2e;
+
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
- mln::data::paste(dilation(input || mln::world::inter_pixel::dim2::is_pixel(),
- mln::world::inter_pixel::v2e()),
+ mln::data::paste(mln::morpho::dilation(mln::extend(input | is_pixel(),
+ input),
+ v2e().win()),
output);
return output;
}
@@ -368,10 +303,14 @@ namespace impl
mln::image2d<T>
erosion_v2e(const mln::image2d<T>& input)
{
+ using mln::world::inter_pixel::dim2::is_edge;
+ using mln::world::inter_pixel::e2v;
+
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
- mln::data::paste(erosion(input || mln::world::inter_pixel::dim2::is_edge(),
- mln::world::inter_pixel::e2v()),
+ mln::data::paste(mln::morpho::erosion(mln::extend(input | is_edge(),
+ input),
+ e2v().win()),
output);
return output;
}
@@ -383,10 +322,14 @@ namespace impl
mln::image2d<T>
erosion_e2v(const mln::image2d<T>& input)
{
+ using mln::world::inter_pixel::dim2::is_pixel;
+ using mln::world::inter_pixel::v2e;
+
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
- mln::data::paste(erosion(input || mln::world::inter_pixel::dim2::is_pixel(),
- mln::world::inter_pixel::v2e()),
+ mln::data::paste(mln::morpho::erosion(mln::extend(input | is_pixel(),
+ input),
+ v2e().win()),
output);
return output;
}
@@ -398,10 +341,14 @@ namespace impl
mln::image2d<T>
dilation_v2e(const mln::image2d<T>& input)
{
+ using mln::world::inter_pixel::dim2::is_edge;
+ using mln::world::inter_pixel::e2v;
+
mln::image2d<T> output(input.domain());
mln::data::fill(output, false);
- mln::data::paste(dilation(input || mln::world::inter_pixel::dim2::is_edge(),
- mln::world::inter_pixel::e2v()),
+ mln::data::paste(mln::morpho::dilation(mln::extend(input | is_edge(),
+ input),
+ e2v().win()),
output);
return output;
}
--
1.6.3.1
1
0
Fix bugs, add hooks for tracing convergence.
* green/mln/clustering/kmean1d.hh: Evict k parameter from template
and replace it by a constructor parameter. Add printing for debugging.
* green/mln/clustering/kmean1d.hh (update_variance): Fix bugs.
* green/mln/clustering/kmean1d.hh
(build_all_dbg, build_mean_dbg, update_cnv, finalize_cnv): New methods.
* green/mln/clustering/kmean1d.hh (launch_one_time): Fix bugs.
* green/mln/clustering/kmean1d.hh (launch_n_times): Add hooks.
Do some works for managing shell parameters while executing the binary.
* green/demo/clustering/kmean1d/kmean1d.cc
(main, char_to_string, char_to_unsigned, demo, do_demo): New methods.
---
trunk/milena/sandbox/ChangeLog | 19 ++
.../green/demo/clustering/kmean1d/kmean1d.cc | 118 +++++--
.../milena/sandbox/green/mln/clustering/kmean1d.hh | 342 ++++++++++++-------
3 files changed, 325 insertions(+), 154 deletions(-)
diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog
index 4700515..53f1385 100644
--- a/trunk/milena/sandbox/ChangeLog
+++ b/trunk/milena/sandbox/ChangeLog
@@ -20,6 +20,25 @@
* fabien/tests/core/image/tiled2d.cc:
Update performance benchmark for different types of image.
+2009-09-29 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Prepare kmean demo for theo. Work in progress.
+
+ Fix bugs, add hooks for tracing convergence.
+
+ * green/mln/clustering/kmean1d.hh: Evict k parameter from template
+ and replace it by a constructor parameter. Add printing for debugging.
+ * green/mln/clustering/kmean1d.hh (update_variance): Fix bugs.
+ * green/mln/clustering/kmean1d.hh
+ (build_all_dbg, build_mean_dbg, update_cnv, finalize_cnv): New methods.
+ * green/mln/clustering/kmean1d.hh (launch_one_time): Fix bugs.
+ * green/mln/clustering/kmean1d.hh (launch_n_times): Add hooks.
+
+ Do some works for managing shell parameters while executing the binary.
+
+ * green/demo/clustering/kmean1d/kmean1d.cc
+ (main, char_to_string, char_to_unsigned, demo, do_demo): New methods.
+
2009-09-28 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
Prepare kmean demo for theo. Work in progress.
diff --git a/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
index cc04149..f13f783 100644
--- a/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
+++ b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
@@ -21,20 +21,25 @@
#include <mln/io/ppm/save.hh>
#include <mln/io/plot/save_image_sh.hh>
-void demo(const unsigned watch_dog, const unsigned n_times)
+void do_demo(const std::string& image,
+ const unsigned k_center,
+ const unsigned n_times,
+ const unsigned watch_dog)
{
- typedef mln::clustering::kmean1d<double,8,3> t_kmean;
- typedef mln::value::label8 t_label8;
+ typedef mln::clustering::kmean1d<double,8> t_kmean;
+ typedef mln::value::label_8 t_label_8;
typedef mln::value::rgb8 t_rgb8;
typedef mln::value::int_u8 t_int_u8;
- typedef mln::image2d<int_u8> t_image2d_int_u8;
- typedef mln::image2d<rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_int_u8> t_image2d_int_u8;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
t_image2d_int_u8 house;
- mln::io::pgm::load(house, OLENA_IMG_PATH"/house.pgm");
+ mln::io::pgm::load(house, image.c_str());
- t_kmean kmean(house, watch_dog, n_times);
+ t_kmean kmean(house, k_center, watch_dog, n_times);
+
+ //mln::trace::quiet = false;
kmean.launch_n_times();
@@ -52,43 +57,100 @@ void demo(const unsigned watch_dog, const unsigned n_times)
mln::io::plot::save_image_sh(variance_cnv, "variance_cnv.sh");
}
+void demo(const std::string& image = OLENA_IMG_PATH"/house.pgm",
+ const unsigned k_center = 3,
+ const unsigned n_times = 10,
+ const unsigned watch_dog = 10)
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "Launching the demo with these parameters" << std::endl;
+ std::cout << "image : " << image << std::endl;
+ std::cout << "k_center : " << k_center << std::endl;
+ std::cout << "n_times : " << n_times << std::endl;
+ std::cout << "watch_dog : " << watch_dog << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+
+ do_demo(image, k_center, n_times, watch_dog);
+}
+
void usage(const int argc, const char *args[])
{
std::cout << "----------------------------------------" << std::endl;
std::cout << "argc : " << argc << std::endl;
for (int i = 0; i < argc; ++i)
- std::cout << "args[i] : " << args[i] << std::endl;
+ std::cout << "args[" << i << "] : " << args[i] << std::endl;
std::cout << "----------------------------------------" << std::endl;
- std::cout << "usage: kmean1d watch_dog n_times k image" << std::endl;
- std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "usage: kmean1d [image [k_center [n_times [watch_dog]]]]"
+ << std::endl;
+ std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "unsigned k_center (number of centers)" << std::endl;
std::cout << "unsigned n_times (number of launching)" << std::endl;
- // std::cout << "unsigned k (number of centers)" << std::endl;
- // std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
std::cout << "----------------------------------------" << std::endl;
}
-int main(const int argc, const char *args[])
+bool char_to_unsigned(const bool status, const char *arg, unsigned& val)
{
- if (3 == argc)
+ bool result = false;
+
+ if (status)
{
- std::istringstream arg1(args[1]);
- std::istringstream arg2(args[2]);
- // std::istringstream arg3(args[3]);
- // std::istringstream arg3(args[4]);
- unsigned watch_dog;
- unsigned n_times;
- // const char *image;
- // unsigned k;
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
+
+ result = !arg_stream.fail();
+ }
+
+ return result;
+}
+
+bool char_to_string(const bool status, const char *arg, std::string& val)
+{
+ bool result = false;
+
+ if (status)
+ {
+ std::istringstream arg_stream(arg);
+
+ arg_stream >> val;
- arg1 >> watch_dog;
- arg2 >> n_times;
+ return !arg_stream.fail();
+ }
+
+ return result;
+}
- if (!arg1.fail() && !arg2.fail())
- demo(watch_dog, n_times);
- else
- usage(argc, args);
+int main(const int argc, const char *args[])
+{
+ std::string image("top");
+ unsigned k_center;
+ unsigned watch_dog;
+ unsigned n_times;
+ bool status = true;
+
+ switch (argc)
+ {
+ case 5: status = char_to_unsigned(status, args[4], watch_dog);
+ case 4: status = char_to_unsigned(status, args[3], n_times);
+ case 3: status = char_to_unsigned(status, args[2], k_center);
+ case 2: status = char_to_string(status, args[1], image); break;
+ case 1: status = true; break;
+ default: status = false;
+ }
+
+ if (status)
+ {
+ switch (argc)
+ {
+ case 1: demo(); break;
+ case 2: demo(image); break;
+ case 3: demo(image, k_center); break;
+ case 4: demo(image, k_center, n_times); break;
+ case 5: demo(image, k_center, n_times, watch_dog); break;
+ }
}
else
usage(argc, args);
diff --git a/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
index 05947c7..9a8c1ea 100644
--- a/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
+++ b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
@@ -74,7 +74,7 @@ namespace mln
{
// Forward declaration.
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
struct kmean1d;
} // end of namespace mln::clustering
@@ -89,8 +89,7 @@ namespace mln
///
/// T is the type used for computations (float or double).
/// n is the quantification for the image grayscale.
- /// k is the number of classes.
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
struct kmean1d
{
/// Type definitions.
@@ -115,7 +114,7 @@ namespace mln
typedef image2d<t_rgb> t_color_dbg;
typedef image2d<t_value> t_mean_dbg;
- typedef image3d<t_value> t_mean_cnv;
+ typedef image3d<t_result> t_mean_cnv;
typedef image2d<t_result> t_variance_cnv;
///}
@@ -130,6 +129,7 @@ namespace mln
/// \param[in] n_times : the number of times that we executed it (10).
kmean1d(const t_point_img& point,
+ const unsigned k_center,
const unsigned watch_dog = 10,
const unsigned n_times = 10);
@@ -231,11 +231,24 @@ namespace mln
bool is_descent_valid();
//------------------------------------------------------------------------
- // Tools
+ // Debugging tools
//------------------------------------------------------------------------
- void build();
- void to_result2();
+ /// Debugging tools
+ /// \{
+ /// \brief These methods help to interpret results.
+ ///
+ /// The methods build_label_dbg and build_all_dbg work in the input data
+ /// space. The first one build the 2d image of labels. The second call the
+ /// first one and then builds the colorize label' image and the mean
+ /// greylevel image.
+
+ void build_label_dbg();
+ void build_all_dbg();
+ void update_cnv();
+ void finalize_cnv();
+
+ /// \}
private:
@@ -243,6 +256,7 @@ namespace mln
/// \{
/// \brief These parameters control the convergence of the process.
///
+ /// The first parameter, k_center, defines the number of center for kmean.
/// In fact, watch_dog limit the number of iteration that a simple kmean
/// loop can do. If the process reaches the watch_dog limit, it means
/// that the process will not converge at all. The second parameter
@@ -251,6 +265,7 @@ namespace mln
/// from different location will confort us in that we found a global
/// minima, not just a local one.
+ unsigned _k_center;
unsigned _watch_dog;
unsigned _n_times;
@@ -266,9 +281,12 @@ namespace mln
/// around the centers. The current_step variable allows us to remember
/// the current iteration in the kmean loop. This information is needed
/// by is_descent_valid routine which decide if convergence occurs or not.
+ /// The last information, current_launching, traces the progress while
+ /// iterates kmean loop again and again.
t_result _within_variance;
unsigned _current_step;
+ unsigned _current_launching;
/// \}
@@ -366,30 +384,32 @@ namespace mln
// Constructor
//--------------------------------------------------------------------------
+ /// FIXME k must be a parameter, not a static compilation paramater.
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- kmean1d<T,n,k>::kmean1d(const image2d< t_value >& point,
- const unsigned watch_dog,
- const unsigned n_times)
+ kmean1d<T,n>::kmean1d(const t_point_img& point,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times)
{
trace::entering("mln::clustering::kmean1d::kmean1d");
mln_precondition(point.is_valid());
-
+ _k_center = k_center;
_watch_dog = watch_dog;
_n_times = n_times;
_point = point;
_histo = data::compute(accu::meta::stat::histo1d(), _point);
- _number.init_(box1d(point1d(0),point1d(k-1)));
- _mean.init_(box1d(point1d(0),point1d(k-1)));
- _variance.init_(box1d(point1d(0),point1d(k-1)));
+ _number.init_(box1d(point1d(0),point1d(_k_center-1)));
+ _mean.init_(box1d(point1d(0),point1d(_k_center-1)));
+ _variance.init_(box1d(point1d(0),point1d(_k_center-1)));
_group.init_(box1d(point1d(mln_min(t_value)), point1d(mln_max(t_value))));
_distance.init_(box2d(point2d(mln_min(t_value), 0),
- point2d(mln_max(t_value), k-1)));
+ point2d(mln_max(t_value), _k_center-1)));
// Debugging, calibrating and testing
initialize(_label_dbg, _point);
@@ -397,12 +417,16 @@ namespace mln
initialize(_mean_dbg, _point);
// Observing the convergence
+
_variance_cnv.init_(box2d(point2d(0, 0),
- point2d(_watch_dog-1, _n_times-1)));
+ point2d(_n_times-1, _watch_dog-1)));
+
+ data::fill(_variance_cnv, literal::zero);
_mean_cnv.init_(box3d(point3d(0, 0, 0),
- point3d(k-1, _watch_dog-1, _n_times-1)));
+ point3d(_n_times-1, _k_center-1, _watch_dog-1)));
+ data::fill(_mean_cnv, literal::zero);
trace::exiting("mln::clustering::kmean1d::kmean1d");
}
@@ -411,9 +435,9 @@ namespace mln
// Mutators and accessors
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_point(t_point_img& point)
+ void kmean1d<T,n>::set_point(t_point_img& point)
{
trace::entering("mln::clustering::kmean1d::set_point");
@@ -422,9 +446,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_point");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_histo(t_histo_img& histo)
+ void kmean1d<T,n>::set_histo(t_histo_img& histo)
{
trace::entering("mln::clustering::kmean1d::set_histo");
@@ -433,9 +457,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_histo");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_number(t_number_img& number)
+ void kmean1d<T,n>::set_number(t_number_img& number)
{
trace::entering("mln::clustering::kmean1d::set_number");
@@ -444,9 +468,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_number");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_mean(t_mean_img& mean)
+ void kmean1d<T,n>::set_mean(t_mean_img& mean)
{
trace::entering("mln::clustering::kmean1d::set_mean");
@@ -455,9 +479,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_mean");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_variance(t_variance_img& variance)
+ void kmean1d<T,n>::set_variance(t_variance_img& variance)
{
trace::entering("mln::clustering::kmean1d::set_variance");
@@ -466,9 +490,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_variance");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_group(t_group_img& group)
+ void kmean1d<T,n>::set_group(t_group_img& group)
{
trace::entering("mln::clustering::kmean1d::set_group");
@@ -477,9 +501,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_group");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::set_distance(t_distance_img& distance)
+ void kmean1d<T,n>::set_distance(t_distance_img& distance)
{
trace::entering("mln::clustering::kmean1d::set_distance");
@@ -488,9 +512,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::set_distance");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_point_img& kmean1d<T,n,k>::get_point()
+ typename kmean1d<T,n>::t_point_img& kmean1d<T,n>::get_point()
{
trace::entering("mln::clustering::kmean1d::get_point");
@@ -498,9 +522,9 @@ namespace mln
return _point;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_histo_img& kmean1d<T,n,k>::get_histo()
+ typename kmean1d<T,n>::t_histo_img& kmean1d<T,n>::get_histo()
{
trace::entering("mln::clustering::kmean1d::get_histo");
@@ -508,9 +532,9 @@ namespace mln
return _histo;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_number_img& kmean1d<T,n,k>::get_number()
+ typename kmean1d<T,n>::t_number_img& kmean1d<T,n>::get_number()
{
trace::entering("mln::clustering::kmean1d::get_number");
@@ -518,9 +542,9 @@ namespace mln
return _number;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_mean_img& kmean1d<T,n,k>::get_mean()
+ typename kmean1d<T,n>::t_mean_img& kmean1d<T,n>::get_mean()
{
trace::entering("mln::clustering::kmean1d::get_mean");
@@ -528,9 +552,9 @@ namespace mln
return _mean;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_variance_img& kmean1d<T,n,k>::get_variance()
+ typename kmean1d<T,n>::t_variance_img& kmean1d<T,n>::get_variance()
{
trace::entering("mln::clustering::kmean1d::get_variance");
@@ -538,9 +562,9 @@ namespace mln
return _variance;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_group_img& kmean1d<T,n,k>::get_group()
+ typename kmean1d<T,n>::t_group_img& kmean1d<T,n>::get_group()
{
trace::entering("mln::clustering::kmean1d::get_group");
@@ -548,9 +572,9 @@ namespace mln
return _group;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_distance_img& kmean1d<T,n,k>::get_distance()
+ typename kmean1d<T,n>::t_distance_img& kmean1d<T,n>::get_distance()
{
trace::entering("mln::clustering::kmean1d::get_distance");
@@ -558,9 +582,9 @@ namespace mln
return _distance;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_color_dbg& kmean1d<T,n,k>::get_color_dbg()
+ typename kmean1d<T,n>::t_color_dbg& kmean1d<T,n>::get_color_dbg()
{
trace::entering("mln::clustering::kmean1d::get_color_dbg");
@@ -568,9 +592,9 @@ namespace mln
return _color_dbg;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_mean_dbg& kmean1d<T,n,k>::get_mean_dbg()
+ typename kmean1d<T,n>::t_mean_dbg& kmean1d<T,n>::get_mean_dbg()
{
trace::entering("mln::clustering::kmean1d::get_mean_dbg");
@@ -578,9 +602,9 @@ namespace mln
return _mean_dbg;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_label_dbg& kmean1d<T,n,k>::get_label_dbg()
+ typename kmean1d<T,n>::t_label_dbg& kmean1d<T,n>::get_label_dbg()
{
trace::entering("mln::clustering::kmean1d::get_label_dbg");
@@ -588,9 +612,9 @@ namespace mln
return _label_dbg;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_mean_cnv& kmean1d<T,n,k>::get_mean_cnv()
+ typename kmean1d<T,n>::t_mean_cnv& kmean1d<T,n>::get_mean_cnv()
{
trace::entering("mln::clustering::kmean1d::get_mean_cnv");
@@ -598,9 +622,9 @@ namespace mln
return _mean_cnv;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_variance_cnv& kmean1d<T,n,k>::get_variance_cnv()
+ typename kmean1d<T,n>::t_variance_cnv& kmean1d<T,n>::get_variance_cnv()
{
trace::entering("mln::clustering::kmean1d::get_variance_cnv");
@@ -608,9 +632,9 @@ namespace mln
return _variance_cnv;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- typename kmean1d<T,n,k>::t_mean_img& kmean1d<T,n,k>::to_result()
+ typename kmean1d<T,n>::t_mean_img& kmean1d<T,n>::to_result()
{
trace::entering("mln::clustering::kmean1d::to_result");
@@ -623,12 +647,12 @@ namespace mln
// Initialization of centers
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::init_mean_regular()
+ void kmean1d<T,n>::init_mean_regular()
{
trace::entering("mln::clustering::kmean1d::init_mean_regular");
- T step = (mln_max(t_value) - mln_min(t_value)) / (k-1);
+ T step = (mln_max(t_value) - mln_min(t_value)) / (_k_center-1);
mln_piter(image1d<t_value>) l(_mean.domain());
for_all(l)
@@ -640,11 +664,11 @@ namespace mln
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::init_mean_random()
+ void kmean1d<T,n>::init_mean_random()
{
- trace::exiting("mln::clustering::kmean1d::init_mean_random");
+ trace::entering("mln::clustering::kmean1d::init_mean_random");
t_value min = mln_min(t_value);
t_value max = mln_max(t_value);
@@ -653,14 +677,16 @@ namespace mln
for_all(l)
{
_mean(l) = (rand() % (max-min)) + min;
+
+ std::cout << "mean" << l << " : " << _mean(l) << std::endl;
}
trace::exiting("mln::clustering::kmean1d::init_mean_random");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::init_mean()
+ void kmean1d<T,n>::init_mean()
{
trace::entering("mln::clustering::kmean1d::init_mean");
@@ -673,9 +699,9 @@ namespace mln
// Computations of distance, group, center, within variance
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::update_distance()
+ void kmean1d<T,n>::update_distance()
{
trace::entering("mln::clustering::kmean1d::update_distance");
@@ -684,22 +710,24 @@ namespace mln
for_all(d)
{
// the square distance
- _distance(d) = math::sqr(d.row() - _mean(point1d(d.col())));
+ _distance(d) = _histo(point1d(d.row()))
+ * math::sqr(d.row() - _mean(point1d(d.col())));
/*
- std::cout << "row : " << d.row() << std::endl;
- std::cout << "col : " << d.col() << std::endl;
- std::cout << "center : " << _mean(point1d(d.col())) << std::endl;
- std::cout << "distance : " << _distance(d) << std::endl;
- std::cout << "--------------------------------------" << std::endl;
+ std::cout << "row : " << d.row() << std::endl;
+ std::cout << "col : " << d.col() << std::endl;
+ std::cout << "histo : " << _histo(point1d(d.row())) << std::endl;
+ std::cout << "center : " << _mean(point1d(d.col())) << std::endl;
+ std::cout << "distance : " << _distance(d) << std::endl;
+ std::cout << "--------------------------------------" << std::endl;
*/
}
trace::exiting("mln::clustering::kmean1d::update_distance");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::update_group()
+ void kmean1d<T,n>::update_group()
{
trace::entering("mln::clustering::kmean1d::update_group");
@@ -708,7 +736,7 @@ namespace mln
for_all(g)
{
mln_piter(t_mean_img) l(_mean.domain());
- T min = mln_max(T);
+ t_result min = mln_max(t_result);
t_label label = mln_max(t_label);
//std::cout << "g = " << g << std::endl;
@@ -721,7 +749,7 @@ namespace mln
label = l.ind();
}
- //std::cout << "d(" << l << ") = " <<
+ //std::cout << "d" << l << " = " <<
// _distance(point2d(g.ind(), l.ind())) << std::endl;
}
@@ -735,9 +763,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::update_group");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::update_mean()
+ void kmean1d<T,n>::update_mean()
{
trace::entering("mln::clustering::kmean1d::update_mean");
@@ -774,23 +802,22 @@ namespace mln
std::cout << "n(" << l << ") = " << _number(l) << std::endl;
}
*/
-
for_all(l)
{
_mean(l) /= _number(l);
- //std::cout << "c(" << l << ") = " << _mean(l) << std::endl;
+ std::cout << "c" << l << " = " << _mean(l) << std::endl;
}
trace::exiting("mln::clustering::kmean1d::update_mean");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::update_variance()
+ void kmean1d<T,n>::update_variance()
{
trace::entering("mln::clustering::kmean1d::update_variance");
- T _within_variance = literal::zero;
+ _within_variance = literal::zero;
mln_piter(t_variance_img) l(_variance.domain());
for_all(l)
@@ -801,11 +828,12 @@ namespace mln
for_all(g)
{
- _variance(l) += _distance(point2d(g.ind(), l.ind()));
+ if (l.ind() == _group(g))
+ _variance(l) += _distance(point2d(g.ind(), l.ind()));
}
_within_variance += _variance(l);
- //std::cout << "v(" << l << ") = " << _variance(l) << std::endl;
+ std::cout << "v(" << l << ") = " << _variance(l) << std::endl;
}
//std::cout << "result" << result << std::endl;
@@ -814,14 +842,14 @@ namespace mln
}
//--------------------------------------------------------------------------
- // Tools
+ // Debugging tools
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::build()
+ void kmean1d<T,n>::build_label_dbg()
{
- trace::entering("build");
+ trace::entering("mln::clustering::kmean1d::build_mean_dbg");
mln_piter(t_point_img) pi(_point.domain());
mln_piter(t_label_dbg) po(_label_dbg.domain());
@@ -834,26 +862,64 @@ namespace mln
_label_dbg(po) = grp;
}
- trace::exiting("build");
+ trace::exiting("mln::clustering::kmean1d::build_mean_dbg");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::to_result2()
+ void kmean1d<T,n>::build_all_dbg()
{
- typedef value::rgb8 rgb8;
- std::cout << "BUILDING OUTPUT" << std::endl;
+ trace::entering("mln::clustering::kmean1d::build_all_dbg");
+ build_label_dbg();
+
+ _mean_dbg = labeling::mean_values(_point, _label_dbg, _k_center);
+ _color_dbg = labeling::colorize(value::rgb8(), _label_dbg);
+
+ trace::exiting("mln::clustering::kmean1d::build_all_dbg");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean1d<T,n>::update_cnv()
+ {
+ trace::entering("mln::clustering::kmean1d::update_cnv");
+
+ _variance_cnv(point2d(_current_launching,
+ _current_step)) = _within_variance;
+
+ mln_piter(t_mean_img) l(_mean.domain());
+
+ for_all(l)
+ {
+ _mean_cnv(point3d(_current_launching,
+ l.ind(),
+ _current_step)) = _mean(l);
+ }
+
+ trace::exiting("mln::clustering::kmean1d::update_cnv");
+ }
- build();
+ template <typename T, unsigned n>
+ inline
+ void kmean1d<T,n>::finalize_cnv()
+ {
+ trace::entering("mln::clustering::kmean1d::finalize_cnv");
- std::cout << "COLORING OUTPUT" << std::endl;
+ // saturate the curv with the within variance
+ for (unsigned i = _current_step; i < _watch_dog; ++i)
+ _variance_cnv(point2d(_current_launching, i)) = _within_variance;
+
+ for (unsigned i = _current_step; i < _watch_dog; ++i)
+ {
+ mln_piter(t_mean_img) l(_mean.domain());
- _mean_dbg = labeling::mean_values(_point, _label_dbg, k);
- _color_dbg = labeling::colorize(rgb8(), _label_dbg);
+ for_all(l)
+ {
+ _mean_cnv(point3d(_current_launching, l.ind(), i)) = _mean(l);
+ }
+ }
- mln::io::pgm::save(_mean_dbg, "mean.pgm");
- mln::io::ppm::save(_color_dbg, "rgb.pgm");
- mln::io::pgm::save(_label_dbg, "label.pgm");
+ trace::exiting("mln::clustering::kmean1d::finalize_cnv");
}
@@ -861,9 +927,9 @@ namespace mln
// Checking the validity of the results
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- bool kmean1d<T,n,k>::is_descent_valid()
+ bool kmean1d<T,n>::is_descent_valid()
{
trace::entering("mln::clustering::kmean1d::is_descent_valid");
bool result = true;
@@ -881,9 +947,9 @@ namespace mln
return result;
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- bool kmean1d<T,n,k>::is_valid()
+ bool kmean1d<T,n>::is_valid()
{
trace::entering("mln::clustering::kmean1d::is_valid");
bool result = true;
@@ -905,61 +971,85 @@ namespace mln
//--------------------------------------------------------------------------
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::launch_one_time()
+ void kmean1d<T,n>::launch_one_time()
{
trace::entering("mln::clustering::kmean1d::launch_one_time");
+ std::cout << "----------------------------------------" << std::endl;
+
// Initialization to start the descent
- _within_variance = mln_max(t_result)/2;
t_result old_variance = mln_max(t_result);
- // Choose random points
+ // Choose random points and compute within variance
init_mean();
+ update_distance();
+ update_group();
+ update_variance(); // update _within_variance
+
+ std::cout << "first_variance : " << _within_variance << std::endl;
// Execute the descent
- for (unsigned i = 0; i<_watch_dog && _within_variance<old_variance; ++i)
+ for (_current_step = 0;
+ _current_step < _watch_dog && _within_variance < old_variance;
+ ++_current_step)
{
+ old_variance = _within_variance;
+
+ update_mean();
update_distance();
update_group();
- update_mean();
+ update_variance(); // update _within_variance
- old_variance = _within_variance;
+ // debugging code
+ update_cnv();
- update_variance(); // update _within_variance
+ std::cout << "_current_step : " << _current_step << std::endl;
+ std::cout << "_within_variance : " << _within_variance << std::endl;
}
+ std::cout << "----------------------------------------" << std::endl;
+
+ finalize_cnv();
+
trace::exiting("mln::clustering::kmean1d::launch_one_time");
}
- template <typename T, unsigned n, unsigned k>
+ template <typename T, unsigned n>
inline
- void kmean1d<T,n,k>::launch_n_times()
+ void kmean1d<T,n>::launch_n_times()
{
trace::entering("mln::clustering::kmean1d::launch_n_times");
- _variance_min = mln_max(t_result);
+ std::cout << "watch_dog : " << _watch_dog << std::endl;
+ std::cout << "n_times : " << _n_times << std::endl;
+
+ _variance_min = mln_max(t_result);
+ _current_launching = 0;
// Execute the descent n times
- for (unsigned i = 0; i < _n_times; ++i)
+ while (_current_launching < _n_times)
{
launch_one_time();
- if (!is_descent_valid())
- --i;
- else
+ if (is_descent_valid())
{
if (_within_variance < _variance_min)
{
_variance_min = _within_variance;
_mean_min = _mean;
- _launching_min = i;
+ _launching_min = _current_launching;
}
- }
+
+ std::cout << "_current_launching : " << _current_launching
+ << std::endl;
+
+ std::cout << "within_variance[" << _current_launching << "] = "
+ << _within_variance << std::endl;
- std::cout << "within_variance[" << i << "] = "
- << _within_variance << std::endl;
+ ++_current_launching;
+ }
}
trace::exiting("mln::clustering::kmean1d::launch_n_times");
--
1.5.6.5
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-09-29 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Update benchmark for types of image.
* fabien/README: Explain hierarchy of the sandbox.
* fabien/TODO: Remove.
* fabien/bin/dumpl16_to_colorize.cc: New bin tool.
* fabien/bin/dumpl8_to_colorize.cc: New bin tool.
* fabien/igr/color/find_color.cc: Update color detection.
* fabien/magick/tiled_image.cc: Add draft of tiled image using
ImageMagick.
* fabien/mln/test/conversion.hh: Update conversion test.
* fabien/tests/core/image/Makefile,
* fabien/tests/core/image/bench.hh,
* fabien/tests/core/image/bench.sh,
* fabien/tests/core/image/disk_ima.cc,
* fabien/tests/core/image/ima2d.cc,
* fabien/tests/core/image/tiled2d.cc:
Update performance benchmark for different types of image.
---
README | 114 +++++++++++++++++++++++++++++++++++++++++++
bin/dumpl16_to_colorize.cc | 64 ++++++++++++++++++++++++
bin/dumpl8_to_colorize.cc | 62 +++++++++++++++++++++++
igr/color/find_color.cc | 62 ++++++++++++++++-------
magick/tiled_image.cc | 38 ++++++++++++++
mln/test/conversion.hh | 14 +++--
tests/core/image/Makefile | 3 +
tests/core/image/bench.hh | 19 +++++++
tests/core/image/bench.sh | 5 +
tests/core/image/disk_ima.cc | 33 +-----------
tests/core/image/ima2d.cc | 31 +++++++++++
tests/core/image/tiled2d.cc | 29 +---------
12 files changed, 396 insertions(+), 78 deletions(-)
Index: trunk/milena/sandbox/fabien/TODO (deleted)
===================================================================
Index: trunk/milena/sandbox/fabien/igr/color/find_color.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/color/find_color.cc (revision 4562)
+++ trunk/milena/sandbox/fabien/igr/color/find_color.cc (revision 4563)
@@ -10,42 +10,50 @@
#include <mln/convert/from_to.hh>
#include <mln/data/convert.hh>
#include <mln/math/diff_abs.hh>
+#include <mln/math/min.hh>
using namespace mln;
using value::rgb8;
using value::hsl_;
using value::int_u8;
+#define GREEN 120.f
+#define BLUE 240.f
+
inline
-bool
-is_green(hsl_<float, float, float> value)
+float
+hue_truth(hsl_<float, float, float> value, float hue, float range)
{
- if (value.hue() > 75 && value.hue() < 170 &&
- value.sat() > 0.5 &&
- value.lum() > 0.3 && value.lum() < 0.7)
- return true;
+ float truth = 0.0;
- return false;
+ if (value.hue() > (hue - range) && value.hue() < (hue + range))
+ {
+ truth += 1.f - ((math::diff_abs(hue, value.hue()) / 100.0) / (range / 100));
+ }
+
+ if (truth > 1.f)
+ truth = 1.f;
+ if (truth < 0.f)
+ truth = 0.f;
+ return truth;
}
inline
-int_u8
-how_green(hsl_<float, float, float> value)
+float
+sat_truth(hsl_<float, float, float> value)
{
- float proba = 0.0;
+ return value.sat();
+}
- if (value.hue() > 60 && value.hue() < 180)
+inline
+float
+lum_truth(hsl_<float, float, float> value)
{
- proba += 1.f - ((math::diff_abs(120.f, value.hue()) / 100.0) / 0.6);
- proba *= value.sat();
- proba *= 1.f - (math::diff_abs(0.5f, value.lum()));
+ return 1.f - 2 * (math::diff_abs(0.5f, value.lum()));
}
- if (proba > 1.f)
- proba = 1.f;
- return (int_u8) (proba * 255);
-}
+
int main(int argc, char* argv[])
{
@@ -58,17 +66,33 @@
image2d<rgb8> input;
io::ppm::load(input, argv[1]);
image2d<int_u8> output;
+
initialize(output, input);
+ image2d<int_u8> hue_ima;
+ initialize(hue_ima, input);
+ image2d<int_u8> sl_p_ima;
+ initialize(sl_p_ima, input);
+ image2d<int_u8> sl_m_ima;
+ initialize(sl_m_ima, input);
typedef image2d<hsl_<float, float, float> > H;
H ima_hsl = data::convert(hsl_<float, float, float>(), input);
mln_piter_(H) p(ima_hsl.domain());
for_all(p)
{
- output(p) = how_green(ima_hsl(p));
+ float truth = 0.0;
+ truth = hue_truth(ima_hsl(p), GREEN, 60.f) * sat_truth(ima_hsl(p)) * lum_truth(ima_hsl(p));
+ output(p) = (int_u8) (truth * 255);
+
+ hue_ima(p) = (int_u8) (hue_truth(ima_hsl(p), GREEN, 60.f) * 255);
+ sl_p_ima(p) = (int_u8) (sat_truth(ima_hsl(p)) * lum_truth(ima_hsl(p)) * 255);
+ sl_m_ima(p) = (int_u8) (math::min(sat_truth(ima_hsl(p)), lum_truth(ima_hsl(p))) * 255);
}
io::pgm::save(output, argv[2]);
+ io::pgm::save(hue_ima, "hue.pgm");
+ io::pgm::save(sl_p_ima, "sl_p.pgm");
+ io::pgm::save(sl_m_ima, "sl_m.pgm");
return 0;
}
Index: trunk/milena/sandbox/fabien/tests/core/image/ima2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/ima2d.cc (revision 0)
+++ trunk/milena/sandbox/fabien/tests/core/image/ima2d.cc (revision 4563)
@@ -0,0 +1,31 @@
+#include <mln/core/image/image2d.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/literal/colors.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/debug/quiet.hh>
+
+#include "bench.hh"
+
+
+using namespace mln;
+using value::rgb8;
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " input" << std::endl;
+ return 1;
+ }
+
+ image2d<rgb8> ima;
+
+ io::ppm::load(ima, argv[1]);
+
+ bench_disk_perf(ima);
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc (revision 4562)
+++ trunk/milena/sandbox/fabien/tests/core/image/disk_ima.cc (revision 4563)
@@ -7,6 +7,8 @@
#include <mln/debug/quiet.hh>
+#include "bench.hh"
+
using namespace mln;
using value::rgb8;
@@ -20,36 +22,11 @@
return 1;
}
- //image2d<rgb8> ima;
- disk_ima<rgb8> tiled_ima;
-
- //io::ppm::load(ima, argv[1]);
- io::ppm::load(tiled_ima, argv[1]);
-
- //std::cout << "bbox: " << tiled_ima.bbox() << std::endl;
- //std::cout << "file: " << tiled_ima.file_() << std::endl;
-
- /*point2d pt0(0, 0);
- mln_assertion(tiled_ima(pt0) == ima(pt0));
+ disk_ima<rgb8> ima;
- point2d pt(0, 1);
- mln_assertion(tiled_ima(pt) == ima(pt));
+ io::ppm::load(ima, argv[1]);
- point2d pt2(1, 0);
- mln_assertion(tiled_ima(pt2) == ima(pt2));
-
- point2d pt3(1, 1);
- mln_assertion(tiled_ima(pt3) == ima(pt3));*/
-
- mln_piter_(disk_ima<rgb8>) p(tiled_ima.domain());
- for_all(p)
- if (p.row() % 16 == 0)
- {
- //std::cout << tiled_ima(p);
- tiled_ima(p) = literal::green;
- //std::cout << " -> " << tiled_ima(p) << std::endl;
- //mln_assertion(tiled_ima(p) == ima(p));
- }
+ bench_disk_perf(ima);
return 0;
}
Index: trunk/milena/sandbox/fabien/tests/core/image/bench.sh
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/bench.sh (revision 4562)
+++ trunk/milena/sandbox/fabien/tests/core/image/bench.sh (revision 4563)
@@ -2,6 +2,7 @@
make disk_ima
make tiled2d
+make ima2d
echo "---"
echo "Disk Image Performance"
@@ -10,3 +11,7 @@
echo "---"
echo "Tiled Image Performance"
time ./tiled2d $1
+
+echo "---"
+echo "Image 2D Performance"
+time ./ima2d $1
Index: trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 4562)
+++ trunk/milena/sandbox/fabien/tests/core/image/tiled2d.cc (revision 4563)
@@ -7,6 +7,8 @@
#include <mln/debug/quiet.hh>
+#include "bench.hh"
+
using namespace mln;
using value::rgb8;
@@ -20,36 +22,11 @@
return 1;
}
- //image2d<rgb8> ima;
tiled2d<rgb8> tiled_ima;
- //io::ppm::load(ima, argv[1]);
io::ppm::load(tiled_ima, argv[1]);
- //std::cout << "bbox: " << tiled_ima.bbox() << std::endl;
- //std::cout << "file: " << tiled_ima.file_() << std::endl;
-
- /*point2d pt0(0, 0);
- mln_assertion(tiled_ima(pt0) == ima(pt0));
-
- point2d pt(0, 1);
- mln_assertion(tiled_ima(pt) == ima(pt));
-
- point2d pt2(1, 0);
- mln_assertion(tiled_ima(pt2) == ima(pt2));
-
- point2d pt3(1, 1);
- mln_assertion(tiled_ima(pt3) == ima(pt3));*/
-
- mln_piter_(tiled2d<rgb8>) p(tiled_ima.domain());
- for_all(p)
- if (p.row() % 16 == 0)
- {
- //std::cout << tiled_ima(p);
- tiled_ima(p) = literal::green;
- //std::cout << " -> " << tiled_ima(p) << std::endl;
- //mln_assertion(tiled_ima(p) == ima(p));
- }
+ bench_disk_perf(tiled_ima);
return 0;
}
Index: trunk/milena/sandbox/fabien/tests/core/image/Makefile
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4562)
+++ trunk/milena/sandbox/fabien/tests/core/image/Makefile (revision 4563)
@@ -10,3 +10,6 @@
disk_ima: disk_ima.cc
${CXX} ${CXXFLAGS} ${INC} $^ -o disk_ima
+
+ima2d: ima2d.cc
+ ${CXX} ${CXXFLAGS} ${INC} $^ -o ima2d
Index: trunk/milena/sandbox/fabien/tests/core/image/bench.hh
===================================================================
--- trunk/milena/sandbox/fabien/tests/core/image/bench.hh (revision 0)
+++ trunk/milena/sandbox/fabien/tests/core/image/bench.hh (revision 4563)
@@ -0,0 +1,19 @@
+#include <mln/core/concept/image.hh>
+#include <mln/literal/colors.hh>
+
+using namespace mln;
+
+template <typename I>
+inline
+void
+bench_disk_perf(Image<I>& ima_)
+{
+ I& ima = exact(ima_);
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ if (p.row() % 16 == 0)
+ {
+ ima(p) = literal::green;
+ }
+}
Index: trunk/milena/sandbox/fabien/mln/test/conversion.hh
===================================================================
--- trunk/milena/sandbox/fabien/mln/test/conversion.hh (revision 4562)
+++ trunk/milena/sandbox/fabien/mln/test/conversion.hh (revision 4563)
@@ -33,6 +33,8 @@
# include <mln/core/concept/image.hh>
# include <mln/data/convert.hh>
# include <mln/math/diff_abs.hh>
+# include <mln/math/sqr.hh>
+# include <mln/math/sqrt.hh>
# include <mln/value/rgb8.hh>
@@ -60,6 +62,8 @@
namespace impl
{
+ /// Distance between two color values.
+ /// We have to specialized it for each type of color.
template <typename V>
inline
float color_distance(const V& color1, const V& color2)
@@ -67,6 +71,8 @@
return -1.0; // FIXME
}
+ /// Distance between two RGB values.
+ /// \return Value is normalized ([0..1]).
template <>
inline
float color_distance<value::rgb8>(const value::rgb8& color1, const value::rgb8& color2)
@@ -82,8 +88,7 @@
return dist;
}
- /// \return The percentage of points which value is not preserved.
- /// The return value is normalized ([0..1]).
+ /// \return Root mean square.
template <typename I, typename V>
inline
float conversion_(const I& ima, const V& value)
@@ -97,12 +102,11 @@
mln_piter(I) p(ima.domain());
for_all(p)
{
- delta += color_distance(ima(p), output(p));
- //if (ima(p) != output(p))
- // delta += 1.0;
+ delta += math::sqr(color_distance(ima(p), output(p)));
}
delta /= ima.nelements();
+ delta = math::sqrt(delta);
return delta;
}
Index: trunk/milena/sandbox/fabien/bin/dumpl16_to_colorize.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dumpl16_to_colorize.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dumpl16_to_colorize.cc (revision 4563)
@@ -0,0 +1,64 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+#include <mln/debug/colorize.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_16.hh>
+#include <mln/value/label_32.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/core/concept/literal.hh>
+
+#include <mln/io/dump/load.hh>
+#include <mln/io/ppm/save.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump dim nbasins output.ppm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::label_16;
+ using value::label_32;
+ using value::rgb8;
+ typedef label_16 L;
+
+ if (argc != 5)
+ return usage(argv);
+
+ unsigned dim = atoi(argv[2]);
+ unsigned nbasins = atoi(argv[3]);
+ if (dim != 2 && dim != 3)
+ {
+ std::cout << "<dimensions> invalid" << std::endl;
+ return 1;
+ }
+
+ if (dim == 2)
+ {
+ image2d<L> ima2d;
+ io::dump::load(ima2d, argv[1]);
+ image2d<rgb8> ima_rgb = debug::colorize(rgb8(), ima2d, nbasins);
+ io::ppm::save(ima_rgb, argv[4]);
+ }
+ else
+ {
+ image3d<L> ima3d;
+ io::dump::load(ima3d, argv[1]);
+ image3d<rgb8> ima_rgb = debug::colorize(rgb8(), ima3d, nbasins);
+
+ image2d<rgb8> ima_result = debug::slices_2d(ima_rgb, 1.f, literal::black);
+ io::ppm::save(ima_result, argv[4]);
+ }
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/bin/dumpl8_to_colorize.cc
===================================================================
--- trunk/milena/sandbox/fabien/bin/dumpl8_to_colorize.cc (revision 0)
+++ trunk/milena/sandbox/fabien/bin/dumpl8_to_colorize.cc (revision 4563)
@@ -0,0 +1,62 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/make/image3d.hh>
+#include <mln/debug/slices_2d.hh>
+#include <mln/labeling/colorize.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/int_u12.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/core/concept/literal.hh>
+
+#include <mln/io/dump/load.hh>
+#include <mln/io/ppm/save.hh>
+
+
+int usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.dump dim nbasins output.ppm" << std::endl;
+ return 1;
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::int_u12;
+ using value::label_8;
+ using value::rgb8;
+ typedef label_8 L;
+
+ if (argc != 5)
+ return usage(argv);
+
+ unsigned dim = atoi(argv[2]);
+ unsigned nbasins = atoi(argv[3]);
+ if (dim != 2 && dim != 3)
+ {
+ std::cout << "<dimensions> invalid" << std::endl;
+ return 1;
+ }
+
+ if (dim == 2)
+ {
+ image2d<L> ima2d;
+ io::dump::load(ima2d, argv[1]);
+ image2d<rgb8> ima_rgb = labeling::colorize(rgb8(), ima2d, nbasins);
+ io::ppm::save(ima_rgb, argv[4]);
+ }
+ else
+ {
+ image3d<L> ima3d;
+ io::dump::load(ima3d, argv[1]);
+ image3d<rgb8> ima_rgb = labeling::colorize(rgb8(), ima3d, nbasins);
+
+ image2d<rgb8> ima_result = debug::slices_2d(ima_rgb, 1.f, literal::black);
+ io::ppm::save(ima_result, argv[4]);
+ }
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/magick/tiled_image.cc
===================================================================
--- trunk/milena/sandbox/fabien/magick/tiled_image.cc (revision 0)
+++ trunk/milena/sandbox/fabien/magick/tiled_image.cc (revision 4563)
@@ -0,0 +1,38 @@
+#include <Magick++.h>
+#include <iostream>
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 2)
+ {
+ std::cout << "Usage: " << argv[0] << " filename" << std::endl;
+ return 1;
+ }
+
+ std::cout << "Loading image..." << std::endl;
+ Magick::Image image(argv[1]);
+ std::cout << "Loading done." << std::endl;
+
+ std::cout << "columns: " << image.columns() << std::endl;
+ std::cout << "rows: " << image.rows() << std::endl;
+
+ unsigned ncols = image.columns();
+ unsigned nrows = image.rows();
+ const Magick::PixelPacket *pixel_cache;
+ unsigned count = 0;
+ for (unsigned row = 0; row < nrows; row += 1024)
+ {
+ std::cout << "Processing row #" << row << std::endl;
+ pixel_cache = image.getConstPixels(0, 0, ncols / 128, row);
+ for (unsigned col = 0; col < ncols / 128; col += 256)
+ {
+ const Magick::PixelPacket *pixel = pixel_cache + col;
+ ++count;
+ }
+ }
+
+ std::cout << "nbr pixels: " << count << std::endl;
+
+ return 0;
+}
Index: trunk/milena/sandbox/fabien/README
===================================================================
--- trunk/milena/sandbox/fabien/README (revision 0)
+++ trunk/milena/sandbox/fabien/README (revision 4563)
@@ -0,0 +1,114 @@
+ ________
+< README >
+ --------
+ \ ^__^
+ \ (oo)\_______
+ (__)\ )\/\
+ ||----w |
+ || ||
+
+
+
+
+./bin/
+======
+Divers binaires pour convertir des images.
+Par exemple, `dumpi12_to_pgm' convertit un dump en int_u12 en une image PGM.
+
+./binarization/ (Deprecated)
+===============
+
+./dcmtk/
+========
+Support incomplet de la bibliotheque DCMTK.
+Abandonne au profit de GDCM (bibliotheque pour le format DICOM).
+
+./igr/
+======
+
+ ./igr/color
+ ===========
+
+ ./igr/fixed_seg
+ ===============
+
+ ./igr/mat2mln
+ =============
+
+ ./igr/plot_points
+ =================
+
+ ./igr/point_filtering
+ =====================
+
+ ./igr/smooth_fixed_seg
+ ======================
+
+ ./igr/space_smooth
+ ==================
+
+ ./igr/time_smooth
+ =================
+
+
+./magick/ (Deprecated)
+=========
+Premiers tests pour support ImageMagick.
+Ce support a ete deplace dans mln/io/magick
+
+./mln/
+======
+
+ ./mln/canvas/browsing/
+ ======================
+ Brouillon pour support du `snake' en n dimensions.
+ Peut etre ignore.
+
+ ./mln/core/image/
+ =================
+ Nouveaux types d'images.
+ disk_ima = image avec access direct au disque dur
+ tiled2d = image 2D avec cache
+ cache = utilise par `tiled2d', gere la politique de cache
+ page = utilise par `cache', gere la forme d'un bloc de donnees
+ magick_tiled2d = brouillon pour image avec cache gere par ImageMagick
+
+ ./mln/data/
+ ===========
+ Brouillon pour support du `fast_median' avec un autre canvas.
+ Peut etre ignore.
+
+ ./mln/debug/
+ ============
+ int2rgb : convertit un int en une valeur RGB afin de pouvoir l'afficher
+
+ ./mln/display/
+ ==============
+ display_region : cree une image avec les lignes de watershed remplacees
+ par une color precise afin d'exhiber les regions
+
+ ./mln/io/pnm/
+ =============
+ Support de la lecture de PNM pour la creation d'image mappees sur disque
+ (`disk_ima').
+
+ ./mln/test/
+ ===========
+ Teste la conversion d'un type de valeur de couleur dans un autre espace
+ de couleur. Renvoie le "root mean square".
+
+ ./mln/upsampling/
+ =================
+ Implementations des HQx.
+
+ ./mln/world/inter_pixel/
+ ========================
+ display_region : cree une image pour aider a la visualization, a ete remplace
+ par la demo d'inter_pixel
+ is_zero_face : implement zero-face
+
+
+
+./tests/
+========
+Tests pour les sources situees dans ./mln/
1
0
* green/mln/clustering/kmean1d.hh: New library file.
* green/demo/clustering/kmean1d: New directory.
* green/demo/clustering/kmean1d/Makefile.am: New makefile.
* green/demo/clustering/kmean1d/kmean1d.cc: New demo.
* green/tests/clustering/kmean1d: New directory.
* green/tests/clustering/kmean1d/Makefile.am: New makefile.
* green/tests/clustering/kmean1d/kmean1d.cc: New unitary tests.
---
trunk/milena/sandbox/ChangeLog | 14 +
.../green/demo/clustering/kmean1d/Makefile.am | 148 +++
.../green/demo/clustering/kmean1d/kmean1d.cc | 97 ++
.../milena/sandbox/green/mln/clustering/kmean1d.hh | 974 ++++++++++++++++++++
.../green/tests/clustering/kmean1d/Makefile.am | 148 +++
.../green/tests/clustering/kmean1d/kmean1d.cc | 483 ++++++++++
6 files changed, 1864 insertions(+), 0 deletions(-)
create mode 100644 trunk/milena/sandbox/green/demo/clustering/kmean1d/Makefile.am
create mode 100644 trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
create mode 100644 trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
create mode 100644 trunk/milena/sandbox/green/tests/clustering/kmean1d/Makefile.am
create mode 100644 trunk/milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog
index 797fa7b..2f2684f 100644
--- a/trunk/milena/sandbox/ChangeLog
+++ b/trunk/milena/sandbox/ChangeLog
@@ -1,3 +1,17 @@
+2009-09-28 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Prepare kmean demo for theo. Work in progress.
+
+ * green/mln/clustering/kmean1d.hh: New library file.
+
+ * green/demo/clustering/kmean1d: New directory.
+ * green/demo/clustering/kmean1d/Makefile.am: New makefile.
+ * green/demo/clustering/kmean1d/kmean1d.cc: New demo.
+
+ * green/tests/clustering/kmean1d: New directory.
+ * green/tests/clustering/kmean1d/Makefile.am: New makefile.
+ * green/tests/clustering/kmean1d/kmean1d.cc: New unitary tests.
+
2009-09-24 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Add benchmark for disk-mapped image and work for color types.
diff --git a/trunk/milena/sandbox/green/demo/clustering/kmean1d/Makefile.am b/trunk/milena/sandbox/green/demo/clustering/kmean1d/Makefile.am
new file mode 100644
index 0000000..91230b6
--- /dev/null
+++ b/trunk/milena/sandbox/green/demo/clustering/kmean1d/Makefile.am
@@ -0,0 +1,148 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+INCLUDES= -I$(HOME)/svn/oln/trunk/milena/sandbox/green
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/demo
+BUILD__PATTERN= green/build/demo
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
new file mode 100644
index 0000000..cc04149
--- /dev/null
+++ b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
@@ -0,0 +1,97 @@
+// DEMO ON KMEAN1D
+
+#include <mln/clustering/kmean1d.hh>
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+#include <mln/pw/value.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/plot/save_image_sh.hh>
+
+void demo(const unsigned watch_dog, const unsigned n_times)
+{
+ typedef mln::clustering::kmean1d<double,8,3> t_kmean;
+ typedef mln::value::label8 t_label8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::int_u8 t_int_u8;
+ typedef mln::image2d<int_u8> t_image2d_int_u8;
+ typedef mln::image2d<rgb8> t_image2d_rgb8;
+
+ t_image2d_int_u8 house;
+
+ mln::io::pgm::load(house, OLENA_IMG_PATH"/house.pgm");
+
+ t_kmean kmean(house, watch_dog, n_times);
+
+ kmean.launch_n_times();
+
+ t_kmean::t_color_dbg color_img = kmean.get_color_dbg();
+ t_kmean::t_mean_dbg mean_img = kmean.get_mean_dbg();
+ t_kmean::t_label_dbg label_img = kmean.get_label_dbg();
+ t_kmean::t_variance_cnv variance_cnv = kmean.get_variance_cnv();
+ t_kmean::t_mean_cnv mean_cnv = kmean.get_mean_cnv();
+
+ mln::io::pgm::save(mean_img, "mean.pgm");
+ mln::io::ppm::save(color_img, "color.pgm");
+ mln::io::pgm::save(label_img, "label.pgm");
+
+ mln::io::plot::save_image_sh(mean_cnv, "mean_cnv.sh");
+ mln::io::plot::save_image_sh(variance_cnv, "variance_cnv.sh");
+}
+
+void usage(const int argc, const char *args[])
+{
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "argc : " << argc << std::endl;
+
+ for (int i = 0; i < argc; ++i)
+ std::cout << "args[i] : " << args[i] << std::endl;
+
+ std::cout << "----------------------------------------" << std::endl;
+ std::cout << "usage: kmean1d watch_dog n_times k image" << std::endl;
+ std::cout << "unsigned watch_dog (convergence loop)" << std::endl;
+ std::cout << "unsigned n_times (number of launching)" << std::endl;
+ // std::cout << "unsigned k (number of centers)" << std::endl;
+ // std::cout << "pbm image (points to work with)" << std::endl;
+ std::cout << "----------------------------------------" << std::endl;
+}
+
+int main(const int argc, const char *args[])
+{
+ if (3 == argc)
+ {
+ std::istringstream arg1(args[1]);
+ std::istringstream arg2(args[2]);
+ // std::istringstream arg3(args[3]);
+ // std::istringstream arg3(args[4]);
+ unsigned watch_dog;
+ unsigned n_times;
+ // const char *image;
+ // unsigned k;
+
+ arg1 >> watch_dog;
+ arg2 >> n_times;
+
+ if (!arg1.fail() && !arg2.fail())
+ demo(watch_dog, n_times);
+ else
+ usage(argc, args);
+ }
+ else
+ usage(argc, args);
+
+ return 0;
+}
diff --git a/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
new file mode 100644
index 0000000..05947c7
--- /dev/null
+++ b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
@@ -0,0 +1,974 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of Olena.
+//
+// Olena is free software: you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation, version 2 of the License.
+//
+// Olena is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Olena. If not, see <http://www.gnu.org/licenses/>.
+//
+// As a special exception, you may use this file as part of a free
+// software project without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to produce
+// an executable, this file does not by itself cause the resulting
+// executable to be covered by the GNU General Public License. This
+// exception does not however invalidate any other reasons why the
+// executable file might be covered by the GNU General Public License.
+
+#ifndef MLN_CLUSTERING_KMEAN1D_HH
+#define MLN_CLUSTERING_KMEAN1D_HH
+
+/// \file
+///
+/// \brief Implements the optimized kmean algorithm.
+///
+/// This algorithm is optimized in the way it proceeds directly with the
+/// greylevel attribute inspite of pixel attribute. The algorithm is
+/// independant from the image dimension. But, we have to use to compute
+/// one time the histogram. In fact, we move a recurrent cost to a fix cost
+/// in the complexity. This version is very adapted to image with small
+/// quantification.
+
+#include <limits.h>
+#include <iostream>
+#include <mln/trace/entering.hh>
+#include <mln/trace/exiting.hh>
+
+#include <mln/core/contract.hh>
+#include <mln/trait/value_.hh>
+#include <mln/accu/stat/histo1d.hh>
+
+#include <mln/math/min.hh>
+#include <mln/math/sqr.hh>
+#include <mln/norm/l2.hh>
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/core/macros.hh>
+
+#include <mln/data/compute.hh>
+#include <mln/debug/println.hh>
+#include <mln/data/fill.hh>
+#include <mln/literal/zero.hh>
+#include <mln/labeling/colorize.hh>
+#include <mln/labeling/mean_values.hh>
+
+#include <mln/io/ppm/save.hh>
+#include <mln/io/pgm/save.hh>
+
+namespace mln
+{
+
+ namespace clustering
+ {
+
+ // Forward declaration.
+ template <typename T, unsigned n, unsigned k>
+ struct kmean1d;
+
+ } // end of namespace mln::clustering
+
+ namespace clustering
+ {
+ /// \brief Implements the kmean algorithm in a specific way.
+ ///
+ /// This version of the kmean algorithm uses a greyscale image as input,
+ /// temporary images for computations and produces images as result. Images
+ /// play the role of matrix or vector in standard statistic algoritm.
+ ///
+ /// T is the type used for computations (float or double).
+ /// n is the quantification for the image grayscale.
+ /// k is the number of classes.
+ template <typename T, unsigned n, unsigned k>
+ struct kmean1d
+ {
+ /// Type definitions.
+ /// \brief A few type definitions to limit the refactoring impact.
+ ///{
+
+ typedef value::rgb<8> t_rgb; // just for debugging
+ typedef value::label<8> t_label; // in fact label<p>, where k <= 2^p
+ typedef value::int_u<n> t_value;
+ typedef T t_result;
+
+ typedef image2d<t_value> t_point_img;
+ typedef image1d<unsigned> t_histo_img;
+ typedef image1d<t_result> t_number_img;
+ typedef image1d<t_result> t_mean_img;
+ typedef image1d<t_result> t_variance_img;
+
+ typedef image1d<t_label> t_group_img;
+ typedef image2d<t_result> t_distance_img;
+
+ typedef image2d<t_label> t_label_dbg;
+ typedef image2d<t_rgb> t_color_dbg;
+ typedef image2d<t_value> t_mean_dbg;
+
+ typedef image3d<t_value> t_mean_cnv;
+ typedef image2d<t_result> t_variance_cnv;
+
+ ///}
+
+ //------------------------------------------------------------------------
+ // Constructor
+ //------------------------------------------------------------------------
+
+ /// \brief Constructor
+ /// \param[in] point : the image as the population of pixels.
+ /// \param[in] watch_dog : the limit to observe the convergence (10).
+ /// \param[in] n_times : the number of times that we executed it (10).
+
+ kmean1d(const t_point_img& point,
+ const unsigned watch_dog = 10,
+ const unsigned n_times = 10);
+
+ //------------------------------------------------------------------------
+ // Accessors
+ //------------------------------------------------------------------------
+
+ /// Mutator and accessors.
+ /// \{
+ /// \brief Mutator and accessors are required for debugging and testing.
+ ///
+ /// Testing needs to hack the kmean loop process in order to verify each
+ /// step of the algorithm.
+
+ void set_point(t_point_img& point);
+ void set_histo(t_histo_img& histo);
+ void set_number(t_number_img& number);
+ void set_mean(t_mean_img& mean);
+ void set_variance(t_variance_img& variance);
+ void set_group(t_group_img& group);
+ void set_distance(t_distance_img& distance);
+
+ // Hacking outputs
+ t_point_img& get_point();
+ t_histo_img& get_histo();
+ t_number_img& get_number();
+ t_mean_img& get_mean();
+ t_variance_img& get_variance();
+ t_group_img& get_group();
+ t_distance_img& get_distance();
+
+ // Testing outputs
+ t_color_dbg& get_color_dbg();
+ t_mean_dbg& get_mean_dbg();
+ t_label_dbg& get_label_dbg();
+
+ t_mean_cnv& get_mean_cnv();
+ t_variance_cnv& get_variance_cnv();
+
+ // Normal outputs
+ t_mean_img& to_result();
+
+ /// \}
+
+ //------------------------------------------------------------------------
+ // Initializations of centers
+ //------------------------------------------------------------------------
+
+ /// Initialization of centers.
+ /// \{
+ /// \brief Two ways: Regular greylevel tick or random greylevel value or.
+ ///
+ /// There is two way to proceed the initialization. First of all, we
+ /// divide the greyscale in regular tick and we assigne them to the mean
+ /// of the centers. Finaly, we can ask random initialization along the
+ /// greyscale axis. The second process is needed to launch_n_times the
+ /// kmean and converge to the best descent.
+
+ void init_mean();
+ void init_mean_regular();
+ void init_mean_random();
+
+ /// \}
+
+
+ //------------------------------------------------------------------------
+ // Computations of distance, group, center, within variance
+ //------------------------------------------------------------------------
+
+ /// Computations of distance, group, center, within variance.
+ /// \{
+ /// \brief Update the statistical information needed by the kmean process.
+ ///
+ /// The kmean process is a loop where distance from centers to pixels are
+ /// first compute. Then we assign the pixels to their nearest center.
+ /// The new location of each center can then update. Finaly, hommogenity
+ /// in group is observed by the within variance.
+
+ void update_distance();
+ void update_group();
+ void update_mean();
+ void update_variance();
+
+ /// \}
+
+ //------------------------------------------------------------------------
+ // Main loop
+ //------------------------------------------------------------------------
+
+ void launch_one_time();
+ void launch_n_times();
+
+
+ //------------------------------------------------------------------------
+ // Checking the validiy of the results
+ //------------------------------------------------------------------------
+
+ bool is_valid();
+ bool is_descent_valid();
+
+ //------------------------------------------------------------------------
+ // Tools
+ //------------------------------------------------------------------------
+
+ void build();
+ void to_result2();
+
+
+ private:
+ /// Parameters.
+ /// \{
+ /// \brief These parameters control the convergence of the process.
+ ///
+ /// In fact, watch_dog limit the number of iteration that a simple kmean
+ /// loop can do. If the process reaches the watch_dog limit, it means
+ /// that the process will not converge at all. The second parameter
+ /// n_times is the number of times we launch again and again the simple
+ /// kmean loop. As the kmean process is a descent, restarting the process
+ /// from different location will confort us in that we found a global
+ /// minima, not just a local one.
+
+ unsigned _watch_dog;
+ unsigned _n_times;
+
+ /// \}
+
+ /// Convergence information.
+ /// \{
+ /// \brief This information is used to follow the convergence.
+ ///
+ /// The within_variance is the homogenity indicator for the kmean process.
+ /// The ideal situation is to find the center with the minimum variance
+ /// around them. The within variance is just the sum of all variance
+ /// around the centers. The current_step variable allows us to remember
+ /// the current iteration in the kmean loop. This information is needed
+ /// by is_descent_valid routine which decide if convergence occurs or not.
+
+ t_result _within_variance;
+ unsigned _current_step;
+
+ /// \}
+
+ /// Result of the kmean process.
+ /// \{
+ /// \brief The center location are the major results of the kmean process.
+ ///
+ /// The kmean process result is composed by three information. The best
+ /// launching iteration, the best within variance obtained and the
+ /// location of the centers associated.
+
+ unsigned _launching_min;
+ t_result _variance_min;
+ t_mean_img _mean_min;
+
+ /// Inputs.
+ /// \{
+ /// \brief The inputs are the distribution of the values and the values.
+ ///
+ /// The point image is a saving data for the real inputs. In fact, we use
+ /// the histogram information in the optimized kmean process.
+
+ t_point_img _point;
+ t_histo_img _histo;
+
+ ///\}
+
+ /// Centers description.
+ /// \{
+ /// \brief Centers are described by the first moment of their group.
+ ///
+ /// Centers are describe by their group attributes like the number of
+ /// pixels wich are relying on, the mass center of the group and the
+ /// homogeneity of the group. The variance is used as indicator for the
+ /// convergence. The number of pixels is used as integrity indicator.
+ /// A center with no point is a non sense. Theses informations are updated
+ /// after each kmean iteration.
+
+ t_number_img _number; // k x 1
+ t_mean_img _mean; // k x 1
+ t_variance_img _variance; // k x 1 within group
+
+ /// \}
+
+ /// Greylevels description.
+ /// \{
+ /// \brief The information are concerned with the greylevel input image.
+ ///
+ /// The group image allow us to decide which greylevel (and of course
+ /// which pixel) is assigned to a center. The distance image give us a
+ /// clue on how a greylevel could contribute to a center. The summation
+ /// over the greylevels of a center give us the within variance.
+
+ t_group_img _group; // g x 1 because dim(t_value) = 1
+ t_distance_img _distance; // label x graylevel
+
+ /// \}
+
+ /// Debugging, calibrating and testing results.
+ /// \{
+ /// \brief Some exports information to control the results.
+ ///
+ /// We come back in the input space. Label is the image which associates
+ /// each pixel to its center. Color is the image which gives a random rgb
+ /// color to each label. We can then visualize the regions of the same
+ /// label (assigned to the same center) in the image. The mean image
+ /// associate the mean of each pixel center to each pixel. We obtain thus
+ /// a rebuilded image.
+
+ t_label_dbg _label_dbg;
+ t_color_dbg _color_dbg;
+ t_mean_dbg _mean_dbg;
+
+ /// \}
+
+ /// Debugging, calibrating and testing convergence.
+ /// \{
+ /// \brief Trace the variance and the center evolution.
+ ///
+ /// The mean_cnv image is a trace of the evolution of the mean' signal.
+ /// We can observe the variation of the mean of each center along the
+ /// kmean loop or along the different launch. The variance_cnv is a trace
+ /// of the within variance along the kmean loop or along the different
+ /// launch.
+
+ t_mean_cnv _mean_cnv;
+ t_variance_cnv _variance_cnv;
+
+ /// \}
+ };
+
+#ifndef MLN_INCLUDE_ONLY
+
+ //--------------------------------------------------------------------------
+ // Constructor
+ //--------------------------------------------------------------------------
+
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ kmean1d<T,n,k>::kmean1d(const image2d< t_value >& point,
+ const unsigned watch_dog,
+ const unsigned n_times)
+ {
+ trace::entering("mln::clustering::kmean1d::kmean1d");
+ mln_precondition(point.is_valid());
+
+
+ _watch_dog = watch_dog;
+ _n_times = n_times;
+
+ _point = point;
+ _histo = data::compute(accu::meta::stat::histo1d(), _point);
+
+ _number.init_(box1d(point1d(0),point1d(k-1)));
+ _mean.init_(box1d(point1d(0),point1d(k-1)));
+ _variance.init_(box1d(point1d(0),point1d(k-1)));
+
+ _group.init_(box1d(point1d(mln_min(t_value)), point1d(mln_max(t_value))));
+ _distance.init_(box2d(point2d(mln_min(t_value), 0),
+ point2d(mln_max(t_value), k-1)));
+
+ // Debugging, calibrating and testing
+ initialize(_label_dbg, _point);
+ initialize(_color_dbg, _point);
+ initialize(_mean_dbg, _point);
+
+ // Observing the convergence
+ _variance_cnv.init_(box2d(point2d(0, 0),
+ point2d(_watch_dog-1, _n_times-1)));
+
+ _mean_cnv.init_(box3d(point3d(0, 0, 0),
+ point3d(k-1, _watch_dog-1, _n_times-1)));
+
+
+ trace::exiting("mln::clustering::kmean1d::kmean1d");
+ }
+
+ //--------------------------------------------------------------------------
+ // Mutators and accessors
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_point(t_point_img& point)
+ {
+ trace::entering("mln::clustering::kmean1d::set_point");
+
+ _point = point;
+
+ trace::exiting("mln::clustering::kmean1d::set_point");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_histo(t_histo_img& histo)
+ {
+ trace::entering("mln::clustering::kmean1d::set_histo");
+
+ _histo = histo;
+
+ trace::exiting("mln::clustering::kmean1d::set_histo");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_number(t_number_img& number)
+ {
+ trace::entering("mln::clustering::kmean1d::set_number");
+
+ _number = number;
+
+ trace::exiting("mln::clustering::kmean1d::set_number");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_mean(t_mean_img& mean)
+ {
+ trace::entering("mln::clustering::kmean1d::set_mean");
+
+ _mean = mean;
+
+ trace::exiting("mln::clustering::kmean1d::set_mean");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_variance(t_variance_img& variance)
+ {
+ trace::entering("mln::clustering::kmean1d::set_variance");
+
+ _variance = variance;
+
+ trace::exiting("mln::clustering::kmean1d::set_variance");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_group(t_group_img& group)
+ {
+ trace::entering("mln::clustering::kmean1d::set_group");
+
+ _group = group;
+
+ trace::exiting("mln::clustering::kmean1d::set_group");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::set_distance(t_distance_img& distance)
+ {
+ trace::entering("mln::clustering::kmean1d::set_distance");
+
+ _distance = distance;
+
+ trace::exiting("mln::clustering::kmean1d::set_distance");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_point_img& kmean1d<T,n,k>::get_point()
+ {
+ trace::entering("mln::clustering::kmean1d::get_point");
+
+ trace::exiting("mln::clustering::kmean1d::get_point");
+ return _point;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_histo_img& kmean1d<T,n,k>::get_histo()
+ {
+ trace::entering("mln::clustering::kmean1d::get_histo");
+
+ trace::exiting("mln::clustering::kmean1d::get_histo");
+ return _histo;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_number_img& kmean1d<T,n,k>::get_number()
+ {
+ trace::entering("mln::clustering::kmean1d::get_number");
+
+ trace::exiting("mln::clustering::kmean1d::get_number");
+ return _number;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_mean_img& kmean1d<T,n,k>::get_mean()
+ {
+ trace::entering("mln::clustering::kmean1d::get_mean");
+
+ trace::exiting("mln::clustering::kmean1d::get_mean");
+ return _mean;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_variance_img& kmean1d<T,n,k>::get_variance()
+ {
+ trace::entering("mln::clustering::kmean1d::get_variance");
+
+ trace::exiting("mln::clustering::kmean1d::get_variance");
+ return _variance;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_group_img& kmean1d<T,n,k>::get_group()
+ {
+ trace::entering("mln::clustering::kmean1d::get_group");
+
+ trace::exiting("mln::clustering::kmean1d::get_group");
+ return _group;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_distance_img& kmean1d<T,n,k>::get_distance()
+ {
+ trace::entering("mln::clustering::kmean1d::get_distance");
+
+ trace::exiting("mln::clustering::kmean1d::get_distance");
+ return _distance;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_color_dbg& kmean1d<T,n,k>::get_color_dbg()
+ {
+ trace::entering("mln::clustering::kmean1d::get_color_dbg");
+
+ trace::exiting("mln::clustering::kmean1d::get_color_dbg");
+ return _color_dbg;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_mean_dbg& kmean1d<T,n,k>::get_mean_dbg()
+ {
+ trace::entering("mln::clustering::kmean1d::get_mean_dbg");
+
+ trace::exiting("mln::clustering::kmean1d::get_mean_dbg");
+ return _mean_dbg;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_label_dbg& kmean1d<T,n,k>::get_label_dbg()
+ {
+ trace::entering("mln::clustering::kmean1d::get_label_dbg");
+
+ trace::exiting("mln::clustering::kmean1d::get_label_dbg");
+ return _label_dbg;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_mean_cnv& kmean1d<T,n,k>::get_mean_cnv()
+ {
+ trace::entering("mln::clustering::kmean1d::get_mean_cnv");
+
+ trace::exiting("mln::clustering::kmean1d::get_mean_cnv");
+ return _mean_cnv;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_variance_cnv& kmean1d<T,n,k>::get_variance_cnv()
+ {
+ trace::entering("mln::clustering::kmean1d::get_variance_cnv");
+
+ trace::exiting("mln::clustering::kmean1d::get_variance_cnv");
+ return _variance_cnv;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ typename kmean1d<T,n,k>::t_mean_img& kmean1d<T,n,k>::to_result()
+ {
+ trace::entering("mln::clustering::kmean1d::to_result");
+
+ trace::exiting("mln::clustering::kmean1d::to_result");
+ return _mean_min;
+ }
+
+
+ //--------------------------------------------------------------------------
+ // Initialization of centers
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::init_mean_regular()
+ {
+ trace::entering("mln::clustering::kmean1d::init_mean_regular");
+ T step = (mln_max(t_value) - mln_min(t_value)) / (k-1);
+ mln_piter(image1d<t_value>) l(_mean.domain());
+
+ for_all(l)
+ {
+ _mean(l) = (l.ind()*step) + mln_min(t_value);
+ }
+
+ trace::exiting("mln::clustering::kmean1d<T,n,k>::init_mean_regular");
+ }
+
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::init_mean_random()
+ {
+ trace::exiting("mln::clustering::kmean1d::init_mean_random");
+
+ t_value min = mln_min(t_value);
+ t_value max = mln_max(t_value);
+ mln_piter(image1d<t_value>) l(_mean.domain());
+
+ for_all(l)
+ {
+ _mean(l) = (rand() % (max-min)) + min;
+ }
+
+ trace::exiting("mln::clustering::kmean1d::init_mean_random");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::init_mean()
+ {
+ trace::entering("mln::clustering::kmean1d::init_mean");
+
+ init_mean_random();
+
+ trace::exiting("mln::clustering::kmean1d::init_mean");
+ }
+
+ //--------------------------------------------------------------------------
+ // Computations of distance, group, center, within variance
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::update_distance()
+ {
+ trace::entering("mln::clustering::kmean1d::update_distance");
+
+ mln_piter(t_distance_img) d(_distance.domain());
+
+ for_all(d)
+ {
+ // the square distance
+ _distance(d) = math::sqr(d.row() - _mean(point1d(d.col())));
+ /*
+ std::cout << "row : " << d.row() << std::endl;
+ std::cout << "col : " << d.col() << std::endl;
+ std::cout << "center : " << _mean(point1d(d.col())) << std::endl;
+ std::cout << "distance : " << _distance(d) << std::endl;
+ std::cout << "--------------------------------------" << std::endl;
+ */
+ }
+
+ trace::exiting("mln::clustering::kmean1d::update_distance");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::update_group()
+ {
+ trace::entering("mln::clustering::kmean1d::update_group");
+
+ mln_piter(t_group_img) g(_group.domain());
+
+ for_all(g)
+ {
+ mln_piter(t_mean_img) l(_mean.domain());
+ T min = mln_max(T);
+ t_label label = mln_max(t_label);
+
+ //std::cout << "g = " << g << std::endl;
+
+ for_all(l)
+ {
+ if (min > _distance(point2d(g.ind(),l.ind())))
+ {
+ min = _distance(point2d(g.ind(),l.ind()));
+ label = l.ind();
+ }
+
+ //std::cout << "d(" << l << ") = " <<
+ // _distance(point2d(g.ind(), l.ind())) << std::endl;
+ }
+
+ //std::cout << "g = " << g << std::endl;
+
+ _group(g) = label;
+ //std::cout << "group = " << _group(g) << std::endl;
+ //std::cout << "-----------" << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean1d::update_group");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::update_mean()
+ {
+ trace::entering("mln::clustering::kmean1d::update_mean");
+
+ /// FIXME VERIFIER QUE L'ON PEUT OBTENIR UNE IMAGE EN NDG SIGNE
+
+ // avec g le niveau de gris (signed or not signed)
+ // w[g] la classe de g sous forme d'image
+ // h[g] l'histogramme de l'image sous forme d'image
+ //
+ // Vg in [0..255]
+ // si w[g] = l
+ // c[l] += g
+ // n[l] += h(g)
+ //
+ // c[l] /= n
+
+ data::fill(_mean, literal::zero);
+ data::fill(_number, literal::zero);
+
+ mln_piter(t_group_img) g(_group.domain());
+
+ for_all(g)
+ {
+ _mean(point1d(_group(g))) += _histo(g) * g.ind();
+ _number(point1d(_group(g))) += _histo(g);
+ }
+
+ mln_piter(t_mean_img) l(_mean.domain());
+
+ /*
+ for_all(l)
+ {
+ std::cout << "c(" << l << ") = " << _mean(l) << std::endl;
+ std::cout << "n(" << l << ") = " << _number(l) << std::endl;
+ }
+ */
+
+ for_all(l)
+ {
+ _mean(l) /= _number(l);
+ //std::cout << "c(" << l << ") = " << _mean(l) << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean1d::update_mean");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::update_variance()
+ {
+ trace::entering("mln::clustering::kmean1d::update_variance");
+
+ T _within_variance = literal::zero;
+ mln_piter(t_variance_img) l(_variance.domain());
+
+ for_all(l)
+ {
+ _variance(l) = literal::zero;
+
+ mln_piter(t_group_img) g(_group.domain());
+
+ for_all(g)
+ {
+ _variance(l) += _distance(point2d(g.ind(), l.ind()));
+ }
+
+ _within_variance += _variance(l);
+ //std::cout << "v(" << l << ") = " << _variance(l) << std::endl;
+ }
+
+ //std::cout << "result" << result << std::endl;
+
+ trace::exiting("mln::clustering::kmean1d::update_variance");
+ }
+
+ //--------------------------------------------------------------------------
+ // Tools
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::build()
+ {
+ trace::entering("build");
+
+ mln_piter(t_point_img) pi(_point.domain());
+ mln_piter(t_label_dbg) po(_label_dbg.domain());
+
+ for_all_2(pi, po)
+ {
+ t_value val = _point(pi);
+ t_label grp = _group(point1d(val));
+
+ _label_dbg(po) = grp;
+ }
+
+ trace::exiting("build");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::to_result2()
+ {
+ typedef value::rgb8 rgb8;
+ std::cout << "BUILDING OUTPUT" << std::endl;
+
+ build();
+
+ std::cout << "COLORING OUTPUT" << std::endl;
+
+ _mean_dbg = labeling::mean_values(_point, _label_dbg, k);
+ _color_dbg = labeling::colorize(rgb8(), _label_dbg);
+
+ mln::io::pgm::save(_mean_dbg, "mean.pgm");
+ mln::io::ppm::save(_color_dbg, "rgb.pgm");
+ mln::io::pgm::save(_label_dbg, "label.pgm");
+ }
+
+
+ //--------------------------------------------------------------------------
+ // Checking the validity of the results
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ bool kmean1d<T,n,k>::is_descent_valid()
+ {
+ trace::entering("mln::clustering::kmean1d::is_descent_valid");
+ bool result = true;
+
+ mln_piter(t_number_img) l(_number.domain());
+
+ for_all(l)
+ {
+ result = result && (_number(l) != 0.0);
+ }
+
+ result = result && (_current_step < _watch_dog);
+
+ trace::exiting("mln::clustering::kmean1d::is_descent_valid");
+ return result;
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ bool kmean1d<T,n,k>::is_valid()
+ {
+ trace::entering("mln::clustering::kmean1d::is_valid");
+ bool result = true;
+
+ mln_piter(t_number_img) l(_number.domain());
+
+ for_all(l)
+ {
+ result = result && (_number(l) != 0.0);
+ }
+
+ trace::exiting("mln::clustering::kmean1d::is_valid");
+ return result;
+ }
+
+
+ //--------------------------------------------------------------------------
+ // Main loop
+ //--------------------------------------------------------------------------
+
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::launch_one_time()
+ {
+ trace::entering("mln::clustering::kmean1d::launch_one_time");
+
+ // Initialization to start the descent
+ _within_variance = mln_max(t_result)/2;
+ t_result old_variance = mln_max(t_result);
+
+ // Choose random points
+ init_mean();
+
+ // Execute the descent
+ for (unsigned i = 0; i<_watch_dog && _within_variance<old_variance; ++i)
+ {
+ update_distance();
+ update_group();
+ update_mean();
+
+ old_variance = _within_variance;
+
+ update_variance(); // update _within_variance
+ }
+
+ trace::exiting("mln::clustering::kmean1d::launch_one_time");
+ }
+
+ template <typename T, unsigned n, unsigned k>
+ inline
+ void kmean1d<T,n,k>::launch_n_times()
+ {
+ trace::entering("mln::clustering::kmean1d::launch_n_times");
+
+ _variance_min = mln_max(t_result);
+
+ // Execute the descent n times
+ for (unsigned i = 0; i < _n_times; ++i)
+ {
+ launch_one_time();
+
+ if (!is_descent_valid())
+ --i;
+ else
+ {
+ if (_within_variance < _variance_min)
+ {
+ _variance_min = _within_variance;
+ _mean_min = _mean;
+ _launching_min = i;
+ }
+ }
+
+ std::cout << "within_variance[" << i << "] = "
+ << _within_variance << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean1d::launch_n_times");
+ }
+
+#endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::clustering
+
+} // end of namespace mln
+
+#endif // ! MLN_CLUSTERING_KMEAN1D_HH
diff --git a/trunk/milena/sandbox/green/tests/clustering/kmean1d/Makefile.am b/trunk/milena/sandbox/green/tests/clustering/kmean1d/Makefile.am
new file mode 100644
index 0000000..cdf3021
--- /dev/null
+++ b/trunk/milena/sandbox/green/tests/clustering/kmean1d/Makefile.am
@@ -0,0 +1,148 @@
+#
+# Generic Makefile
+#
+
+#########
+# TOOLS #
+#########
+
+INCLUDES= -I$(HOME)/svn/oln/trunk/milena/sandbox/green
+CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe $(INCLUDES)
+ECHO= echo
+RM= rm
+MKDIR= mkdir -p
+CP= cp
+
+SOURCE_PATTERN= green/tests
+BUILD__PATTERN= green/build/tests
+
+
+ifeq ($(findstring $(BUILD__PATTERN),$(PWD)), $(BUILD__PATTERN))
+# Case where make is done from build directory.
+SOURCE_DIR= $(subst $(BUILD__PATTERN),$(SOURCE_PATTERN),$(PWD))
+BUILD__DIR= $(PWD)/
+else
+# Case where make is done from source directory.
+SOURCE_DIR= $(PWD)/
+BUILD__DIR= $(subst $(SOURCE_PATTERN),$(BUILD__PATTERN),$(PWD))
+endif
+
+SRC= $(notdir $(wildcard $(SOURCE_DIR)/*.cc))
+OLD= $(notdir $(wildcard $(SOURCE_DIR)/*~))
+OBJ= $(patsubst %.cc,%.o,$(SRC))
+SOURCE_MAKEFILE=Makefile.am
+BUILD__MAKEFILE=Makefile
+TARGET_FILE= $(notdir $(PWD))
+SOURCE_FILES= $(notdir $(wildcard $(SOURCE_DIR)/*.*))
+BUILD__FILES= $(filter-out $(SRC) $(SOURCE_MAKEFILE), $(SOURCE_FILES))
+
+BUILD__F_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__FILES))
+SOURCE_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_FILES))
+
+BUILD__M_PATH= $(addprefix $(BUILD__DIR)/,$(BUILD__MAKEFILE))
+SOURCE_M_PATH= $(addprefix $(SOURCE_DIR)/,$(SOURCE_MAKEFILE))
+
+TARGET_F_PATH= $(addprefix $(BUILD__DIR)/,$(TARGET_FILE))
+OBJ_F_PATH= $(addprefix $(BUILD__DIR)/,$(OBJ))
+SRC_F_PATH= $(addprefix $(SOURCE_DIR)/,$(SRC))
+OLD_F_PATH= $(addprefix $(SOURCE_DIR)/,$(OLD))
+
+#############
+# BOOTSTRAP #
+#############
+
+
+bootstrap: $(BUILD__DIR) $(BUILD__F_PATH) $(BUILD__M_PATH)
+
+# Create, if nessary, the destination directory
+$(BUILD__DIR):
+ $(MKDIR) $(BUILD__DIR)
+
+# Copy, if nessary, all the files, except the Makefile.am
+$(BUILD__F_PATH): $(SOURCE_F_PATH)
+ $(CP) $(addprefix $(SOURCE_DIR),$(@F)) $@
+
+# Copy if nessary, the Makefile.am into Makefile
+$(BUILD__M_PATH): $(SOURCE_M_PATH)
+ $(CP) $(SOURCE_M_PATH) $(BUILD__M_PATH)
+
+
+#######
+# ALL #
+#######
+
+# We assume that the call is done from the build directory.
+# With the directive vpath, hidden files are found in the source directory.
+
+all: $(TARGET_F_PATH)
+
+
+$(TARGET_F_PATH): $(OBJ_F_PATH)
+ $(LINK.cc) $< $(LOADLIBES) $(LDLIBS) -o $@
+
+$(OBJ_F_PATH):$(SRC_F_PATH)
+ $(COMPILE.cc) $(OUTPUT_OPTION) $<
+
+
+#########
+# CLEAN #
+#########
+
+# Force every time the deletion
+clean: clean_target clean_obj clean_dst clean_old #clean_make
+
+
+clean_target:
+ -@$(RM) $(TARGET_F_PATH) &> /dev/null
+
+clean_obj:
+ -@$(RM) $(OBJ_F_PATH) &> /dev/null
+
+clean_dst:
+ -@$(RM) $(BUILD_F_PATH) &> /dev/null
+
+clean_make:
+ -@$(RM) $(BUILD_M_PATH) &> /dev/null
+
+clean_old:
+ -@$(RM) $(OLD_F_PATH) &> /dev/null
+
+
+#########
+# PRINT #
+#########
+
+print: print_tools print_bootstrap
+
+print_tools:
+ @$(ECHO) "HOME = $(HOME)"
+ @$(ECHO) "INCLUDES = $(INCLUDES)"
+ @$(ECHO) "CXXFLAGS = $(CXXFLAGS)"
+ @$(ECHO) "ECHO = $(ECHO)"
+ @$(ECHO) "RM = $(RM)"
+ @$(ECHO) "MKDIR = $(MKDIR)"
+ @$(ECHO) "CP = $(CP)"
+ @$(ECHO)
+
+print_bootstrap:
+ @$(ECHO) "PWD = $(PWD)"
+ @$(ECHO) "SOURCE_PATTERN = $(SOURCE_PATTERN)"
+ @$(ECHO) "BUILD__PATTERN = $(BUILD__PATTERN)"
+ @$(ECHO) "SOURCE_DIR = $(SOURCE_DIR)"
+ @$(ECHO) "BUILD__DIR = $(BUILD__DIR)"
+ @$(ECHO) "SOURCE_MAKEFILE = $(SOURCE_MAKEFILE)"
+ @$(ECHO) "BUILD__MAKEFILE = $(BUILD__MAKEFILE)"
+ @$(ECHO) "TARGET_FILE = $(TARGET_FILE)"
+ @$(ECHO) "SOURCE_FILES = $(SOURCE_FILES)"
+ @$(ECHO) "SOURCE_F_PATH = $(SOURCE_F_PATH)"
+ @$(ECHO) "BUILD__FILES = $(BUILD__FILES)"
+ @$(ECHO) "BUILD__F_PATH = $(BUILD__F_PATH)"
+ @$(ECHO) "BUILD__M_PATH = $(BUILD__M_PATH)"
+ @$(ECHO) "SOURCE_M_PATH = $(SOURCE_M_PATH)"
+ @$(ECHO) "SRC = $(SRC)"
+ @$(ECHO) "OBJ = $(OBJ)"
+ @$(ECHO) "OLD = $(OLD)"
+ @$(ECHO) "SRC_F_PATH = $(SRC_F_PATH)"
+ @$(ECHO) "OBJ_F_PATH = $(OBJ_F_PATH)"
+ @$(ECHO) "OLD_F_PATH = $(OLD_F_PATH)"
+ @$(ECHO)
diff --git a/trunk/milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc b/trunk/milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
new file mode 100644
index 0000000..fe5b6cf
--- /dev/null
+++ b/trunk/milena/sandbox/green/tests/clustering/kmean1d/kmean1d.cc
@@ -0,0 +1,483 @@
+// UNARY TESTS ON KMEAN1D
+
+#include <mln/clustering/kmean1d.hh>
+
+#include <iostream>
+
+#include <mln/pw/value.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/rgb8.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/algebra/vec.hh>
+#include <mln/algebra/mat.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/contract.hh>
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/io/ppm/load.hh>
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/img_path.hh>
+
+#include <mln/data/transform.hh>
+
+#include <mln/trait/value/print.hh>
+#include <mln/trait/image/print.hh>
+
+#define SIZE_IMAGE 512
+#define SIZE_SAMPLE1 (512*512)
+#define SIZE_SAMPLE2 4
+#define NB_CENTER 2
+#define DIM_POINT 3
+#define TYPE_POINT double
+
+/*
+void test_instantiation()
+{
+ typedef mln::value::int_u8 int_u8;
+ typedef mln::image2d<int_u8> image2d_int_u8;
+ image2d_int_u8 house;
+
+ mln::io::pgm::load(house, OLENA_IMG_PATH"/house.pgm");
+
+ mln::clustering::kmean1d<double, 8, 3> kmean(house);
+
+ // test the compilation
+ std::cout << "test instantiation : ok" << std::endl;
+}
+
+void test_init_center()
+{
+ typedef mln::value::int_u8 int_u8;
+ typedef mln::image2d<int_u8> image2d_int_u8;
+ image2d_int_u8 house;
+
+ mln::io::pgm::load(house, OLENA_IMG_PATH"/house.pgm");
+
+ mln::clustering::kmean1d<double, 8, 3> kmean(house);
+
+ kmean.init_center();
+
+ std::cout << "test init center : ok" << std::endl;
+}
+*/
+
+void test_init_loop()
+{
+ typedef mln::value::int_u8 int_u8;
+ typedef mln::image2d<int_u8> image2d_int_u8;
+ image2d_int_u8 house;
+
+ mln::io::pgm::load(house, OLENA_IMG_PATH"/house.pgm");
+
+ mln::clustering::kmean1d<double, 8, 3> kmean(house);
+
+ kmean.launch_n_times();
+
+ std::cout << "test loop : ok" << std::endl;
+}
+
+
+
+/*
+struct rgb8_to_4colors : mln::Function_v2v<rgb8_to_4colors>
+{
+ typedef mln::value::rgb8 result;
+
+ mln::value::rgb8 operator()(const mln::value::rgb8& color) const
+ {
+ mln::value::rgb8 result;
+ unsigned hash = (color.red() + color.green() + color.blue()) % 4;
+
+ switch (hash)
+ {
+ case 0: result = mln::literal::lime; break;
+ case 1: result = mln::literal::brown; break;
+ case 2: result = mln::literal::teal; break;
+ case 3: result = mln::literal::purple; break;
+ }
+
+ return result;
+ }
+};
+
+
+void print_color(const mln::value::rgb8& color)
+{
+ std::cout << "{r=" << color.red() << ", ";
+ std::cout << "g=" << color.green() << ", ";
+ std::cout << "b=" << color.blue() << "}" << std::endl;
+}
+
+void fill_image_with_4colors(mln::image2d<mln::value::rgb8>& img)
+{
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+
+ img = mln::data::transform(img, rgb8_to_4colors());
+
+ //print_color(lime);
+ //print_color(brown);
+ //print_color(teal);
+ //print_color(purple);
+}
+
+bool is_equivalent(const mln::image2d<mln::value::rgb8>& img,
+ const MAT_POINT1& point)
+{
+ mln_piter_(mln::image2d<mln::value::rgb8>) pi(img.domain());
+ bool result = true;
+ unsigned index = -1;
+
+ for_all(pi)
+ {
+ bool test = true;
+
+ ++index;
+
+ test = test && (point(index,0) == img(pi).red());
+ test = test && (point(index,1) == img(pi).green());
+ test = test && (point(index,2) == img(pi).blue());
+
+ if (!test)
+ {
+ std::cout << pi;
+ std::cout << "{r=" << img(pi).red() << ", ";
+ std::cout << "g=" << img(pi).green() << ", ";
+ std::cout << "b=" << img(pi).blue() << "}";
+ std::cout << index;
+ std::cout << "[r=" << point(index,0) << ", ";
+ std::cout << "g=" << point(index,1) << ", ";
+ std::cout << "b=" << point(index,2) << "]" << std::endl;
+
+ mln_assertion(test);
+ }
+
+ result &= test;
+ }
+
+ return result;
+}
+
+void test_init_point()
+{
+ typedef mln::value::rgb8 rgb8;
+ mln::image2d<rgb8> img_ref;
+
+ mln::clustering::k_mean<SIZE_SAMPLE1,NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ mln::io::ppm::load(img_ref, "/usr/local/share/olena/images/lena.ppm");
+ //mln::io::ppm::save(img_ref, "verif.ppm");
+
+ fill_image_with_4colors(img_ref);
+ kmean.init_point(img_ref);
+
+ mln_assertion(true == is_equivalent(img_ref, kmean.get_point()));
+
+ std::cout << "Test init point : ok" << std::endl;
+}
+
+void set_point(MAT_POINT2& point,
+ const unsigned index,
+ const mln::value::rgb8& color)
+{
+ point(index,0) = color.red();
+ point(index,1) = color.green();
+ point(index,2) = color.blue();
+}
+
+void fake_init_point(MAT_POINT2& point,
+ const mln::value::rgb8& point1,
+ const mln::value::rgb8& point2,
+ const mln::value::rgb8& point3,
+ const mln::value::rgb8& point4)
+{
+ set_point(point, 0, point1);
+ set_point(point, 1, point2);
+ set_point(point, 2, point3);
+ set_point(point, 3, point4);
+}
+
+bool is_equal(const mln::value::rgb8& ref,
+ const MAT_CENTER& center,
+ const unsigned i)
+{
+ bool result = true;
+
+ result = result && (center(i, 0) - ref.red() < 1.0);
+ result = result && (center(i, 1) - ref.green() < 1.0);
+ result = result && (center(i, 2) - ref.blue() < 1.0);
+
+ return result;
+}
+
+void test_init_center()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+
+ fake_init_point(kmean.get_point(), lime, brown, teal, purple);
+ kmean.init_center();
+
+ mln_assertion(is_equal(lime, kmean.get_center(), 0) ||
+ is_equal(brown, kmean.get_center(), 0) ||
+ is_equal(teal, kmean.get_center(), 0) ||
+ is_equal(purple, kmean.get_center(), 0));
+
+ mln_assertion(is_equal(lime, kmean.get_center(), 1) ||
+ is_equal(brown, kmean.get_center(), 1) ||
+ is_equal(teal, kmean.get_center(), 1) ||
+ is_equal(purple, kmean.get_center(), 1));
+
+ std::cout << "Test init center : ok" << std::endl;
+}
+
+void set_center(MAT_CENTER& center,
+ const unsigned index,
+ const mln::value::rgb8& color)
+{
+ center(index,0) = color.red();
+ center(index,1) = color.green();
+ center(index,2) = color.blue();
+}
+
+void fake_init_center(MAT_CENTER& center,
+ const mln::value::rgb8 center1,
+ const mln::value::rgb8 center2)
+{
+
+ set_center(center, 0, center1);
+ set_center(center, 1, center2);
+}
+
+
+double dist(mln::value::rgb8 color1, mln::value::rgb8 color2)
+{
+ double red = color1.red() - color2.red();
+ double green = color1.green() - color2.green();
+ double blue = color1.blue() - color2.blue();
+ double result= red * red + green * green + blue * blue;
+
+ return result;
+}
+
+void test_update_distance()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+ const mln::value::rgb8 c1 = lime;
+ const mln::value::rgb8 c2 = purple;
+ const MAT_DISTANCE2& dist_v = kmean.get_distance();
+
+ fake_init_point(kmean.get_point(), lime, brown, teal, purple);
+ fake_init_center(kmean.get_center(), c1, c2);
+ kmean.update_distance();
+
+ mln_assertion(dist(lime, c1) == dist_v(0,0));
+ mln_assertion(dist(lime, c2) == dist_v(0,1));
+ mln_assertion(dist(brown, c1) == dist_v(1,0));
+ mln_assertion(dist(brown, c2) == dist_v(1,1));
+ mln_assertion(dist(teal, c1) == dist_v(2,0));
+ mln_assertion(dist(teal, c2) == dist_v(2,1));
+ mln_assertion(dist(purple, c1) == dist_v(3,0));
+ mln_assertion(dist(purple, c2) == dist_v(3,1));
+
+ std::cout << "Test update distance : ok" << std::endl;
+}
+
+void set_distance(MAT_DISTANCE2& distance,
+ const unsigned index,
+ const double d1,
+ const double d2)
+{
+ distance(index,0) = d1;
+ distance(index,1) = d2;
+}
+
+void fake_update_distance(MAT_DISTANCE2& distance,
+ const mln::value::rgb8& point1,
+ const mln::value::rgb8& point2,
+ const mln::value::rgb8& point3,
+ const mln::value::rgb8& point4,
+ const mln::value::rgb8& center1,
+ const mln::value::rgb8& center2)
+{
+ set_distance(distance, 0, dist(point1, center1), dist(point1, center2));
+ set_distance(distance, 1, dist(point2, center1), dist(point2, center2));
+ set_distance(distance, 2, dist(point3, center1), dist(point3, center2));
+ set_distance(distance, 3, dist(point4, center1), dist(point4, center2));
+
+
+ // for (int i = 0; i < SIZE_SAMPLE2; ++i)
+ //for (int j = 0; j < NB_CENTER; ++j)
+ // std::cout << "d(" << i << "," << j << ") = " << distance(i,j) <<std::endl;
+}
+
+void test_update_group()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+ const mln::value::rgb8 c1 = lime;
+ const mln::value::rgb8 c2 = purple;
+ const unsigned point1_min= 0; // lime near lime (c1)
+ const unsigned point2_min= 1; // brown near purple (c2)
+ const unsigned point3_min= 1; // teal near purple (c2)
+ const unsigned point4_min= 1; // purple near purple (c2)
+ const MAT_GROUP2& group = kmean.get_group();
+
+ fake_init_point(kmean.get_point(), lime, brown, teal, purple);
+ fake_init_center(kmean.get_center(), c1, c2);
+ fake_update_distance(kmean.get_distance(), lime, brown, teal, purple, c1, c2);
+ kmean.update_group();
+
+ mln_assertion(0.0 == group(0, 1 - point1_min));
+ mln_assertion(1.0 == group(0, point1_min));
+ mln_assertion(0.0 == group(1, 1 - point2_min));
+ mln_assertion(1.0 == group(1, point2_min));
+ mln_assertion(0.0 == group(2, 1 - point3_min));
+ mln_assertion(1.0 == group(2, point3_min));
+ mln_assertion(0.0 == group(3, 1 - point4_min));
+ mln_assertion(1.0 == group(3, point4_min));
+
+ std::cout << "Test update group : ok" << std::endl;
+}
+
+void set_group(MAT_GROUP2& group,
+ const unsigned index,
+ const unsigned min)
+{
+ group(index, min) = 1.0;
+ group(index, 1-min) = 0.0;
+}
+
+
+void fake_update_group(MAT_GROUP2& group,
+ const unsigned& point1_min,
+ const unsigned& point2_min,
+ const unsigned& point3_min,
+ const unsigned& point4_min)
+{
+ set_group(group, 0, point1_min);
+ set_group(group, 1, point2_min);
+ set_group(group, 2, point3_min);
+ set_group(group, 3, point4_min);
+}
+
+void test_update_center()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+ const mln::value::rgb8 c1 = lime;
+ const mln::value::rgb8 c2 = purple;
+ const unsigned pt1_min = 0; // lime near lime (c1)
+ const unsigned pt2_min = 1; // brown near purple (c2)
+ const unsigned pt3_min = 1; // teal near purple (c2)
+ const unsigned pt4_min = 1; // purple near purple (c2)
+ const mln::value::rgb8 mean_c1 = lime;
+ const mln::value::rgb8 mean_c2 = (brown+teal+purple)/3;
+
+ fake_init_point(kmean.get_point(), lime, brown, teal, purple);
+ fake_init_center(kmean.get_center(), c1, c2);
+ fake_update_distance(kmean.get_distance(), lime, brown, teal, purple, c1, c2);
+ fake_update_group(kmean.get_group(), pt1_min, pt2_min, pt3_min, pt4_min);
+ kmean.update_center();
+
+ mln_assertion(is_equal(mean_c1, kmean.get_center(), 0));
+ mln_assertion(is_equal(mean_c2, kmean.get_center(), 1));
+
+ std::cout << "Test update center : ok" << std::endl;
+}
+
+void test_update_variance()
+{
+ mln::clustering::k_mean<SIZE_SAMPLE2, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ const mln::value::rgb8 lime = mln::literal::lime;
+ const mln::value::rgb8 brown = mln::literal::brown;
+ const mln::value::rgb8 teal = mln::literal::teal;
+ const mln::value::rgb8 purple = mln::literal::purple;
+ const mln::value::rgb8 c1 = lime;
+ const mln::value::rgb8 c2 = purple;
+ const unsigned pt1_min = 0; // lime near lime (c1)
+ const unsigned pt2_min = 1; // brown near purple (c2)
+ const unsigned pt3_min = 1; // teal near purple (c2)
+ const unsigned pt4_min = 1; // purple near purple (c2)
+ const double v1 = 0;
+ const double v2 = dist(purple, brown) + dist(purple, teal);
+ const mln::value::rgb8 mean_c2 = (brown+teal+purple)/3;
+ const VEC_VAR& var = kmean.get_variance();
+
+ fake_init_point(kmean.get_point(), lime, brown, teal, purple);
+ fake_init_center(kmean.get_center(), c1, c2);
+ fake_update_distance(kmean.get_distance(), lime, brown, teal, purple, c1, c2);
+ fake_update_group(kmean.get_group(), pt1_min, pt2_min, pt3_min, pt4_min);
+ kmean.update_variance();
+
+ mln_assertion(v1 == var[0]);
+ mln_assertion(v2 == var[1]);
+
+ std::cout << "Test update variance : ok" << std::endl;
+}
+
+void test_loop()
+{
+ typedef mln::value::rgb8 rgb8;
+ mln::image2d<rgb8> img_ref;
+
+ mln::clustering::k_mean<SIZE_SAMPLE1, NB_CENTER, DIM_POINT, TYPE_POINT> kmean;
+
+ mln::io::ppm::load(img_ref, "/usr/local/share/olena/images/lena.ppm");
+ //mln::io::ppm::save(img_ref, "verif.ppm");
+
+ fill_image_with_4colors(img_ref);
+ kmean.init_point(img_ref);
+
+ kmean.loop(img_ref);
+
+
+ // std::cout << "Test update variance: ok" << std::endl;
+}
+*/
+
+int main()
+{
+ //test_instantiation();
+ //test_init_point();
+ // test_init_center();
+ test_init_loop();
+ //test_update_distance();
+ //test_update_group();
+ //test_update_center();
+ //test_update_variance();
+
+ // mln::trace::quiet = false;
+
+ //test_loop();
+
+ return 0;
+}
--
1.5.6.5
1
0