* green/mln/clustering/kmean_rgb.hh: New library source code.
* green/demo/clustering/kmean_rgb/Makefile: New Makefile.
* green/demo/clustering/kmean_rgb/kmean_rgb.cc: New demo. code.
---
milena/sandbox/ChangeLog | 8 +
.../histo2d => clustering/kmean_rgb}/Makefile.am | 0
.../green/demo/clustering/kmean_rgb/kmean_rgb.cc | 91 ++
milena/sandbox/green/mln/clustering/kmean_rgb.hh | 973 ++++++++++++++++++++
4 files changed, 1072 insertions(+), 0 deletions(-)
copy milena/sandbox/green/demo/{accu/stat/histo2d => clustering/kmean_rgb}/Makefile.am
(100%)
create mode 100644 milena/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
create mode 100644 milena/sandbox/green/mln/clustering/kmean_rgb.hh
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index a2cc751..b3029e2 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,5 +1,13 @@
2009-12-02 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+ Transform kmean object in a big function and then a canvas.
+
+ * green/mln/clustering/kmean_rgb.hh: New library source code.
+ * green/demo/clustering/kmean_rgb/Makefile: New Makefile.
+ * green/demo/clustering/kmean_rgb/kmean_rgb.cc: New demo. code.
+
+2009-12-02 Yann Jacquelet <jacquelet(a)lrde.epita.fr>
+
Benchmark on distance, preliminary work before optimizing kmean.
* green/bench/transform/distance/Makefile: New Makefile.
diff --git a/milena/sandbox/green/demo/accu/stat/histo2d/Makefile.am
b/milena/sandbox/green/demo/clustering/kmean_rgb/Makefile.am
similarity index 100%
copy from milena/sandbox/green/demo/accu/stat/histo2d/Makefile.am
copy to milena/sandbox/green/demo/clustering/kmean_rgb/Makefile.am
diff --git a/milena/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
b/milena/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
new file mode 100644
index 0000000..36641b6
--- /dev/null
+++ b/milena/sandbox/green/demo/clustering/kmean_rgb/kmean_rgb.cc
@@ -0,0 +1,91 @@
+// DEMO ON KMEAN_RGB
+
+#include <mln/clustering/kmean_rgb.hh>
+
+#include <iostream>
+#include <sstream>
+
+#include <mln/img_path.hh>
+
+#include <mln/core/macros.hh>
+#include <mln/core/image/image2d.hh>
+//#include <mln/core/image/dmorph/image_if.hh>
+
+#include <mln/data/transform.hh>
+#include <mln/fun/v2v/rgb8_to_rgbn.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/io/plot/save_image_sh.hh>
+
+//#include <mln/pw/value.hh>
+
+//#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+
+int main()
+{
+ const std::string& image = OLENA_IMG_PATH"/house.ppm";
+ const unsigned k_center = 3;
+ const unsigned n_times = 10;
+ const unsigned watch_dog = 10;
+
+ typedef mln::value::label_8 t_lbl8;
+ typedef mln::value::rgb8 t_rgb8;
+ typedef mln::value::rgb<5> t_rgb5;
+ typedef mln::image2d<t_rgb8> t_image2d_rgb8;
+ typedef mln::image2d<t_rgb5> t_image2d_rgb5;
+ typedef mln::image2d<t_lbl8> t_image2d_lbl8;
+ typedef mln::fun::v2v::rgb8_to_rgbn<5> t_rgb8_to_rgb5;
+
+ t_image2d_rgb8 house_rgb8;
+ t_image2d_rgb5 house_rgb5;
+ t_image2d_lbl8 house_lbl8;
+
+ mln::io::ppm::load(house_rgb8, image.c_str());
+ house_rgb5 = mln::data::transform(house_rgb8, t_rgb8_to_rgb5());
+
+ mln::trace::quiet = false;
+
+ house_lbl8 = mln::clustering::kmean_rgb<double,5>(house_rgb5,
+ k_center,
+ watch_dog,
+ n_times);
+ mln::trace::quiet = true;
+
+ mln::io::pgm::save(house_lbl8, "label.pgm");
+ /*
+
+
+
+ t_kmean kmean(house_rgb5, k_center, watch_dog, n_times);
+
+
+
+ //kmean.launch_one_time();
+ 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();
+ t_kmean::t_variance_cnv variance_cnv = kmean.get_variance_cnv();
+ t_kmean::t_mean_cnv mean_cnv = kmean.get_mean_cnv();
+
+ mln::io::ppm::save(mean_img, "mean.ppm");
+ mln::io::ppm::save(color_img, "color.ppm");
+ mln::io::pgm::save(label_img, "label.pgm");
+
+ mln::io::plot::save_image_sh(mean_img, "mean.sh");
+ mln::io::plot::save_image_sh(mean_cnv, "mean_cnv.sh");
+ mln::io::plot::save_image_sh(variance_cnv, "variance_cnv.sh");
+
+ */
+
+ return 0;
+}
+
diff --git a/milena/sandbox/green/mln/clustering/kmean_rgb.hh
b/milena/sandbox/green/mln/clustering/kmean_rgb.hh
new file mode 100644
index 0000000..253745b
--- /dev/null
+++ b/milena/sandbox/green/mln/clustering/kmean_rgb.hh
@@ -0,0 +1,973 @@
+// 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_CLUSTERING_KMEAN_RGB_HH
+# define MLN_CLUSTERING_KMEAN_RGB_HH
+
+/// \file
+///
+/// \brief Implements the optimized kmean algorithm.
+///
+/// This algorithm is optimized in the way it proceeds directly with
+/// the rgb values inspite of the pixel attribute. The
+/// algorithm is independant from the image dimension. But, we have to
+/// compute one time the histogram. In fact, we move a recurrent cost
+/// to a fix cost in the complexity. This version is adapted to
+/// image with small quantification.
+
+/// APLATISSEMENT DES KMEAN3D
+
+# include <limits.h>
+# include <iostream>
+
+# include <mln/accu/stat/histo3d_rgb.hh>
+
+# include <mln/algebra/vec.hh>
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/contract.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/macros.hh>
+
+# include <mln/data/compute.hh>
+# include <mln/data/fill.hh>
+# include <mln/data/transform.hh>
+
+# include <mln/debug/println.hh>
+
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/labeling/colorize.hh>
+# include <mln/labeling/mean_values.hh>
+
+# include <mln/literal/zero.hh>
+# include <mln/literal/one.hh>
+
+# include <mln/math/min.hh>
+# include <mln/math/sqr.hh>
+
+# include <mln/norm/l2.hh>
+
+# include <mln/opt/at.hh>
+
+# include <mln/trace/entering.hh>
+# include <mln/trace/exiting.hh>
+
+# include <mln/trait/value_.hh>
+
+# include <mln/util/array.hh>
+
+# include <mln/value/int_u.hh>
+# include <mln/value/rgb8.hh>
+# include <mln/value/label_8.hh>
+
+
+//--------------------------------------------------------------------------
+// CODE APLATI
+//--------------------------------------------------------------------------
+
+
+namespace mln
+{
+
+ namespace clustering
+ {
+
+ template <typename T, unsigned n, typename I>
+ inline
+ image2d<value::label_8>
+ kmean_rgb(const Image<I>& point,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times);
+
+ } // end of namespace mln::clustering
+
+ namespace clustering
+ {
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ //--------------------------------------------------------------------------
+ // Internal.
+ //--------------------------------------------------------------------------
+
+ namespace internal
+ {
+
+ //------------------------------------------------------------------------
+ // Debugging tools
+ //------------------------------------------------------------------------
+
+ /*
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::build_label_dbg()
+ {
+ trace::entering("mln::clustering::kmean3d_a::build_label_dbg");
+
+ 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(point3d(val.blue(), val.red(), val.green()));
+
+ // As label zero has got a particular semantic, the first label is one
+ _label_dbg(po) = ++grp;
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::build_label_dbg");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::build_mean_dbg()
+ {
+ trace::entering("mln::clustering::kmean3d_a::build_mean_dbg");
+
+ mln_piter(t_mean_dbg) p(_mean_dbg.domain());
+
+ for_all(p)
+ {
+ _mean_dbg(p).red() = static_cast<unsigned>(_mean[_label_dbg(p)][0]);
+ _mean_dbg(p).green() = static_cast<unsigned>(_mean[_label_dbg(p)][1]);
+ _mean_dbg(p).blue() = static_cast<unsigned>(_mean[_label_dbg(p)][2]);
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::build_mean_dbg");
+ }
+
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::build_all_dbg()
+ {
+ trace::entering("mln::clustering::kmean3d_a::build_all_dbg");
+ build_label_dbg();
+ //build_mean_dbg();
+ _mean_dbg = labeling::mean_values(_point, _label_dbg, _k_center);
+ _color_dbg = labeling::colorize(value::rgb8(), _label_dbg);
+
+ trace::exiting("mln::clustering::kmean3d_a::build_all_dbg");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::update_cnv()
+ {
+ trace::entering("mln::clustering::kmean3d_a::update_cnv");
+
+ _variance_cnv[_current_launching](point1d(_current_step))
+ = _within_variance;
+
+ mln_eiter(t_mean_img) l(_mean);
+
+ for_all(l)
+ {
+ _mean_cnv[l.index_()][_current_launching](point1d(_current_step))
+ = _mean[l.index_()];
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::update_cnv");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::finalize_cnv()
+ {
+ trace::entering("mln::clustering::kmean3d_a::finalize_cnv");
+
+ // saturate the curv with the within variance
+ for (unsigned i = _current_step; i < _watch_dog; ++i)
+ _variance_cnv[_current_launching](point1d(i)) = _within_variance;
+
+ for (unsigned i = _current_step; i < _watch_dog; ++i)
+ {
+ mln_eiter(t_mean_img) l(_mean);
+
+ for_all(l)
+ {
+ _mean_cnv[l.index_()][_current_launching](point1d(i))
+ = _mean[l.index_()];
+ }
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::finalize_cnv");
+ }
+
+
+
+
+ //--------------------------------------------------------------------------
+ // Printing temporary results
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_mean()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_mean");
+
+ mln_eiter(t_mean_img) l(_mean);
+
+ for_all(l)
+ {
+ std::cout << "mean(" << l.index_();
+ std::cout << ") = [r=" << _mean[l.index_()][0];
+ std::cout << ", g=" << _mean[l.index_()][1];
+ std::cout << ", b=" << _mean[l.index_()][2];
+ std::cout << "]" << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_mean");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_number()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_number");
+
+ mln_eiter(t_number_img) l(_number);
+
+ for_all(l)
+ {
+ std::cout << "number(" << l.index_();
+ std::cout << ") = " << _number[l.index_()];
+ std::cout << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_number");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_variance()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_variance");
+
+ mln_eiter(t_variance_img) l(_number);
+
+ for_all(l)
+ {
+ std::cout << "variance(" << l.index_();
+ std::cout << ") = " << _variance[l.index_()];
+ std::cout << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_variance");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_histo()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_histo");
+
+ mln_piter(t_histo_img) rgb(_histo.domain());
+
+ for_all(rgb)
+ {
+ if (0 < _histo(rgb))
+ {
+ std::cout << "histo(r=" << rgb.row();
+ std::cout << ", g=" << rgb.col();
+ std::cout << ", b=" << rgb.sli();
+ std::cout << ")= " << _histo(rgb);
+ std::cout << std::endl;
+ }
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_histo");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_group()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_group");
+
+ mln_piter(t_group_img) rgb(_group.domain());
+
+ for_all(rgb)
+ {
+ if (0 < _histo(rgb))
+ {
+ std::cout << "group(r=" << rgb.row();
+ std::cout << ", g=" << rgb.col();
+ std::cout << ", b=" << rgb.sli();
+ std::cout << ")= " << _group(rgb);
+ std::cout << std::endl;
+ }
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_group");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_distance()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_distance");
+
+ mln_eiter(t_distance_img) l(_distance);
+
+ for_all(l)
+ {
+ mln_piter(t_distance_val) rgb(_distance[l.index_()].domain());
+
+ for_all(rgb)
+ {
+ if (0 < _histo(rgb))
+ {
+ std::cout << "distance(l=" << l.index_();
+ std::cout << ",r=" << rgb.row();
+ std::cout << ", g=" << rgb.col();
+ std::cout << ", b=" << rgb.sli();
+ std::cout << ")= " << _distance[l.index_()](rgb);
+ std::cout << std::endl;
+ }
+ }
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_distance");
+ }
+
+ template <typename T, unsigned n>
+ inline
+ void kmean3d_a<T,n>::print_point()
+ {
+ trace::entering("mln::clustering::kmean3d_a::print_point");
+
+ mln_piter(t_point_img) p(_point.domain());
+
+ for_all(p)
+ {
+ std::cout << "point(r=" << p.row();
+ std::cout << ", c=" << p.col();
+ std::cout << ")= " << _point(p);
+ std::cout << std::endl;
+ }
+
+ trace::exiting("mln::clustering::kmean3d_a::print_point");
+ }
+
+
+
+ template <typename T, unsigned n>
+ inline
+ void rgb_rand_init(t_mean_img mean)
+ {
+ typedef value::rgb<n> t_value;
+ typedef mln_trait_value_comp(t_value,0) t_value_comp0;
+ typedef mln_trait_value_comp(t_value,1) t_value_comp1;
+ typedef mln_trait_value_comp(t_value,2) t_value_comp2;
+ typedef algebra::vec<3,T> t_result3d;
+ typedef util::array<t_result3d> t_mean_img;
+
+ t_value_comp0 min_comp0 = mln_min(t_value_comp0);
+ t_value_comp0 max_comp0 = mln_max(t_value_comp0);
+ t_value_comp1 min_comp1 = mln_min(t_value_comp1);
+ t_value_comp1 max_comp1 = mln_max(t_value_comp1);
+ t_value_comp2 min_comp2 = mln_min(t_value_comp2);
+ t_value_comp2 max_comp2 = mln_max(t_value_comp2);
+ mln_eiter(t_mean_img) l(mean);
+
+ for_all(l)
+ {
+ mean[l.index_()][0] = (rand() % (max_comp0 - min_comp0)) + min_comp0;
+ mean[l.index_()][1] = (rand() % (max_comp1 - min_comp1)) + min_comp1;
+ mean[l.index_()][2] = (rand() % (max_comp2 - min_comp2)) + min_comp2;
+ }
+
+ return mean;
+ }
+
+ */
+
+ } // end of namespace mln::clustering::internal
+
+
+ //--------------------------------------------------------------------------
+ // Impl.
+ //--------------------------------------------------------------------------
+
+ namespace impl
+ {
+
+ //------------------------------------------------------------------------
+ // kmean_image2d_rgb(const t_point_img& point,
+ // const unsigned k_center,
+ // const unsigned watch_dog = 10,
+ // const unsigned n_times = 10)
+ //------------------------------------------------------------------------
+
+ template <unsigned n>
+ struct rgbn_to_lbl8 : Function_v2v< rgbn_to_lbl8<n> >
+ {
+ typedef value::rgb<n> argument;
+ typedef value::label_8 result;
+ typedef value::label_8 t_label;
+ typedef image3d<t_label> t_group_img;
+
+ t_group_img _group;
+
+ rgbn_to_lbl8(t_group_img group) : _group(group) {}
+
+ result operator()(const argument& c) const
+ {
+ value::label_8 tmp = opt::at(_group, c.blue(), c.red(), c.green());
+
+ // FIXME WHY DO WE NOT USE +1
+ return ++tmp;
+ }
+ };
+
+ template <typename T, unsigned n>
+ struct rgb_to_dist : Function_v2v< rgb_to_dist<T,n> >
+ {
+ typedef value::rgb<n> argument;
+ typedef T result;
+ typedef T t_result1d;
+ typedef algebra::vec<3,T> t_result3d;
+ typedef image3d<unsigned> t_histo_img;
+
+ t_result3d _mean;
+ t_histo_img _histo;
+
+ rgb_to_dist(t_result3d mean, t_histo_img histo) : _mean(mean),
+ _histo(histo) {}
+
+ result operator()(const argument& c) const
+ {
+ t_result1d diff2_row = math::sqr(c.row() - _mean[0]);
+ t_result1d diff2_col = math::sqr(c.col() - _mean[1]);
+ t_result1d diff2_sli = math::sqr(c.sli() - _mean[2]);
+ t_result1d tmp = _histo(c)*(diff2_row + diff2_col + diff2_sli);
+
+ return tmp;
+ }
+ };
+
+ template <typename T, unsigned n>
+ inline
+ image2d<value::label_8>
+ kmean_image2d_rgb(const image2d< value::rgb<n> >& point,
+ const unsigned k_center,
+ const unsigned watch_dog = 10,
+ const unsigned n_times = 10)
+ {
+ trace::entering("mln::clustering::impl::kmean_image2d_rgb");
+ trace::quiet = true;
+ // BEGIN TYPEDEF
+ typedef value::rgb<8> t_rgb;
+ typedef value::label<8> t_label;
+ typedef value::rgb<n> t_value;
+ typedef mln_trait_value_comp(t_value,0) t_value_comp0;
+ typedef mln_trait_value_comp(t_value,1) t_value_comp1;
+ typedef mln_trait_value_comp(t_value,2) t_value_comp2;
+ typedef T t_result1d;
+ typedef algebra::vec<3,T> t_result3d;
+
+ typedef image2d<t_value> t_point_img;
+ typedef image3d<unsigned> t_histo_img;
+ typedef util::array<t_result1d> t_number_img;
+ typedef util::array<t_result3d> t_mean_img;
+ typedef util::array<t_result1d> t_variance_img;
+
+ typedef image3d<t_label> t_group_img;
+ typedef image3d<t_result1d> t_distance_val;
+ typedef util::array<t_distance_val> 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 image1d<t_result3d> t_mean_val;
+ typedef util::array<t_mean_val> t_mean_set;
+ typedef util::array<t_mean_set> t_mean_cnv;
+ typedef image1d<t_result1d> t_variance_val;
+ typedef util::array<t_variance_val> t_variance_cnv;
+ // END TYPEDEF
+
+ // BEGIN INITIALISATION
+ mln_precondition(point.is_valid());
+
+ static const unsigned _N_TRIES = 3;
+
+ typedef accu::meta::stat::histo3d_rgb t_histo3d_rgb;
+
+ t_result1d _within_variance;
+
+ unsigned _k_center = k_center;
+ unsigned _watch_dog = watch_dog;
+ unsigned _n_times = n_times;
+ t_point_img _point = point;
+
+ // HISTOGRAM INIT
+ t_histo_img _histo = data::compute(t_histo3d_rgb(),
+ _point);
+
+ // CENTER STATS INIT
+ t_number_img _number;
+ t_mean_img _mean;
+ t_variance_img _variance;
+
+ for (unsigned i = 0; i < _k_center; ++i)
+ {
+ _number.append(literal::zero);
+ _mean.append(literal::zero);
+ _variance.append(literal::zero);
+ }
+
+
+ unsigned _current_step = 0;
+ unsigned _current_launching = 0;
+ bool _is_number_valid = false;
+
+ unsigned _launching_min;
+ t_result1d _variance_min;
+ t_mean_img _mean_min;
+
+
+
+ t_group_img _group;
+ t_distance_img _distance;
+
+
+ t_label_dbg _label_dbg;
+ t_color_dbg _color_dbg;
+ t_mean_dbg _mean_dbg;
+
+
+ t_mean_cnv _mean_cnv;
+ t_variance_cnv _variance_cnv;
+
+
+
+
+ _group.init_(box3d(point3d(mln_min(t_value_comp2),
+ mln_min(t_value_comp0),
+ mln_min(t_value_comp1)),
+ point3d(mln_max(t_value_comp2),
+ mln_max(t_value_comp0),
+ mln_max(t_value_comp1))));
+
+ for (unsigned i = 0; i < _k_center; ++i)
+ {
+ t_distance_val img(box3d(point3d(mln_min(t_value_comp2),
+ mln_min(t_value_comp0),
+ mln_min(t_value_comp1)),
+ point3d(mln_max(t_value_comp2),
+ mln_max(t_value_comp0),
+ mln_max(t_value_comp1))));
+
+ _distance.append(img);
+ }
+
+ // Debugging, calibrating and testing
+ initialize(_label_dbg, _point);
+ initialize(_color_dbg, _point);
+ initialize(_mean_dbg, _point);
+
+ // Observing the convergence
+
+ for (unsigned i = 0; i < _n_times; ++i)
+ {
+ t_variance_val img(box1d(point1d(0), point1d(_watch_dog-1)));
+
+ data::fill(img, literal::zero);
+
+ _variance_cnv.append(img);
+ }
+
+ for (unsigned i = 0; i < _k_center; ++i)
+ {
+ t_mean_set mean_set;
+
+ for (unsigned j = 0; j < _n_times; ++j)
+ {
+ t_mean_val img(box1d(point1d(0), point1d(_watch_dog-1)));
+
+ data::fill(img, literal::zero);
+
+ mean_set.append(img);
+ }
+
+ _mean_cnv.append(mean_set);
+ }
+ // END INITIALISATION
+
+ // BEGIN LOOP N TIMES
+ {
+ unsigned tries = 0;
+ _variance_min = mln_max(t_result1d);
+ _current_launching = 0;
+
+ while (_current_launching < _n_times)
+ {
+ // BEGIN LAUNCH ONE TIME
+ trace::quiet = false;
+ trace::entering("Launch one time");
+ trace::quiet = true;
+ {
+ t_result1d old_variance = mln_max(t_result1d);
+ _within_variance = mln_max(t_result1d);
+ _current_step = 0;
+
+ // BEGIN INIT_MEAN
+ trace::quiet = false;
+ trace::entering("init mean");
+ trace::quiet = true;
+ {
+ t_value_comp0 min_comp0 = mln_min(t_value_comp0);
+ t_value_comp0 max_comp0 = mln_max(t_value_comp0);
+ t_value_comp1 min_comp1 = mln_min(t_value_comp1);
+ t_value_comp1 max_comp1 = mln_max(t_value_comp1);
+ t_value_comp2 min_comp2 = mln_min(t_value_comp2);
+ t_value_comp2 max_comp2 = mln_max(t_value_comp2);
+ mln_eiter(t_mean_img) l(_mean);
+
+ for_all(l)
+ {
+ _mean[l.index_()][0]=(rand()%(max_comp0-min_comp0))+min_comp0;
+ _mean[l.index_()][1]=(rand()%(max_comp1-min_comp1))+min_comp1;
+ _mean[l.index_()][2]=(rand()%(max_comp2-min_comp2))+min_comp2;
+ }
+ }
+ trace::quiet = false;
+ trace::exiting("init mean");
+ trace::quiet = true;
+ // END INIT MEAN
+
+
+ // UPDATE DISTANCE
+ trace::quiet = false;
+ trace::entering("update distance");
+ trace::quiet = true;
+
+ for (unsigned i = 0; i < _k_center; ++i)
+ {
+
+ // _distance[i] = data::transform(_histo,
+ // rgb_to_dist<T,n>(_mean[i],
+ // _histo));
+
+ mln_piter(t_distance_val) d(_distance[i].domain());
+
+ for_all(d)
+ {
+ t_result1d diff2_row = math::sqr(d.row() - _mean[i][0]);
+ t_result1d diff2_col = math::sqr(d.col() - _mean[i][1]);
+ t_result1d diff2_sli = math::sqr(d.sli() - _mean[i][2]);
+ _distance[i](d) = _histo(d)*
+ (diff2_row + diff2_col + diff2_sli);
+ }
+ }
+
+ trace::quiet = false;
+ trace::exiting("update distance");
+ trace::quiet = true;
+ // END UPDATE DISTANCE
+
+ do
+ {
+ old_variance = _within_variance;
+
+ // BEGIN UPDATE GROUP
+ trace::quiet = false;
+ trace::entering("update group");
+ trace::quiet = true;
+ {
+ mln_piter(t_group_img) rgb(_group.domain());
+
+ for_all(rgb)
+ {
+ mln_eiter(t_distance_img) l(_distance);
+ t_result1d min = mln_max(t_result1d);
+ t_label label = mln_max(t_label);
+
+ for_all(l)
+ {
+ if (min > _distance[l.index_()](rgb))
+ {
+ min = _distance[l.index_()](rgb);
+ label = l.index_();
+ }
+ }
+
+ _group(rgb) = label;
+ }
+
+ }
+ trace::quiet = false;
+ trace::exiting("update group");
+ trace::quiet = true;
+ // END UPDATE GROUP
+
+ // BEGIN UPDATE MEAN
+ trace::quiet = false;
+ trace::entering("update mean");
+ trace::quiet = true;
+ {
+ mln_eiter(t_number_img) en(_number);
+ mln_eiter(t_mean_img) em(_mean);
+
+ for_all_2(en,em)
+ {
+ _number[en.index_()] = literal::zero;
+ _mean[em.index_()] = literal::zero;
+ }
+
+ mln_piter(t_group_img) rgb(_group.domain());
+
+ for_all(rgb)
+ {
+ _mean[_group(rgb)][0] += rgb.row() * _histo(rgb);
+ _mean[_group(rgb)][1] += rgb.col() * _histo(rgb);
+ _mean[_group(rgb)][2] += rgb.sli() * _histo(rgb);
+ _number(_group(rgb)) += _histo(rgb);
+ }
+
+ mln_eiter(t_mean_img) l(_mean);
+
+ for_all(l)
+ {
+ _is_number_valid = (0 != _number[l.index_()]);
+
+ if (!_is_number_valid)
+ break;
+
+ _mean[l.index_()] /= _number[l.index_()];
+ }
+ }
+ trace::quiet = false;
+ trace::exiting("update mean");
+ trace::quiet = true;
+ // END UPDATE MEAN
+
+
+ // Stopping Nan propagation
+ if (!_is_number_valid)
+ break;
+
+ // UPDATE DISTANCE
+ trace::quiet = false;
+ trace::entering("update distance");
+ trace::quiet = true;
+
+ for (unsigned i = 0; i < _k_center; ++i)
+ {
+ mln_piter(t_distance_val) d(_distance[i].domain());
+
+ for_all(d)
+ {
+ // the square distance
+ t_result1d diff2_row = math::sqr(d.row() - _mean[i][0]);
+ t_result1d diff2_col = math::sqr(d.col() - _mean[i][1]);
+ t_result1d diff2_sli = math::sqr(d.sli() - _mean[i][2]);
+ _distance[i](d) = _histo(d)*
+ (diff2_row + diff2_col + diff2_sli);
+ }
+ }
+ trace::quiet = false;
+ trace::exiting("update distance");
+ trace::quiet = true;
+ // END UPDATE DISTANCE
+
+ // BEGIN UPDATE VARIANCE
+ trace::quiet = false;
+ trace::entering("update variance");
+ trace::quiet = true;
+ {
+ _within_variance = literal::zero;
+ mln_eiter(t_variance_img) l(_variance);
+
+ for_all(l)
+ {
+ _variance[l.index_()] = literal::zero;
+
+ mln_piter(t_group_img) rgb(_group.domain());
+
+ for_all(rgb)
+ {
+ if (l.index_() == _group(rgb))
+ _variance[l.index_()] += _distance[l.index_()](rgb);
+ }
+
+ _within_variance += _variance[l.index_()];
+ }
+
+ }
+ trace::quiet = false;
+ trace::exiting("update variance");
+ trace::quiet = true;
+ // END UPDATE VARIANCE
+
+ //update_cnv();
+
+ ++_current_step;
+ }
+ while (_current_step < _watch_dog &&
+ _within_variance < old_variance);
+
+ //finalize_cnv();
+ //build_all_dbg();
+ }
+ trace::quiet = false;
+ trace::exiting("Launch one time");
+ trace::quiet = true;
+ // END LAUNCH ONE TIME
+
+ if ((_is_number_valid && (_current_step < _watch_dog))||
+ _N_TRIES < tries)
+ {
+ if (_within_variance < _variance_min)
+ {
+ _variance_min = _within_variance;
+ _mean_min = _mean;
+ _launching_min = _current_launching;
+ }
+
+ // Reinitialize the number of echecs possible
+ tries = 0;
+
+ //std::cout << "_current_launching : " <<
_current_launching
+ // << std::endl;
+
+ //std::cout << "within_variance[" << _current_launching
<< "] = "
+ // << _within_variance << std::endl;
+
+ ++_current_launching;
+ }
+ else
+ ++tries;
+ }
+
+ //Debugging code
+ //build_all_dbg();
+
+ }
+ // END LOOP N TIMES
+
+ // BEGIN BUILD LABEL IMAGE
+ _label_dbg = data::transform(_point, rgbn_to_lbl8<n>(_group));
+
+// {
+// 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(point3d(val.blue(),val.red(),val.green()));
+
+// _label_dbg(po) = ++grp;
+// }
+// }
+
+ // END BUILD LABEL IMAGE
+ trace::quiet = false;
+ trace::exiting("mln::clustering::impl::kmean_image2d_rgb");
+
+ return _label_dbg;
+
+ }
+
+ } // end of namespace mln::clustering::impl
+
+
+
+
+
+ //--------------------------------------------------------------------------
+ // Internal.
+ //--------------------------------------------------------------------------
+
+ namespace internal
+ {
+
+ template <typename T, unsigned n>
+ inline
+ image2d<value::label_8>
+ kmean_rgb_dispatch(const image2d< value::rgb<n> >& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times)
+ {
+ return impl::kmean_image2d_rgb<T,n>(img, k_center, watch_dog, n_times);
+ }
+
+
+ template <typename T, unsigned n, typename I>
+ inline
+ image2d< value::label_8>
+ kmean_rgb_dispatch(const Image<I>& img,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times)
+ {
+ return kmean_rgb_dispatch<T,n>(exact(img),k_center,watch_dog,n_times);
+ }
+
+
+ } // end of namespace mln::clustering::internal
+
+
+ //--------------------------------------------------------------------------
+ // Facade.
+ //--------------------------------------------------------------------------
+
+ template <typename T, unsigned n, typename I>
+ inline
+ image2d<value::label_8>
+ kmean_rgb(const Image<I>& point,
+ const unsigned k_center,
+ const unsigned watch_dog,
+ const unsigned n_times)
+ {
+ trace::entering("mln::clustering::kmean_rgb");
+
+ image2d<value::label_8> tmp = internal::kmean_rgb_dispatch<T,n>(point,
+ k_center,
+ watch_dog,
+ n_times);
+ trace::exiting("mln::clustering::kmean_rgb");
+
+ return tmp;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::clustering
+
+} // end of namespace mln
+
+#endif // ! MLN_CLUSTERING_KMEAN_RGB_HH
--
1.5.6.5