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