
* green/histo1d : New directory. * green/histo1d/Makefile.am : New Makefile. * green/histo1d/histo1d.hh : New C++ type. * green/histo1d/save_sh.hh : New gnuplot export routine. * green/histo1d/histo1d.cc : New unitary tests. --- trunk/milena/sandbox/ChangeLog | 10 + trunk/milena/sandbox/green/histo1d/Makefile.am | 49 +++++ trunk/milena/sandbox/green/histo1d/histo1d.cc | 274 ++++++++++++++++++++++++ trunk/milena/sandbox/green/histo1d/histo1d.hh | 270 +++++++++++++++++++++++ trunk/milena/sandbox/green/histo1d/save_sh.hh | 198 +++++++++++++++++ 5 files changed, 801 insertions(+), 0 deletions(-) create mode 100644 trunk/milena/sandbox/green/histo1d/Makefile.am create mode 100644 trunk/milena/sandbox/green/histo1d/histo1d.cc create mode 100644 trunk/milena/sandbox/green/histo1d/histo1d.hh create mode 100644 trunk/milena/sandbox/green/histo1d/save_sh.hh diff --git a/trunk/milena/sandbox/ChangeLog b/trunk/milena/sandbox/ChangeLog index efcfd71..87880a5 100644 --- a/trunk/milena/sandbox/ChangeLog +++ b/trunk/milena/sandbox/ChangeLog @@ -18,6 +18,16 @@ 2009-08-04 Yann Jacquelet <jacquelet@lrde.epita.fr> + Write histogram accumulator which the result is image1d. + + * green/histo1d : New directory. + * green/histo1d/Makefile.am : New Makefile. + * green/histo1d/histo1d.hh : New C++ type. + * green/histo1d/save_sh.hh : New gnuplot export routine. + * green/histo1d/histo1d.cc : New unitary tests. + +2009-08-04 Yann Jacquelet <jacquelet@lrde.epita.fr> + Integrate LRDE code writting rules in the Stats code. * green/Stats/Makefile.am : Remove Makefile. diff --git a/trunk/milena/sandbox/green/histo1d/Makefile.am b/trunk/milena/sandbox/green/histo1d/Makefile.am new file mode 100644 index 0000000..36a83e3 --- /dev/null +++ b/trunk/milena/sandbox/green/histo1d/Makefile.am @@ -0,0 +1,49 @@ +# +# Generic Makefile +# + +BIN_PATTERN= trunk/build/milena +SRC_PATTERN= trunk/milena + +CXXFLAGS= -ggdb -O0 -Wall -W -pedantic -ansi -pipe +ECHO= echo +RM= rm +MKDIR= mkdir +CP= cp + +ifeq ($(findstring $(BIN_PATTERN),$(PWD)), $(BIN_PATTERN)) +BIN_DIR= +SRC_DIR= $(subst $(BIN_PATTERN),$(SRC_PATTERN), $(PWD))/ +else +BIN_DIR= $(subst $(SRC_PATTERN),$(BIN_PATTERN), $(PWD))/ +SRC_DIR= +endif + +TARGET= $(BIN_DIR)$(notdir $(PWD)) +BIN_MAKE= $(BIN_DIR)Makefile +SRC_MAKE= $(SRC_DIR)Makefile.am + + +SRC_FILES= $(wildcard $(SRC_DIR)*.cc) +OLD_FILES= $(addsuffix ~, $(SRC_FILES)) +OBJ_FILES= $(addprefix $(BIN_DIR), $(notdir $(SRC_FILES:%.cc=%.o))) + + +all: $(BIN_DIR) $(TARGET) + @$(ECHO) "Compilation terminée" + +$(BIN_DIR): + $(MKDIR) $(BIN_DIR) + $(CP) $(SRC_MAKE) $(BIN_MAKE) + +$(TARGET):$(OBJ_FILES) + $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@ + +$(BIN_DIR)%.o:$(SRC_DIR)%.cc + $(COMPILE.cc) $(OUTPUT_OPTION) $< + +clean: + -@$(RM) $(TARGET) + -@$(RM) $(OBJ_FILES) + -@$(RM) $(OLD_FILES) + diff --git a/trunk/milena/sandbox/green/histo1d/histo1d.cc b/trunk/milena/sandbox/green/histo1d/histo1d.cc new file mode 100644 index 0000000..c39a412 --- /dev/null +++ b/trunk/milena/sandbox/green/histo1d/histo1d.cc @@ -0,0 +1,274 @@ +/// TEST HISTO1D + +#include "save_sh.hh" +#include "histo1d.hh" + +#include <mln/io/pgm/load.hh> +#include <mln/io/plot/save.hh> + +#include <mln/data/compute.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/label_8.hh> + +#include <mln/core/alias/neighb1d.hh> +#include <mln/core/alias/box1d.hh> +#include <mln/core/alias/point1d.hh> + +#include <mln/core/routine/initialize.hh> +#include <mln/core/contract.hh> + +#include <mln/accu/math/sum.hh> +#include <mln/accu/math/count.hh> +#include <mln/accu/stat/mean.hh> +#include <mln/accu/stat/variance.hh> + +#include <mln/morpho/watershed/flooding.hh> +#include <mln/morpho/elementary/dilation.hh> +#include <mln/morpho/elementary/closing.hh> + +void test_operator_equal() +{ + using namespace mln::accu::stat; + + typedef mln::value::int_u8 int_u8; + mln::accu::stat::histo1d<int_u8> histo1; + mln::accu::stat::histo1d<int_u8> histo2; + int_u8 val = 3; + + histo1.init(); + histo2.init(); + + mln_assertion(histo1 == histo2); + + histo1.take(val); + + mln_assertion(!(histo1 == histo2)); + + histo2.take(val); + + mln_assertion(histo1 == histo2); + + std::cout << "histo == histo : ok" << std::endl; +} + +void test_instantiation_without_argument() +{ + typedef mln::value::int_u8 int_u8; + const mln::accu::stat::histo1d<int_u8> histo; + const mln::image1d<unsigned>& res = histo.to_result(); + const mln::point1d& min = mln::point1d(mln_min(int_u8)); + const mln::point1d& max = mln::point1d(mln_max(int_u8)); + const mln::box1d& ref = mln::box1d(min, max); + + mln_assertion(ref == res.domain()); + mln_assertion(res.is_valid()); + + std::cout << "histo<T> histo : ok" << std::endl; +} + + +void test_initialization() +{ + typedef mln::value::int_u8 int_u8; + mln::accu::stat::histo1d<int_u8> histo; + mln::image1d<unsigned> img_res = histo.to_result(); + mln::image1d<unsigned> img_ref; + + mln::initialize(img_ref, img_res); + mln::data::fill(img_ref, 0); + histo.init(); + + unsigned res = mln::data::compute(mln::accu::math::sum<int_u8>(), img_res); + unsigned ref = mln::data::compute(mln::accu::math::sum<int_u8>(), img_ref); + + mln_assertion(ref == res); + + std::cout << "histo.init() : ok" << std::endl; +} + + +void test_take_argument() +{ + typedef mln::value::int_u8 int_u8; + mln::accu::stat::histo1d<int_u8> histo1; + mln::accu::stat::histo1d<int_u8> histo2; + int_u8 val = 3; + + histo1.init(); + histo2.init(); + histo1.take(val); + + const mln::image1d<unsigned> img1 = histo1.to_result(); + const mln::image1d<unsigned> img2 = histo2.to_result(); + + const unsigned res = mln::data::compute(mln::accu::math::sum<int_u8>(), img1); + const unsigned ref = mln::data::compute(mln::accu::math::sum<int_u8>(), img2); + + mln_assertion(ref == res-1); + mln_assertion(1 == img1(mln::point1d(val))); + + std::cout << "histo.take(argument) : ok" << std::endl; +} + + +void test_take_other() +{ + typedef mln::value::int_u8 int_u8; + mln::accu::stat::histo1d<int_u8> histo1; + mln::accu::stat::histo1d<int_u8> histo2; + mln::accu::stat::histo1d<int_u8> histo3; + int_u8 val = 3; + + histo1.init(); + histo2.init(); + histo3.init(); + + histo1.take(val); + histo1.take(val); + histo3.take(val); + histo2.take(val); + histo2.take(histo3); + + mln_assertion(histo1 == histo2); + + std::cout << "histo.take(other) : ok" << std::endl; +} + +double count_histo(mln::image1d<unsigned> img) +{ + mln_precondition(img.is_valid()); + + double result = 0.0; + mln_piter_(mln::image1d<unsigned>) p(img.domain()); + + for_all(p) + result += img(p); + + return result; +} + +double mean_histo(mln::image1d<unsigned> img) +{ + mln_precondition(img.is_valid()); + + double count = 0.0; + double sum = 0.0; + double result = 0.0; + mln_piter_(mln::image1d<unsigned>) p(img.domain()); + + for_all(p) + { + count += img(p); + sum += p[0] * img(p); + } + + result = sum / count; + + return result; +} + + +double var_histo(mln::image1d<unsigned> img) +{ + mln_precondition(img.is_valid()); + + double count = 0.0; + double sum = 0.0; + double sum2 = 0.0; + double result = 0.0; + mln_piter_(mln::image1d<unsigned>) p(img.domain()); + + for_all(p) + { + count += img(p); + sum += p[0] * img(p); + sum2 += p[0] * p[0] * img(p); + } + + result = sum2 / count - (sum / count) * (sum / count); + + return result; +} + +void test_integration() +{ + typedef mln::value::int_u8 int_u8; + typedef mln::accu::math::count<double> count; + typedef mln::accu::math::sum<double> sum; + typedef mln::accu::stat::mean<double> mean; + typedef mln::accu::stat::variance<double> variance; + + mln::image2d<int_u8> img_ref; + mln::image1d<unsigned> img_res; + + mln::io::pgm::load(img_ref, "/usr/local/share/olena/images/lena.pgm"); + + const double count_ref = mln::data::compute(count(), img_ref); + const double mean_ref = mln::data::compute(mean(), img_ref); + const double var_ref = mln::data::compute(variance(), img_ref); + + img_res = mln::data::compute(mln::accu::stat::histo1d<int_u8>(), img_ref); + + const double count_res = count_histo(img_res); + const double mean_res = mean_histo(img_res); + const double var_res = var_histo(img_res); + + mln_assertion(count_ref == count_res); + mln_assertion( mean_ref == mean_res ); + mln_assertion( var_ref == var_res ); + + std::cout << "test integration : ok" << std::endl; +} + + +void test_classifying() +{ + typedef mln::value::int_u8 int_u8; + typedef mln::value::label_8 label_8; + + mln::image2d<int_u8> img_ref; + mln::image1d<unsigned> img_res; + mln::image1d<label_8> labels; + label_8 n_shape; + + mln::io::pgm::load(img_ref, "/usr/local/share/olena/images/lena.pgm"); + + img_res = mln::data::compute(mln::accu::stat::histo1d<int_u8>(), img_ref); + + mln::io::plot::save_sh(img_res, "histo.sh"); + + img_res = mln::morpho::elementary::closing(img_res, mln::c2()); + img_res = mln::morpho::elementary::closing(img_res, mln::c2()); + img_res = mln::morpho::elementary::closing(img_res, mln::c2()); + + mln::io::plot::save_sh(img_res, "histo1.sh"); + /* + labels = mln::morpho::watershed::flooding(img_res, mln::c2(), n_shape); + + mln::io::plot::save_sh(labels, "histo2.sh"); + + labels = mln::morpho::elementary::dilation(labels, mln::c2()); + + mln::io::plot::save_sh(labels, "histo3.sh"); + + //mln::io::plot::save(labels, "labelized.data"); + */ +} + +int main() +{ + using namespace mln; + using namespace std; + + test_instantiation_without_argument(); + test_initialization(); + test_take_argument(); + test_take_other(); + test_operator_equal(); + test_integration(); + + //test_classifying(); + + return 0; +} diff --git a/trunk/milena/sandbox/green/histo1d/histo1d.hh b/trunk/milena/sandbox/green/histo1d/histo1d.hh new file mode 100644 index 0000000..23e230b --- /dev/null +++ b/trunk/milena/sandbox/green/histo1d/histo1d.hh @@ -0,0 +1,270 @@ +// 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_ACCU_HISTO1D_HH +#define MLN_ACCU_HISTO1D_HH + +/// \file +/// +/// \brief Define an histogram as an accumulator which returns an image1d . +/// +/// It based on image to allow collecting statistics on it. +/// + +#include <iostream> + +#include <mln/accu/internal/base.hh> + +#include <mln/core/macros.hh> +#include <mln/core/image/image1d.hh> + +#include <mln/trait/value/comp.hh> + +#include <mln/arith/plus.hh> + +#include <mln/trace/entering.hh> +#include <mln/trace/exiting.hh> + +#include <mln/value/ops.hh> + +namespace mln +{ + + namespace accu + { + + namespace stat + { + + // Forward declaration + template <typename V> + struct histo1d; + + } // end of namespace mln::accu::stat + + } // end of namespace mln::accu + + + namespace trait + { + + template <typename V> + struct accumulator_< mln::accu::stat::histo1d<V> > + { + typedef accumulator::has_untake::no has_untake; + typedef accumulator::has_set_value::no has_set_value; + typedef accumulator::has_stop::no has_stop; + typedef accumulator::when_pix::use_v when_pix; + }; + + template <typename V> + struct set_precise_binary_<op::eq, + accu::stat::histo1d<V>, + accu::stat::histo1d<V> > + { + typedef bool ret; + }; + + } // end of namespace mln::trait + + namespace accu + { + + namespace stat + { + + + /// \brief Define an histogram which returns an image1d . + /// + /// Param V defines the space in which we count the values. + /// For instance, this histogram works image2d<gl8> or image1d<gl16>. + /// The histogram count the occurrence of each value. + /// + /// \ingroup modaccuvalues + + template <typename V> + struct histo1d : + public mln::accu::internal::base<image1d<unsigned>, histo1d<V> > + { + typedef V argument; + typedef image1d<unsigned> result; + typedef result q_result; + + /// Constructors + /// \{ + /// \brief Nothing to do + histo1d(); + /// \} + + + /// Manipulators. + /// \{ + /// \brief Initialize the bounding box of the resulting image. + void init(); + + + /// \brief Update the histogram with the RGB pixel t. + /// \param[in] t a RGB pixel. + void take(const argument& t); + + + /// \brief Update the histogram with an other histogram. + /// \param[in] other the other histogram. + void take(const histo1d<V>& other); + /// \} + + /// Accessors. + /// \{ + result to_result() const; + operator result () const; + /// \} + + /// Check whethever this accumulator is able to return a result. + /// Always in a safe state and then always return true; + bool is_valid() const; + + protected: + result count_; + }; + + template <typename V> + bool operator==(const histo1d<V>& histo1, const histo1d<V>& histo2); + +#ifndef MLN_INCLUDE_ONLY + + + + + template <typename V> + inline + histo1d<V>::histo1d() + { + trace::entering("mln::accu::stat::histo1d<V>::histo1d"); + typedef mln_trait_value_comp(V,0) comp; + + count_.init_(box1d(point1d(mln_min(comp)), // -> 0 + point1d(mln_max(comp)))); // -> 2^n-1 + + trace::exiting("mln::accu::stat::histo1d<V>::histo1d"); + } + + template <typename V> + inline + void histo1d<V>::init() + { + trace::entering("mln::accu::stat::histo1d<V>::init"); + + data::fill(count_, 0); + trace::exiting("mln::accu::stat::histo1d<V>::init"); + } + + template <typename V> + inline + void histo1d<V>::take(const argument& t) + { + trace::entering("mln::accu::stat::histo1d<V>::take"); + + ++count_(point1d(t)); + + trace::exiting("mln::accu::stat::histo1d<V>::take"); + } + + + template <typename V> + inline + void histo1d<V>::take(const histo1d<V>& other) + { + trace::entering("mln::accu::stat::histo1d<V>::take"); + + count_ += other.count_; + + trace::exiting("mln::accu::stat::histo1d<V>::take"); + } + + template <typename V> + inline + typename histo1d<V>::result histo1d<V>::to_result() const + { + trace::entering("mln::accu::stat::histo1d<V>::to_result"); + + trace::exiting("mln::accu::stat::histo1d<V>::to_result"); + return count_; + } + + template <typename V> + inline + histo1d<V>::operator result() const + { + trace::entering("mln::accu::stat::histo1d<V>::operator result"); + + trace::exiting("mln::accu::stat::histo1d<V>::operator result"); + return count_; + } + + template <typename V> + inline + bool histo1d<V>::is_valid() const + { + trace::entering("mln::accu::stat::histo1d<V>::is_valid"); + + trace::exiting("mln::accu::stat::histo1d<V>::is_valid"); + return true; + } + + template <typename V> + bool operator==(const histo1d<V>& histo1, const histo1d<V>& histo2) + { + trace::entering("mln::accu::stat::operator=="); + + bool result = true; + const image1d<unsigned>& res1 = histo1.to_result(); + const image1d<unsigned>& res2 = histo2.to_result(); + + mln_precondition(res1.is_valid()); + mln_precondition(res2.is_valid()); + + mln_piter(image1d<unsigned>) p1(res1.domain()); + mln_piter(image1d<unsigned>) p2(res2.domain()); + + for_all_2(p1, p2) + result &= (res1(p1) == res2(p2)); + + trace::exiting("mln::accu::stat::operator=="); + return result; + } + + +#endif // ! MLN_INCLUDE_ONLY + + + } // end of namespace mln::accu::stat + + } // end of namespace mln::accu + +} // end of namespace mln + +#endif // ! MLN_ACCU_HISTO1D_HH diff --git a/trunk/milena/sandbox/green/histo1d/save_sh.hh b/trunk/milena/sandbox/green/histo1d/save_sh.hh new file mode 100644 index 0000000..ece30f4 --- /dev/null +++ b/trunk/milena/sandbox/green/histo1d/save_sh.hh @@ -0,0 +1,198 @@ +// 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_IO_PLOT_SAVE_SH_HH +#define MLN_IO_PLOT_SAVE_SH_HH + +/// \file +/// +/// \brief Define some function to export to gnuplots format as a script shell. +/// +/// Theses routines help to visualize data. +/// + +#include <fstream> +#include <string> + +#include <mln/core/macros.hh> +#include <mln/core/image/image1d.hh> +#include <mln/core/image/image2d.hh> +#include <mln/core/image/image3d.hh> + + +namespace mln +{ + + namespace io + { + + namespace plot + { + + /// \brief Save a image1d as a gnuplot script shell. + /// \param[in] img the 1d image which contains the data to save. + /// \param[in] filename the name of the unix script shell. + template <typename I> + void save_sh(const image1d<I>& img, const std::string& filename); + + /// \brief Save a image2d as a gnuplot script shell. + /// \param[in] img the 2d image which contains the data to save. + /// \param[in] filename the name of the unix script shell. + template <typename I> + void save_sh(const image2d<I>& img, const std::string& filename); + + /// \brief Save a image3d as a gnuplot script shell. + /// \param[in] img the 3d image which contains the data to save. + /// \param[in] filename the name of the unix script shell. + template <typename I> + void save_sh(const image3d<I>& img, const std::string& filename); + + } // end of namespace mln::accu::stat + + } // end of namespace mln::accu + + + namespace io + { + + namespace plot + { + +#ifndef MLN_INCLUDE_ONLY + + template <typename I> + inline + void save_sh(const image1d<I>& img, const std::string& filename) + { + trace::entering("mln::io::plot::save_sh<1d>"); + mln_precondition(img.is_valid()); + + std::ofstream out(filename.c_str()); + mln_piter(image1d<I>) p(img.domain()); + + out << "#!/bin/sh" << std::endl; + out << "##########################" << std::endl; + out << "# Two columns = (x,data) #" << std::endl; + out << "##########################" << std::endl; + out << std::endl; + out << "gnuplot <<EOF" << std::endl; + out << "set terminal x11 persist 1" << std::endl; + //out << "plot '-' with points pointtype 0" << std::endl; + out << "plot '-' with histograms" << std::endl; + + for_all(p) + { + // for (unsigned i = 0; i < mln_dim(I); ++i) + // out << p[0] << " "; + + out << img(p) << std::endl; + } + out << "e" << std::endl; + out << "EOF" << std::endl; + + out.close(); + trace::exiting("mln::io::plot::save_sh<1d>"); + } + + template <typename I> + inline + void save_sh(const image2d<I>& img, const std::string& filename) + { + trace::entering("mln::io::plot::save_sh<2d>") + mln_precondition(img.is_valid()); + + std::ofstream out(filename.c_str()); + mln_piter(I) p(img.domain()); + + out << "#!/bin/sh" << std::endl; + out << "##############################" << std::endl; + out << "# Three columns = (x,y,data) #" << std::endl; + out << "##############################" << std::endl; + out << std::endl; + out << "gnuplot <<EOF" << std::endl; + out << "set terminal x11 persist 1" << std::endl; + out << "plot '-' with points palette pointtype 0" << std::endl; + + for_all(p) + { + for (unsigned i = 0; i < mln_dim(I); ++i) + out << p << " "; + + out << img(p) << std::endl; + } + + out << "e" << std::endl; + out << "EOF" << std::endl; + + out.close(); + trace::exiting("mln::io::plot::save_sh<2d>"); + } + + template <typename I> + inline + void save_sh(const image3d<I>& img, const std::string& filename) + { + trace::entering("mln::io::plot::save_sh<3d>") + mln_precondition(img.is_valid()); + + std::ofstream out(filename.c_str()); + mln_piter(I) p(img.domain()); + + out << "#!/bin/sh" << std::endl; + out << "####################################" << std::endl; + out << "# Columns = (red,green,blue,count) #" << std::endl; + out << "####################################" << std::endl; + out << std::endl; + out << "gnuplot <<EOF" << std::endl; + out << "set terminal x11 persist 1" << std::endl; + out << "splot '-' with points palette pointtype 0" << std::endl; + + for_all(p) + if (0 < img(p)) + { + out << p.row() << " "; + out << p.col() << " "; + out << p.sli() << " "; + out << img(p) << std::endl; + } + out << "e" << std::endl; + out << "EOF" << std::endl; + + out.close(); + trace::exiting("mln::io::plot::save_sh<3d>"); + } + +#endif // ! MLN_INCLUDE_ONLY + + + } // end of namespace mln::accu::stat + + } // end of namespace mln::accu + +} // end of namespace mln + +#endif // ! MLN_IO_PLOT_SAVE_SH_HH -- 1.5.6.5