r3665: Add multivalued image support for components detection

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2009-04-14 Edwin Carlinet <carlinet@lrde.epita.fr> Add multivalued image support for components detection. * edwin/tree/propagate.hh: Move a propagation routine from sharp.cc to this file. * edwin/tree/sharp.cc: Add multivalued image support. --- propagate.hh | 36 ++++++++++++++++++++++++ sharp.cc | 86 +++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 88 insertions(+), 34 deletions(-) Index: trunk/milena/sandbox/edwin/tree/propagate.hh =================================================================== --- trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3664) +++ trunk/milena/sandbox/edwin/tree/propagate.hh (revision 3665) @@ -55,6 +55,42 @@ } } + /** + ** For each component in the list \p component_list, it + ** propagates the representant value to the remaining nodes of the + ** component. The value of a node that doesn't belong to a component is + ** set to \p null. + ** + ** @param attr_image The attribute image. + ** @param tree The component tree used to propagate value. + ** @param component_list The list of components. + ** @param null The nodes that don't belong to components will be set + ** with this value. + ** + ** @return The resulting component image. + */ + template <typename A, typename T> + inline + A set_value_to_components(const Image<A>& attr_image, + const T& tree, + const p_array< mln_psite(A) >& component_list, + const mln_value(A)& null) + { + const A& attr_img = exact(attr_image); + A out; + initialize(out, attr_img); + data::fill(out, null); + + mln_piter(p_array<mln_psite(A)>) p(component_list); + for_all(p) + { + out(p) = attr_img(p); + morpho::tree::propagate_node_to_descendants(p, tree, out); + } + morpho::tree::propagate_representant(tree, out); + return out; + } + } // end of namespace mln::morpho::tree } // end of namespace mln::morpho } // end of namespace mln Index: trunk/milena/sandbox/edwin/tree/sharp.cc =================================================================== --- trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3664) +++ trunk/milena/sandbox/edwin/tree/sharp.cc (revision 3665) @@ -22,6 +22,7 @@ /* io */ +#include <mln/io/ppm/load.hh> #include <mln/io/pgm/load.hh> #include <mln/io/pgm/save.hh> #include <mln/io/pbm/save.hh> @@ -61,49 +62,53 @@ << "*********************" << std::endl; } +namespace mln +{ + // Distance, stored on pixels, of neighboring colors. -/** -** For each component in the list \p component_list, it -** propagates the representant value to the remaining nodes of the -** component. The value of a node that doesn't belong to a component is -** set to \p null. -** -** @param attr_image The attribute image. -** @param tree The component tree used to propagate value. -** @param component_list The list of components. -** @param null The nodes that don't belong to components will be set -** with this value. -** -** @return The resulting component image. -*/ -template <typename A, typename T> -inline -A set_value_to_components(const Image<A>& attr_image, - const T& tree, - const p_array< mln_psite(A) >& component_list, - const mln_value(A)& null) -{ - const A& attr_img = exact(attr_image); - A out; - initialize(out, attr_img); - data::fill(out, null); + 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; + } - mln_piter(p_array<mln_psite(A)>) p(component_list); + template <typename N> + image2d<value::int_u8> + dist_on_pixels(const image2d<value::rgb8>& input, const N& nbh) + { + using value::int_u8; + image2d<int_u8> output(input.domain()); + + mln_piter(box2d) p(input.domain()); + mln_niter(N) n(nbh, p); for_all(p) { - out(p) = attr_img(p); - morpho::tree::propagate_node_to_descendants(p, tree, out); + int_u8 d = 0u; + for_all(n) if (input.domain().has(n)) + { + int_u8 d_ = dist_mean(input(p), input(n)); + if (d_ > d) + d = d_; + } + output(p) = 255 - d; + } + return output; } - morpho::tree::propagate_representant(tree, out); - return out; } + int main(int argc, char* argv[]) { using value::int_u8; + using value::rgb8; std::string arg; unsigned nb_components = 0; unsigned card = 0; @@ -131,10 +136,15 @@ /* Image loadin' */ + image2d<rgb8> input_; + io::ppm::load(input_, argv[1]); + typedef image2d<int_u8> I; + I input = dist_on_pixels(input_, c4()); + + if (mydebug) + io::pgm::save(input, "input.pgm"); - I input; - io::pgm::load(input, argv[1]); /* Component tree creation */ typedef p_array< mln_site_(I) > S; @@ -144,6 +154,12 @@ tree_t tree(input, sorted_sites, c4()); /* Compute Attribute On Image */ + + // TODO: l'attribut devrait favoriser les composantes plus larges + // dans son calcul. Ainsi au lieu de faire un sharpness, on aurait + // un ratio sharpness / largeur de composante (reprendre l'idee du + // log utilise pour INIM). + typedef morpho::attribute::sharpness<I> sharp_t; typedef mln_ch_value_(I, double) A; @@ -175,6 +191,9 @@ a = duplicate((fun::p2v::ternary(pw::value(b) > pw::cst(card), pw::value(a), pw::cst(0.0))) | a.domain()); } + if (mydebug) + io::pgm::save(level::stretch(int_u8(), a), "attr_image.pgm"); + /* Run max accumulator */ accumulator::arg_max<A> argmax(a); p_array< mln_psite_(A) > obj_array; // Array of object components. @@ -209,12 +228,11 @@ } /* Now Back Propagate to component */ - if (mydebug) { dsp("Create mask and propagate"); } - A pre_output = set_value_to_components(a, tree, obj_array, 0); + A pre_output = morpho::tree::set_value_to_components(a, tree, obj_array, 0); I output = level::stretch(int_u8(), pre_output); io::pgm::save(output, "components.pgm");
participants (1)
-
Edwin Carlinet