* 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