
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-07-01 Edwin Carlinet <carlinet@lrde.epita.fr> Retrieval of components whose maximize mean color difference. * edwin/exec/color_distance.hh: Some routines about color distances. * edwin/exec/max_delta_colormean_obj.cc: Main file for components retrieval with respect to their mean color difference. * edwin/mln/morpho/tree/components.hh: Minor fixes. --- exec/color_distance.hh | 80 +++++++++++++++++ exec/max_delta_colormean_obj.cc | 179 ++++++++++++++++++++++++++++++++++++++++ mln/morpho/tree/components.hh | 15 ++- 3 files changed, 268 insertions(+), 6 deletions(-) Index: trunk/milena/sandbox/edwin/exec/color_distance.hh =================================================================== --- trunk/milena/sandbox/edwin/exec/color_distance.hh (revision 0) +++ trunk/milena/sandbox/edwin/exec/color_distance.hh (revision 4225) @@ -0,0 +1,80 @@ +//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. + +// From theo's sandbox ~theo/color/filter_meandist_rgb_pixels.cc + + +#ifndef COLOR_DISTANCE_HH +# define COLOR_DISTANCE_HH + +#include <mln/value/rgb8.hh> +#include <mln/math/diff_abs.hh> + +namespace mln +{ + + value::int_u8 dist_mean(const value::rgb8& c1, const value::rgb8& c2) + { + unsigned d = 0; + d += (math::diff_abs(c1.red(), c2.red()) + 2) / 3; + d += (math::diff_abs(c1.green(), c2.green()) + 2) / 3; + d += (math::diff_abs(c1.blue(), c2.blue()) + 2) / 3; + if (d > 255) + d = 255; + return d; + } + + value::int_u8 dist_sat(const value::rgb8& c1, const value::rgb8& c2) + { + unsigned d = 0; + d += math::diff_abs(c1.red(), c2.red()); + d += math::diff_abs(c1.green(), c2.green()); + d += math::diff_abs(c1.blue(), c2.blue()); + if (d > 255) + d = 255; + return d; + } + + value::int_u8 dist_max(const value::rgb8& c1, const value::rgb8& c2) + { + unsigned d = 0, d_; + d_ = math::diff_abs(c1.red(), c2.red()); + if (d_ > d) d = d_; + d_ = math::diff_abs(c1.green(), c2.green()); + if (d_ > d) d = d_; + d_ = math::diff_abs(c1.blue(), c2.blue()); + if (d_ > d) d = d_; + return d; + } + + + +# ifndef MLN_INCLUDE_ONLY + +# endif // ! MLN_INCLUDE_ONLY + +} // end of namespace mln. + +#endif // ! COLOR_DISTANCE_HH Index: trunk/milena/sandbox/edwin/exec/max_delta_colormean_obj.cc =================================================================== --- trunk/milena/sandbox/edwin/exec/max_delta_colormean_obj.cc (revision 0) +++ trunk/milena/sandbox/edwin/exec/max_delta_colormean_obj.cc (revision 4225) @@ -0,0 +1,179 @@ +//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. + +#include <mln/core/image/image2d.hh> +#include <mln/core/alias/neighb2d.hh> + +#include <mln/value/int_u8.hh> +#include <mln/value/rgb8.hh> + +#include <mln/morpho/tree/data.hh> +#include <mln/morpho/tree/compute_attribute_image.hh> +#include <mln/morpho/tree/components.hh> +#include <mln/morpho/tree/propagate.hh> + +#include <mln/accu/stat/mean.hh> + +#include <mln/data/sort_psites.hh> +#include <mln/data/convert.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/ppm/load.hh> +#include <mln/io/pbm/save.hh> + + +#include "color_distance.hh" +#include <iostream> +#include <cstring> + +using namespace mln; +using value::int_u8; + + +void usage(char** argv) +{ + std::cout << "Usage: " << argv[0] << " in:input.pgm in:source(.pgm|.ppm) [out:attribute.pbm]" + << std::endl + << "Compute the mean attribute image from 'source' values using 'input'" + " min tree structure. Then, compute the delta image d (parent(n) - n) and retrieve" + " components that maximizes the delta. The retrieved components are stored through a mask" + " where objects are set to 1 and background to 0 in 'attribute.pbm'." + << std::endl; + + abort(); +} + +const char* get_extension(const char* filename) +{ + return (filename + strlen(filename) - 3); +} + + +template <typename T, typename S> +inline +mln_ch_value(typename T::function, int_u8) +compute_delta_mean(const value::int_u8&, const T& tree, const Image<S>& source) +{ + + typedef mln_ch_value(typename T::function, mln_sum(mln_value(S))) O; + O out = morpho::tree::compute_attribute_image_from(accu::stat::mean<mln_value(S)>(), + tree, source); + + // Compute delta image. + mln_ch_value(typename T::function, int_u8) dist; + initialize(dist, tree.f()); + + mln_up_node_piter(T) n(tree); + for_all(n) + dist(n) = out(tree.parent(n)) - out(n); + + return dist; +} + +template <typename T, typename S> +inline +mln_ch_value(typename T::function, int_u8) +compute_delta_mean(const value::rgb8&, const T& tree, const Image<S>& source) +{ + + typedef mln_ch_value(typename T::function, mln_sum(mln_value(S))) O; + O out = morpho::tree::compute_attribute_image_from(accu::stat::mean<mln_value(S)>(), + tree, source); + + // Compute delta image. + mln_ch_value(typename T::function, int_u8) dist; + initialize(dist, tree.f()); + + mln_up_node_piter(T) n(tree); + for_all(n) + { + // Fixme: rewrite distance routines with vector instead of convert ? + dist(n) = dist_mean(convert::to<value::rgb8>(out(tree.parent(n))), convert::to<value::rgb8>(out(n))); + } + + return dist; +} + +template <typename T, typename S> +inline +mln_ch_value(typename T::function, int_u8) +compute_delta_mean(const T& tree, const Image<S>& source) +{ + return compute_delta_mean(mln_value(S) (), tree, source); +} + + + +int main(int argc, char** argv) +{ + + + if (argc < 3) + usage(argv); + + const char* finput = argv[1]; + const char* fsource = argv[2]; + const char* foutput = argc > 3 ? argv[3] : "mask.pbm"; + + // Image loadin'. + typedef image2d<value::int_u8> I; + I input; + io::pgm::load(input, finput); + + + // Tree construction. + typedef p_array<mln_psite_(I)> S; + typedef morpho::tree::data<I, S> T; + + S s = data::sort_psites_increasing(input); + T tree(input, s, c4()); + + // Attribute computation. + mln_ch_value_(I, int_u8) delta; + + const char* extension = get_extension(fsource); + if (strcmp(extension, "pgm") == 0) + { + image2d<value::int_u8> src; + io::pgm::load(src, fsource); + delta = compute_delta_mean(tree, src); + } + else if (strcmp(extension, "ppm") == 0) + { + image2d<value::rgb8> src; + io::ppm::load(src, fsource); + delta = compute_delta_mean(tree, src); + } + else + usage(argv); // Type not handled. + + // Get the max components of the delta image. + p_array<mln_psite_(I)> obj = morpho::tree::get_components(tree, delta); + + typedef mln_ch_value_(I, bool) O; + O out = morpho::tree::set_value_to_components(tree, obj, true, false); + + io::pbm::save(out, foutput); +} Index: trunk/milena/sandbox/edwin/mln/morpho/tree/components.hh =================================================================== --- trunk/milena/sandbox/edwin/mln/morpho/tree/components.hh (revision 4224) +++ trunk/milena/sandbox/edwin/mln/morpho/tree/components.hh (revision 4225) @@ -49,7 +49,9 @@ namespace mln { + namespace morpho { + namespace tree { /** @@ -237,7 +239,6 @@ p = max_arr[arr_pos]; if (a(p) == 0) break; - std::cout << p << " " << a(p) << std::endl; components.insert(p); morpho::tree::propagate_node_to_descendants(p, tree, activity, false, nb_leaves); morpho::tree::propagate_node_to_ancestors(p, tree, activity, false); @@ -262,7 +263,7 @@ trace::entering("mln::morpho::tree::get_components"); const A& a = exact(attr_image); - mln_precondition(tree.f().domain() == a.domain()); + mln_precondition(tree.f().domain() == a.domain()); // May be to strong. mln_precondition(a.is_valid()); p_array< mln_psite(A) > components = @@ -280,7 +281,7 @@ trace::entering("mln::morpho::tree::get_components"); const A& a = exact(attr_image); - mln_precondition(tree.f().domain() == a.domain()); + mln_precondition(tree.f().domain() == a.domain()); // May be to strong. mln_precondition(a.is_valid()); p_array< mln_psite(A) > components; @@ -300,7 +301,7 @@ const A& a = exact(attr_image); const P2B& predicate = exact(pred); - mln_precondition(tree.f().domain() == a.domain()); + mln_precondition(tree.f().domain() == a.domain()); // May be to strong. mln_precondition(a.is_valid()); p_array< mln_psite(A) > components = @@ -310,10 +311,12 @@ return components; } +# endif /* !MLN_INCLUDE_ONLY */ + } // end of namespace mln::morpho::tree + } // end of namespace mln::morpho -} // end of namespace mln -# endif /* !MLN_INCLUDE_ONLY */ +} // end of namespace mln #endif /* !MLN_MORPHO_TREE_COMPONENTS_HH_ */