* green/mln/clustering/kmean1d.hh
(update_kmean, launch_one_time, is_valid, is_descent_valid): Introduce
_is_number_valid which turns to false when empty class appears.
* green/mln/clustering/kmean1d.hh
(launch_one_time): Fix method call order in kmean's loop.
* green/mln/clustering/kmean1d.hh
(launch_n_times): Introduce nb_tries that garanties to be infinite
loop safe.
Update kmean.launch_n_times method call.
* green/demo/clustering/kmean1d/kmean1d.cc
(do_demo): Add comments.
---
trunk/milena/sandbox/ChangeLog | 21 ++++
.../green/demo/clustering/kmean1d/kmean1d.cc | 4 +-
.../milena/sandbox/green/mln/clustering/kmean1d.hh | 97 ++++++++++++--------
3 files changed, 83 insertions(+), 39 deletions(-)
diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog
index 2f6ad31..7f3b3ab 100644
--- a/trunk/milena/sandbox/ChangeLog
+++ b/trunk/milena/sandbox/ChangeLog
@@ -1,3 +1,24 @@
+2009-09-29 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
+ Fix behaviour when empty class appears. Fix methods order of the
+ kmean1d loop.
+
+ * green/mln/clustering/kmean1d.hh
+ (update_kmean, launch_one_time, is_valid, is_descent_valid): Introduce
+ _is_number_valid which turns to false when empty class appears.
+
+ * green/mln/clustering/kmean1d.hh
+ (launch_one_time): Fix method call order in kmean's loop.
+
+ * green/mln/clustering/kmean1d.hh
+ (launch_n_times): Introduce nb_tries that garanties to be infinite
+ loop safe.
+
+ Update kmean.launch_n_times method call.
+
+ * green/demo/clustering/kmean1d/kmean1d.cc
+ (do_demo): Add comments.
+
2009-09-29 Fabien Freling <fabien.freling(a)lrde.epita.fr>
Update benchmark for types of image.
diff --git a/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
index f13f783..c0b9944 100644
--- a/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
+++ b/trunk/milena/sandbox/green/demo/clustering/kmean1d/kmean1d.cc
@@ -42,7 +42,9 @@ void do_demo(const std::string& image,
//mln::trace::quiet = false;
kmean.launch_n_times();
-
+
+ // Not safe because we don't test kmean.is_valid()
+
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();
diff --git a/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
index 9a8c1ea..9f467bd 100644
--- a/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
+++ b/trunk/milena/sandbox/green/mln/clustering/kmean1d.hh
@@ -125,6 +125,7 @@ namespace mln
/// \brief Constructor
/// \param[in] point : the image as the population of pixels.
+ /// \param[in] k_center : the number of centers.
/// \param[in] watch_dog : the limit to observe the convergence (10).
/// \param[in] n_times : the number of times that we executed it (10).
@@ -228,6 +229,7 @@ namespace mln
//------------------------------------------------------------------------
bool is_valid();
+ bool is_number_valid();
bool is_descent_valid();
//------------------------------------------------------------------------
@@ -287,6 +289,9 @@ namespace mln
t_result _within_variance;
unsigned _current_step;
unsigned _current_launching;
+ bool _is_number_valid;
+
+ static const unsigned _N_TRIES = 3;
/// \}
@@ -384,8 +389,6 @@ namespace mln
// Constructor
//--------------------------------------------------------------------------
- /// FIXME k must be a parameter, not a static compilation paramater.
-
template <typename T, unsigned n>
inline
kmean1d<T,n>::kmean1d(const t_point_img& point,
@@ -396,12 +399,15 @@ namespace mln
trace::entering("mln::clustering::kmean1d::kmean1d");
mln_precondition(point.is_valid());
- _k_center = k_center;
- _watch_dog = watch_dog;
- _n_times = n_times;
+ _k_center = k_center;
+ _watch_dog = watch_dog;
+ _n_times = n_times;
- _point = point;
- _histo = data::compute(accu::meta::stat::histo1d(), _point);
+ _point = point;
+ _histo = data::compute(accu::meta::stat::histo1d(), _point);
+
+ // Results aren't valid since they aren't available
+ _is_number_valid = false;
_number.init_(box1d(point1d(0),point1d(_k_center-1)));
_mean.init_(box1d(point1d(0),point1d(_k_center-1)));
@@ -804,7 +810,17 @@ namespace mln
*/
for_all(l)
{
+ // State the stopping propagation Nan flag
+ _is_number_valid = (0 != _number(l));
+
+ // Emergency exit
+ if (!_is_number_valid)
+ break;
+
+ // Compute the mean
_mean(l) /= _number(l);
+
+ // Debugging
std::cout << "c" << l << " = " << _mean(l)
<< std::endl;
}
@@ -932,45 +948,29 @@ namespace mln
bool kmean1d<T,n>::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);
+ bool result = _is_number_valid && (_current_step < _watch_dog);
trace::exiting("mln::clustering::kmean1d::is_descent_valid");
return result;
}
-
+
template <typename T, unsigned n>
inline
- bool kmean1d<T,n>::is_valid()
+ bool kmean1d<T,n>::is_number_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);
- }
+ bool result = _is_number_valid;
trace::exiting("mln::clustering::kmean1d::is_valid");
return result;
}
-
//--------------------------------------------------------------------------
// Main loop
//--------------------------------------------------------------------------
-
template <typename T, unsigned n>
inline
void kmean1d<T,n>::launch_one_time()
@@ -981,33 +981,40 @@ namespace mln
// Initialization to start the descent
t_result old_variance = mln_max(t_result);
+ _within_variance = mln_max(t_result);
+ _current_step = 0;
- // Choose random points and compute within variance
+ // Build the first group and evaluate its caharacteristics
init_mean();
update_distance();
- update_group();
- update_variance(); // update _within_variance
- std::cout << "first_variance : " << _within_variance <<
std::endl;
+ std::cout << "first_variance : " << old_variance <<
std::endl;
// Execute the descent
- for (_current_step = 0;
- _current_step < _watch_dog && _within_variance < old_variance;
- ++_current_step)
+ do
{
old_variance = _within_variance;
- update_mean();
- update_distance();
update_group();
+ update_mean(); // update _is_number_valid
+
+ // Stopping Nan propagation
+ if (!_is_number_valid)
+ break;
+
+ update_distance();
update_variance(); // update _within_variance
- // debugging code
+
+ // Debugging code
update_cnv();
std::cout << "_current_step : " << _current_step <<
std::endl;
std::cout << "_within_variance : " << _within_variance <<
std::endl;
+
+ ++_current_step;
}
+ while (_current_step < _watch_dog && _within_variance <
old_variance);
std::cout << "----------------------------------------" <<
std::endl;
@@ -1016,6 +1023,9 @@ namespace mln
trace::exiting("mln::clustering::kmean1d::launch_one_time");
}
+ /// FIXME There is a risk of infinite loop if convergence is not observed
+ /// FIXME What do we prefer, bad results or infinite loop ?
+
template <typename T, unsigned n>
inline
void kmean1d<T,n>::launch_n_times()
@@ -1025,6 +1035,9 @@ namespace mln
std::cout << "watch_dog : " << _watch_dog <<
std::endl;
std::cout << "n_times : " << _n_times <<
std::endl;
+ // number of times we reexecute launch_one_time without any success
+ unsigned tries = 0;
+
_variance_min = mln_max(t_result);
_current_launching = 0;
@@ -1033,7 +1046,7 @@ namespace mln
{
launch_one_time();
- if (is_descent_valid())
+ if (is_descent_valid() || _N_TRIES < tries)
{
if (_within_variance < _variance_min)
{
@@ -1042,6 +1055,9 @@ namespace mln
_launching_min = _current_launching;
}
+ // Reinitialize the number of echecs possible
+ tries = 0;
+
std::cout << "_current_launching : " << _current_launching
<< std::endl;
@@ -1050,8 +1066,13 @@ namespace mln
++_current_launching;
}
+ else
+ ++tries;
}
+ //Debugging code
+ build_all_dbg();
+
trace::exiting("mln::clustering::kmean1d::launch_n_times");
}
--
1.5.6.5