$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
kmean_rgb.hh
1 // Copyright (C) 2010, 2012, 2013 EPITA Research and Development
2 // Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_CLUSTERING_KMEAN_RGB_HH
28 # define MLN_CLUSTERING_KMEAN_RGB_HH
29 
96 
97 # include <limits.h>
98 # include <iostream>
99 
100 # include <mln/accu/stat/histo3d_rgb.hh>
101 
102 # include <mln/algebra/vec.hh>
103 
104 # include <mln/core/concept/image.hh>
105 # include <mln/core/contract.hh>
106 # include <mln/core/image/image2d.hh>
107 # include <mln/core/macros.hh>
108 
109 # include <mln/data/compute.hh>
110 # include <mln/data/fill.hh>
111 # include <mln/data/transform.hh>
112 
113 # include <mln/debug/println.hh>
114 
115 # include <mln/io/ppm/save.hh>
116 # include <mln/io/pgm/save.hh>
117 
118 # include <mln/labeling/colorize.hh>
119 # include <mln/labeling/mean_values.hh>
120 
121 # include <mln/literal/zero.hh>
122 # include <mln/literal/one.hh>
123 
124 # include <mln/math/min.hh>
125 # include <mln/math/sqr.hh>
126 
127 # include <mln/norm/l2.hh>
128 
129 # include <mln/opt/at.hh>
130 
131 # include <mln/debug/trace.hh>
132 
133 # include <mln/trait/value_.hh>
134 
135 # include <mln/util/array.hh>
136 
137 # include <mln/value/int_u.hh>
138 # include <mln/value/rgb8.hh>
139 # include <mln/value/label_8.hh>
140 
141 
142 //--------------------------------------------------------------------------
143 // FUNCTIONAL CODE
144 //--------------------------------------------------------------------------
145 
146 
147 namespace mln
148 {
149 
150  namespace clustering
151  {
170  template <typename T, unsigned n, typename I>
171  inline
172  mln_ch_value(I,value::label_8)
173  kmean_rgb(const Image<I>& point,
174  const unsigned k_center,
175  const unsigned watch_dog,
176  const unsigned n_times);
177 
178  } // end of namespace mln::clustering
179 
180  namespace clustering
181  {
182 
183 
184 # ifndef MLN_INCLUDE_ONLY
185 
186  //--------------------------------------------------------------------------
187  // Internal.
188  //--------------------------------------------------------------------------
189 
190  namespace internal
191  {
192 
193  //------------------------------------------------------------------------
194  // Debugging tools
195  //------------------------------------------------------------------------
196 
197  /*
198  template <typename T, unsigned n>
199  inline
200  void kmean3d_a<T,n>::build_label_dbg()
201  {
202  mln_trace("mln::clustering::kmean3d_a::build_label_dbg");
203 
204  mln_piter(t_point_img) pi(_point.domain());
205  mln_piter(t_label_dbg) po(_label_dbg.domain());
206 
207  for_all_2(pi, po)
208  {
209  t_value val = _point(pi);
210  t_label grp = _group(point3d(val.blue(), val.red(), val.green()));
211 
212  // As label zero has got a particular semantic, the first label is one
213  _label_dbg(po) = ++grp;
214  }
215 
216  }
217 
218  template <typename T, unsigned n>
219  inline
220  void kmean3d_a<T,n>::build_mean_dbg()
221  {
222  mln_trace("mln::clustering::kmean3d_a::build_mean_dbg");
223 
224  mln_piter(t_mean_dbg) p(_mean_dbg.domain());
225 
226  for_all(p)
227  {
228  _mean_dbg(p).red() = static_cast<unsigned>(_mean[_label_dbg(p)][0]);
229  _mean_dbg(p).green() = static_cast<unsigned>(_mean[_label_dbg(p)][1]);
230  _mean_dbg(p).blue() = static_cast<unsigned>(_mean[_label_dbg(p)][2]);
231  }
232 
233  }
234 
235 
236  template <typename T, unsigned n>
237  inline
238  void kmean3d_a<T,n>::build_all_dbg()
239  {
240  mln_trace("mln::clustering::kmean3d_a::build_all_dbg");
241  build_label_dbg();
242  //build_mean_dbg();
243  _mean_dbg = labeling::mean_values(_point, _label_dbg, _k_center);
244  _color_dbg = labeling::colorize(value::rgb8(), _label_dbg);
245 
246  }
247 
248  template <typename T, unsigned n>
249  inline
250  void kmean3d_a<T,n>::update_cnv()
251  {
252  mln_trace("mln::clustering::kmean3d_a::update_cnv");
253 
254  _variance_cnv[_current_launching](point1d(_current_step))
255  = _within_variance;
256 
257  mln_eiter(t_mean_img) l(_mean);
258 
259  for_all(l)
260  {
261  _mean_cnv[l.index_()][_current_launching](point1d(_current_step))
262  = _mean[l.index_()];
263  }
264 
265  }
266 
267  template <typename T, unsigned n>
268  inline
269  void kmean3d_a<T,n>::finalize_cnv()
270  {
271  mln_trace("mln::clustering::kmean3d_a::finalize_cnv");
272 
273  // saturate the curv with the within variance
274  for (unsigned i = _current_step; i < _watch_dog; ++i)
275  _variance_cnv[_current_launching](point1d(i)) = _within_variance;
276 
277  for (unsigned i = _current_step; i < _watch_dog; ++i)
278  {
279  mln_eiter(t_mean_img) l(_mean);
280 
281  for_all(l)
282  {
283  _mean_cnv[l.index_()][_current_launching](point1d(i))
284  = _mean[l.index_()];
285  }
286  }
287 
288  }
289 
290 
291 
292 
293  //--------------------------------------------------------------------------
294  // Printing temporary results
295  //--------------------------------------------------------------------------
296 
297  template <typename T, unsigned n>
298  inline
299  void kmean3d_a<T,n>::print_mean()
300  {
301  mln_trace("mln::clustering::kmean3d_a::print_mean");
302 
303  mln_eiter(t_mean_img) l(_mean);
304 
305  for_all(l)
306  {
307  std::cout << "mean(" << l.index_();
308  std::cout << ") = [r=" << _mean[l.index_()][0];
309  std::cout << ", g=" << _mean[l.index_()][1];
310  std::cout << ", b=" << _mean[l.index_()][2];
311  std::cout << "]" << std::endl;
312  }
313 
314  }
315 
316  template <typename T, unsigned n>
317  inline
318  void kmean3d_a<T,n>::print_number()
319  {
320  mln_trace("mln::clustering::kmean3d_a::print_number");
321 
322  mln_eiter(t_number_img) l(_number);
323 
324  for_all(l)
325  {
326  std::cout << "number(" << l.index_();
327  std::cout << ") = " << _number[l.index_()];
328  std::cout << std::endl;
329  }
330 
331  }
332 
333  template <typename T, unsigned n>
334  inline
335  void kmean3d_a<T,n>::print_variance()
336  {
337  mln_trace("mln::clustering::kmean3d_a::print_variance");
338 
339  mln_eiter(t_variance_img) l(_number);
340 
341  for_all(l)
342  {
343  std::cout << "variance(" << l.index_();
344  std::cout << ") = " << _variance[l.index_()];
345  std::cout << std::endl;
346  }
347 
348  }
349 
350  template <typename T, unsigned n>
351  inline
352  void kmean3d_a<T,n>::print_histo()
353  {
354  mln_trace("mln::clustering::kmean3d_a::print_histo");
355 
356  mln_piter(t_histo_img) rgb(_histo.domain());
357 
358  for_all(rgb)
359  {
360  if (0 < _histo(rgb))
361  {
362  std::cout << "histo(r=" << rgb.row();
363  std::cout << ", g=" << rgb.col();
364  std::cout << ", b=" << rgb.sli();
365  std::cout << ")= " << _histo(rgb);
366  std::cout << std::endl;
367  }
368  }
369 
370  }
371 
372  template <typename T, unsigned n>
373  inline
374  void kmean3d_a<T,n>::print_group()
375  {
376  mln_trace("mln::clustering::kmean3d_a::print_group");
377 
378  mln_piter(t_group_img) rgb(_group.domain());
379 
380  for_all(rgb)
381  {
382  if (0 < _histo(rgb))
383  {
384  std::cout << "group(r=" << rgb.row();
385  std::cout << ", g=" << rgb.col();
386  std::cout << ", b=" << rgb.sli();
387  std::cout << ")= " << _group(rgb);
388  std::cout << std::endl;
389  }
390  }
391 
392  }
393 
394  template <typename T, unsigned n>
395  inline
396  void kmean3d_a<T,n>::print_distance()
397  {
398  mln_trace("mln::clustering::kmean3d_a::print_distance");
399 
400  mln_eiter(t_distance_img) l(_distance);
401 
402  for_all(l)
403  {
404  mln_piter(t_distance_val) rgb(_distance[l.index_()].domain());
405 
406  for_all(rgb)
407  {
408  if (0 < _histo(rgb))
409  {
410  std::cout << "distance(l=" << l.index_();
411  std::cout << ",r=" << rgb.row();
412  std::cout << ", g=" << rgb.col();
413  std::cout << ", b=" << rgb.sli();
414  std::cout << ")= " << _distance[l.index_()](rgb);
415  std::cout << std::endl;
416  }
417  }
418  }
419 
420  }
421 
422  template <typename T, unsigned n>
423  inline
424  void kmean3d_a<T,n>::print_point()
425  {
426  mln_trace("mln::clustering::kmean3d_a::print_point");
427 
428  mln_piter(t_point_img) p(_point.domain());
429 
430  for_all(p)
431  {
432  std::cout << "point(r=" << p.row();
433  std::cout << ", c=" << p.col();
434  std::cout << ")= " << _point(p);
435  std::cout << std::endl;
436  }
437 
438  }
439 
440 
441 
442  template <typename T, unsigned n>
443  inline
444  void rgb_rand_init(t_mean_img mean)
445  {
446  typedef value::rgb<n> t_value;
447  typedef mln_trait_value_comp(t_value,0) t_value_comp0;
448  typedef mln_trait_value_comp(t_value,1) t_value_comp1;
449  typedef mln_trait_value_comp(t_value,2) t_value_comp2;
450  typedef algebra::vec<3,T> t_result3d;
451  typedef util::array<t_result3d> t_mean_img;
452 
453  t_value_comp0 min_comp0 = mln_min(t_value_comp0);
454  t_value_comp0 max_comp0 = mln_max(t_value_comp0);
455  t_value_comp1 min_comp1 = mln_min(t_value_comp1);
456  t_value_comp1 max_comp1 = mln_max(t_value_comp1);
457  t_value_comp2 min_comp2 = mln_min(t_value_comp2);
458  t_value_comp2 max_comp2 = mln_max(t_value_comp2);
459  mln_eiter(t_mean_img) l(mean);
460 
461  for_all(l)
462  {
463  mean[l.index_()][0] = (rand() % (max_comp0 - min_comp0)) + min_comp0;
464  mean[l.index_()][1] = (rand() % (max_comp1 - min_comp1)) + min_comp1;
465  mean[l.index_()][2] = (rand() % (max_comp2 - min_comp2)) + min_comp2;
466  }
467 
468  return mean;
469  }
470 
471  */
472 
473  } // end of namespace mln::clustering::internal
474 
475 
476  //--------------------------------------------------------------------------
477  // Impl.
478  //--------------------------------------------------------------------------
479 
480  namespace impl
481  {
482 
483  //------------------------------------------------------------------------
484  // kmean_image2d_rgb(const t_point_img& point,
485  // const unsigned k_center,
486  // const unsigned watch_dog = 10,
487  // const unsigned n_times = 10)
488  //------------------------------------------------------------------------
489 
490  template <unsigned n>
491  struct rgbn_to_lbl8 : Function_v2v< rgbn_to_lbl8<n> >
492  {
493  typedef value::rgb<n> argument;
494  typedef value::label_8 result;
495  typedef value::label_8 t_label;
496  typedef image3d<t_label> t_group_img;
497 
498  t_group_img _group;
499 
500  rgbn_to_lbl8(t_group_img group) : _group(group) {}
501 
502  result operator()(const argument& c) const
503  {
504  value::label_8 tmp = opt::at(_group, c.blue(), c.red(), c.green());
505 
506  // FIXME WHY DO WE NOT USE +1
507  return ++tmp;
508  }
509  };
510 
511  template <typename T, unsigned n>
512  struct rgb_to_dist : Function_v2v< rgb_to_dist<T,n> >
513  {
514  typedef value::rgb<n> argument;
515  typedef T result;
516  typedef T t_result1d;
517  typedef algebra::vec<3,T> t_result3d;
518  typedef image3d<unsigned> t_histo_img;
519 
520  t_result3d _mean;
521  t_histo_img _histo;
522 
523  rgb_to_dist(t_result3d mean, t_histo_img histo) : _mean(mean),
524  _histo(histo) {}
525 
526  result operator()(const argument& c) const
527  {
528  t_result1d diff2_row = math::sqr(c.row() - _mean[0]);
529  t_result1d diff2_col = math::sqr(c.col() - _mean[1]);
530  t_result1d diff2_sli = math::sqr(c.sli() - _mean[2]);
531  t_result1d tmp = _histo(c)*(diff2_row + diff2_col + diff2_sli);
532 
533  return tmp;
534  }
535  };
536 
537  template <typename T, unsigned n, typename I>
538  inline
539  mln_ch_value(I,value::label_8)
540  kmean_image2d_rgb(const Image<I>& point__,
541  const unsigned k_center,
542  const unsigned watch_dog = 10,
543  const unsigned n_times = 10)
544  {
545  mln_trace("mln::clustering::impl::kmean_image2d_rgb");
546 
547  const I& point = exact(point__);
548  typedef mln_value(I) V;
549  mlc_is(V, value::rgb<n>)::check();
550  mlc_bool(mln_site_(I)::dim == 2u)::check();
551  mln_precondition(point.is_valid());
552 
553  // BEGIN TYPEDEF
554  typedef value::rgb<8> t_rgb;
555  typedef value::label<8> t_label;
556  typedef value::rgb<n> t_value;
557  typedef mln_trait_value_comp(t_value,0) t_value_comp0;
558  typedef mln_trait_value_comp(t_value,1) t_value_comp1;
559  typedef mln_trait_value_comp(t_value,2) t_value_comp2;
560  typedef T t_result1d;
561  typedef algebra::vec<3,T> t_result3d;
562 
563  typedef I t_point_img;
564  typedef image3d<unsigned> t_histo_img;
565  typedef util::array<t_result1d> t_number_img;
566  typedef util::array<t_result3d> t_mean_img;
567  typedef util::array<t_result1d> t_variance_img;
568 
569  typedef image3d<t_label> t_group_img;
570  typedef image3d<t_result1d> t_distance_val;
571  typedef util::array<t_distance_val> t_distance_img;
572 
573  typedef mln_ch_value(I,t_label) t_label_dbg;
574  typedef image2d<t_rgb> t_color_dbg;
575  typedef image2d<t_value> t_mean_dbg;
576 
577  typedef image1d<t_result3d> t_mean_val;
578  typedef util::array<t_mean_val> t_mean_set;
579  typedef util::array<t_mean_set> t_mean_cnv;
580  typedef image1d<t_result1d> t_variance_val;
581  typedef util::array<t_variance_val> t_variance_cnv;
582  // END TYPEDEF
583 
584  // BEGIN INITIALISATION
585  mln_precondition(point.is_valid());
586 
587  static const unsigned _N_TRIES = 3;
588 
589  typedef accu::meta::stat::histo3d_rgb t_histo3d_rgb;
590 
591  t_result1d _within_variance;
592 
593  unsigned _k_center = k_center;
594  unsigned _watch_dog = watch_dog;
595  unsigned _n_times = n_times;
596  t_point_img _point = point;
597 
598  // HISTOGRAM INIT
599  t_histo_img _histo = data::compute(t_histo3d_rgb(),
600  _point);
601 
602  // CENTER STATS INIT
603  t_number_img _number;
604  t_mean_img _mean;
605  t_variance_img _variance;
606 
607  for (unsigned i = 0; i < _k_center; ++i)
608  {
609  _number.append(literal::zero);
610  _mean.append(literal::zero);
611  _variance.append(literal::zero);
612  }
613 
614 
615  unsigned _current_step = 0;
616  unsigned _current_launching = 0;
617  bool _is_number_valid = false;
618 
619  unsigned _launching_min;
620  t_result1d _variance_min;
621  t_mean_img _mean_min;
622 
623 
624 
625  t_group_img _group;
626  t_distance_img _distance;
627 
628 
629  t_label_dbg _label_dbg;
630  t_color_dbg _color_dbg;
631  t_mean_dbg _mean_dbg;
632 
633 
634  t_mean_cnv _mean_cnv;
635  t_variance_cnv _variance_cnv;
636 
637 
638 
639 
640  _group.init_(box3d(point3d(mln_min(t_value_comp2),
641  mln_min(t_value_comp0),
642  mln_min(t_value_comp1)),
643  point3d(mln_max(t_value_comp2),
644  mln_max(t_value_comp0),
645  mln_max(t_value_comp1))));
646 
647  for (unsigned i = 0; i < _k_center; ++i)
648  {
649  t_distance_val img(box3d(point3d(mln_min(t_value_comp2),
650  mln_min(t_value_comp0),
651  mln_min(t_value_comp1)),
652  point3d(mln_max(t_value_comp2),
653  mln_max(t_value_comp0),
654  mln_max(t_value_comp1))));
655 
656  _distance.append(img);
657  }
658 
659  // Debugging, calibrating and testing
660  initialize(_label_dbg, _point);
661  initialize(_color_dbg, _point);
662  initialize(_mean_dbg, _point);
663 
664  // Observing the convergence
665 
666  for (unsigned i = 0; i < _n_times; ++i)
667  {
668  t_variance_val img(box1d(point1d(0), point1d(_watch_dog-1)));
669 
671 
672  _variance_cnv.append(img);
673  }
674 
675  for (unsigned i = 0; i < _k_center; ++i)
676  {
677  t_mean_set mean_set;
678 
679  for (unsigned j = 0; j < _n_times; ++j)
680  {
681  t_mean_val img(box1d(point1d(0), point1d(_watch_dog-1)));
682 
684 
685  mean_set.append(img);
686  }
687 
688  _mean_cnv.append(mean_set);
689  }
690  // END INITIALISATION
691 
692  // BEGIN LOOP N TIMES
693  {
694  unsigned tries = 0;
695  _variance_min = mln_max(t_result1d);
696  _current_launching = 0;
697 
698  while (_current_launching < _n_times)
699  {
700  // BEGIN LAUNCH ONE TIME
701  {
702  t_result1d old_variance = mln_max(t_result1d);
703  _within_variance = mln_max(t_result1d);
704  _current_step = 0;
705 
706  // BEGIN INIT_MEAN
707  {
708  t_value_comp0 min_comp0 = mln_min(t_value_comp0);
709  t_value_comp0 max_comp0 = mln_max(t_value_comp0);
710  t_value_comp1 min_comp1 = mln_min(t_value_comp1);
711  t_value_comp1 max_comp1 = mln_max(t_value_comp1);
712  t_value_comp2 min_comp2 = mln_min(t_value_comp2);
713  t_value_comp2 max_comp2 = mln_max(t_value_comp2);
714  mln_eiter(t_mean_img) l(_mean);
715 
716  for_all(l)
717  {
718  _mean[l.index_()][0]=(rand()%(max_comp0-min_comp0))+min_comp0;
719  _mean[l.index_()][1]=(rand()%(max_comp1-min_comp1))+min_comp1;
720  _mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
721  }
722  }
723  // END INIT MEAN
724 
725 
726  // UPDATE DISTANCE
727 
728  for (unsigned i = 0; i < _k_center; ++i)
729  {
730 
731  // _distance[i] = data::transform(_histo,
732  // rgb_to_dist<T,n>(_mean[i],
733  // _histo));
734 
735  mln_piter(t_distance_val) d(_distance[i].domain());
736 
737  for_all(d)
738  {
739  t_result1d diff2_row = math::sqr(d.row() - _mean[i][0]);
740  t_result1d diff2_col = math::sqr(d.col() - _mean[i][1]);
741  t_result1d diff2_sli = math::sqr(d.sli() - _mean[i][2]);
742  _distance[i](d) = _histo(d)*
743  (diff2_row + diff2_col + diff2_sli);
744  }
745  }
746 
747  // END UPDATE DISTANCE
748 
749  do
750  {
751  old_variance = _within_variance;
752 
753  // BEGIN UPDATE GROUP
754  {
755  mln_piter(t_group_img) rgb(_group.domain());
756 
757  for_all(rgb)
758  {
759  mln_eiter(t_distance_img) l(_distance);
760  t_result1d min = mln_max(t_result1d);
761  t_label label = mln_max(t_label);
762 
763  for_all(l)
764  {
765  if (min > _distance[l.index_()](rgb))
766  {
767  min = _distance[l.index_()](rgb);
768  label = l.index_();
769  }
770  }
771 
772  _group(rgb) = label;
773  }
774 
775  }
776  // END UPDATE GROUP
777 
778  // BEGIN UPDATE MEAN
779  {
780  mln_eiter(t_number_img) en(_number);
781  mln_eiter(t_mean_img) em(_mean);
782 
783  for_all_2(en,em)
784  {
785  _number[en.index_()] = literal::zero;
786  _mean[em.index_()] = literal::zero;
787  }
788 
789  mln_piter(t_group_img) rgb(_group.domain());
790 
791  for_all(rgb)
792  {
793  _mean[_group(rgb)][0] += rgb.row() * _histo(rgb);
794  _mean[_group(rgb)][1] += rgb.col() * _histo(rgb);
795  _mean[_group(rgb)][2] += rgb.sli() * _histo(rgb);
796  _number(_group(rgb)) += _histo(rgb);
797  }
798 
799  mln_eiter(t_mean_img) l(_mean);
800 
801  for_all(l)
802  {
803  _is_number_valid = (0 != _number[l.index_()]);
804 
805  if (!_is_number_valid)
806  break;
807 
808  _mean[l.index_()] /= _number[l.index_()];
809  }
810  }
811  // END UPDATE MEAN
812 
813 
814  // Stopping Nan propagation
815  if (!_is_number_valid)
816  break;
817 
818  // UPDATE DISTANCE
819 
820  for (unsigned i = 0; i < _k_center; ++i)
821  {
822  mln_piter(t_distance_val) d(_distance[i].domain());
823 
824  for_all(d)
825  {
826  // the square distance
827  t_result1d diff2_row = math::sqr(d.row() - _mean[i][0]);
828  t_result1d diff2_col = math::sqr(d.col() - _mean[i][1]);
829  t_result1d diff2_sli = math::sqr(d.sli() - _mean[i][2]);
830  _distance[i](d) = _histo(d)*
831  (diff2_row + diff2_col + diff2_sli);
832  }
833  }
834  // END UPDATE DISTANCE
835 
836  // BEGIN UPDATE VARIANCE
837  {
838  _within_variance = literal::zero;
839  mln_eiter(t_variance_img) l(_variance);
840 
841  for_all(l)
842  {
843  _variance[l.index_()] = literal::zero;
844 
845  mln_piter(t_group_img) rgb(_group.domain());
846 
847  for_all(rgb)
848  {
849  if (l.index_() == _group(rgb))
850  _variance[l.index_()] += _distance[l.index_()](rgb);
851  }
852 
853  _within_variance += _variance[l.index_()];
854  }
855 
856  }
857  // END UPDATE VARIANCE
858 
859  //update_cnv();
860 
861  ++_current_step;
862  }
863  while (_current_step < _watch_dog &&
864  _within_variance < old_variance);
865 
866  //finalize_cnv();
867  //build_all_dbg();
868  }
869  // END LAUNCH ONE TIME
870 
871  if ((_is_number_valid && (_current_step < _watch_dog))||
872  _N_TRIES < tries)
873  {
874  if (_within_variance < _variance_min)
875  {
876  _variance_min = _within_variance;
877  _mean_min = _mean;
878  _launching_min = _current_launching;
879  }
880 
881  // Reinitialize the number of echecs possible
882  tries = 0;
883 
884  //std::cout << "_current_launching : " << _current_launching
885  // << std::endl;
886 
887  //std::cout << "within_variance[" << _current_launching << "] = "
888  // << _within_variance << std::endl;
889 
890  ++_current_launching;
891  }
892  else
893  ++tries;
894  }
895 
896  //Debugging code
897  //build_all_dbg();
898 
899  }
900  // END LOOP N TIMES
901 
902  // BEGIN BUILD LABEL IMAGE
903  _label_dbg = data::transform(_point, rgbn_to_lbl8<n>(_group));
904 
905 // {
906 // mln_piter(t_point_img) pi(_point.domain());
907 // mln_piter(t_label_dbg) po(_label_dbg.domain());
908 
909 // for_all_2(pi, po)
910 // {
911 // t_value val = _point(pi);
912 // t_label grp = _group(point3d(val.blue(),val.red(),val.green()));
913 
914 // _label_dbg(po) = ++grp;
915 // }
916 // }
917 
918  // END BUILD LABEL IMAGE
919 
920  return _label_dbg;
921 
922  }
923 
924  } // end of namespace mln::clustering::impl
925 
926 
927 
928 
929 
930  //--------------------------------------------------------------------------
931  // Internal.
932  //--------------------------------------------------------------------------
933 
934  namespace internal
935  {
936 
937  template <typename T, unsigned n, typename I>
938  inline
939  mln_ch_value(I,value::label_8)
940  kmean_rgb_dispatch(const Image<I>& img,
941  const unsigned k_center,
942  const unsigned watch_dog,
943  const unsigned n_times,
944  const value::rgb<n>& /* v */,
945  const point2d& /* p */)
946  {
947  return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
948  }
949 
950  template <typename T, unsigned n, typename I, typename V, typename P>
951  inline
952  mln_ch_value(I,value::label_8)
953  kmean_rgb_dispatch(const Image<I>& /* img */,
954  const unsigned /* k_center */,
955  const unsigned /* watch_dog */,
956  const unsigned /* n_times */,
957  const V& /* v */,
958  const P& /* p */)
959  {
960  // No kmean implementation found.
961  mlc_abort(I)::check();
962 
963  typedef mln_ch_value(I, value::label_8) output_t;
964  return output_t();
965  }
966 
967 
968  template <typename T, unsigned n, typename I>
969  inline
970  mln_ch_value(I,value::label_8)
971  kmean_rgb_dispatch(const Image<I>& img,
972  const unsigned k_center,
973  const unsigned watch_dog,
974  const unsigned n_times)
975  {
976  typedef mln_value(I) V;
977  typedef mln_site(I) P;
978  return kmean_rgb_dispatch<T,n>(img, k_center, watch_dog,
979  n_times, V(), P());
980  }
981 
982 
983  } // end of namespace mln::clustering::internal
984 
985 
986  //--------------------------------------------------------------------------
987  // Facade.
988  //--------------------------------------------------------------------------
989 
990  template <typename T, unsigned n, typename I>
991  inline
992  mln_ch_value(I,value::label_8)
993  kmean_rgb(const Image<I>& point,
994  const unsigned k_center,
995  const unsigned watch_dog,
996  const unsigned n_times)
997  {
998  mln_trace("mln::clustering::kmean_rgb");
999 
1000  mln_ch_value(I, value::label_8)
1001  output = internal::kmean_rgb_dispatch<T,n>(point, k_center,
1002  watch_dog, n_times);
1003 
1004  return output;
1005  }
1006 
1007 
1008 # endif // ! MLN_INCLUDE_ONLY
1009 
1010  } // end of namespace mln::clustering
1011 
1012 } // end of namespace mln
1013 
1014 #endif // ! MLN_CLUSTERING_KMEAN_RGB_HH