r1952: Merge upper and lower level set in fllt

URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2008-05-15 Matthieu Garrigues <garrigues@lrde.epita.fr> * geraud/fllt.cc: Merge upper and lower level set in fllt. --- fllt.cc | 355 +++++++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 294 insertions(+), 61 deletions(-) Index: trunk/milena/sandbox/geraud/fllt.cc =================================================================== --- trunk/milena/sandbox/geraud/fllt.cc (revision 1951) +++ trunk/milena/sandbox/geraud/fllt.cc (revision 1952) @@ -34,6 +34,7 @@ #include <mln/core/image_if_value.hh> #include <mln/core/sub_image.hh> #include <mln/core/p_queue_fast.hh> +#include <mln/core/cast_image.hh> #include <mln/value/int_u8.hh> #include <mln/value/rgb8.hh> @@ -57,6 +58,7 @@ #include <mln/util/tree.hh> #include <mln/util/branch_iter_ind.hh> +#include <mln/util/branch_iter.hh> #include <sstream> @@ -73,6 +75,7 @@ # define fllt_node_ptr(P, V) mln::util::tree_node< fllt_node_elt<P, V>* > # define fllt_branch(P, V) mln::util::branch< fllt_node_elt<P, V> > # define fllt_branch_iter_ind(P, V) mln::util::branch_iter_ind< fllt_node_elt<P, V> > +# define fllt_branch_iter(P, V) mln::util::branch_iter< fllt_node_elt<P, V> > //Fwd declarations. @@ -90,8 +93,25 @@ bool brighter; unsigned npoints; bool tagged; + bool set_id; - fllt_node_elt() : npoints(0), tagged(false) {} + fllt_node_elt(bool set_id) : npoints(0), tagged(false), set_id(set_id) {} + }; + + + template <typename C> + class stl_iterator + { + public: + stl_iterator(C& c) : container_(c) {} + void start(){ it_ = container_.begin(); } + void next() { it_++; } + bool is_valid() const{ return it_ != container_.end(); } + typename C::value_type& operator*() { return *it_; } + + private: + C& container_; + typename C::iterator it_; }; template <typename N_t, typename G, typename Set> @@ -163,20 +183,23 @@ void save_u(const image2d<value::int_u8>& u, const image2d<int>& is, box2d R_box, - int in_R) + int in_R, + int in_N) { static int id = 0; std::stringstream filename; filename << "fllt_trace_" << std::setw(5) << std::setfill('0') << std::right << id++ << ".ppm"; - image2d<value::int_u8> out = clone(u); + image2d<value::int_u8> out = clone(cast_image<value::int_u8>(is)); mln_assertion(R_box.npoints() > 0); mln_piter_(box2d) p(R_box); for_all(p) if (is(p) == in_R) out(p) = 255; + else if (is(p) == in_N) + out(p) = 127; // else if (is(p) == in_N) // out(p) = literal::green; @@ -219,11 +242,12 @@ void blob(const I& is, p_array<mln_point(I)>* N[256], unsigned in_N, + const box2d& N_box, fllt_node(mln_point(I), V)* current_cc) { typedef p_array<mln_point(I)> arr_t; -// std::cout << ">>>>>>>enter blob." << std::endl; +// std::cout << ">>>>>>>enter blob. " << current_cc << std::endl; bool flower = true; unsigned ncc = 0; static image2d<unsigned> is_labeled(is.domain()); @@ -241,6 +265,35 @@ p_queue_fast<P> qu; p_array<P>& holes = current_cc->elt().holes; + mln_piter(I) p(N_box); + for_all(p) + if (is(p) == in_N) + break; + + mln_assertion(is(p) == in_N); + if (is_labeled(p) != label) + { + if (flower == false) + holes.append(p); + else + flower = false; + qu.push(p); + is_labeled(p) = label; + do + { + cur = qu.front(); + qu.pop(); + for_all(n) if (is.has(n)) + if (is(n) == in_N && is_labeled(n) != label) + { + qu.push(n); + is_labeled(n) = label; + } + } + while (! qu.is_empty()); + } + + for (unsigned i = 0; i < 256; ++i) { @@ -308,12 +361,17 @@ if (!smallest_shapes(a)->parent()) if (smallest_shapes(a)->elt().value == g) { + fllt_node(P, V)* to_delete = smallest_shapes(a); + mln_piter(arr_t) p(smallest_shapes(a)->elt().points); // Todo optimization here. for_all(p) smallest_shapes(p) = 0; - delete smallest_shapes(a); + while(!to_delete->children().empty()) + current_cc->add_child(*to_delete->children().begin()); + delete to_delete; + smallest_shapes(a) = current_cc; current_cc->elt().points.append(a); } @@ -329,6 +387,8 @@ struct lower { typedef upper<V> opposite; + // If compare(u,v) u root <- v <- u + // else root <- u <- v static bool compare(const V& u, const V& v) { @@ -343,6 +403,7 @@ } static const bool parent_is_brighter = true; + static const bool id = false; static const neighb2d& bdr_nbh() { return c8(); } static const neighb2d& reg_nbh() { return c4(); } @@ -355,6 +416,8 @@ { typedef lower<V> opposite; + // If compare(u,v) u root <- v <- u + // else root <- u <- v static bool compare(const V& u, const V& v) { return u > v; } @@ -365,6 +428,8 @@ { return labeling::regional_maxima(input, nbh, nlabels); } static const bool parent_is_brighter = false; + static const bool id = true; + static const neighb2d& bdr_nbh() { return c4(); } static const neighb2d& reg_nbh() { return c8(); } }; @@ -410,6 +475,7 @@ N[i] = new arr_t(); accu::bbox<P> N_box; + bool touch_border_of_image = false; unsigned n_step_1 = 0, n_step_3 = 0, n_comps = 0, n_holes = 0; // Step 1. @@ -425,8 +491,9 @@ ++n_step_1; x0 = p; g = input(x0); - current_cc = new node_type(); + current_cc = new node_type(Set::id); current_cc->elt().value = g; + touch_border_of_image = false; } @@ -454,7 +521,7 @@ // Step 3. step_3: { -// save_u(u, deja_vu, N_box, in_R); +// save_u(u, deja_vu, N_box, in_R, in_N); ++n_step_3; mln_piter(arr_t) a(*A); @@ -476,6 +543,8 @@ N[u(x)]->append(x); N_box.take(x); } + else + touch_border_of_image = true; deja_vu(x) = in_N; } } @@ -494,13 +563,19 @@ g = gN; ++n_comps; - blob(deja_vu, N, in_N, current_cc); + + if (touch_border_of_image) + blob(deja_vu, N, in_N, N_box.to_result().to_larger(1), current_cc); + else + blob(deja_vu, N, in_N, N_box, current_cc); + + n_holes += current_cc->elt().holes.npoints(); + node_type* child = current_cc; - current_cc = new node_type(); + current_cc = new node_type(Set::id); current_cc->elt().value = g; child->set_parent(current_cc); - n_holes += current_cc->elt().holes.npoints(); arr_t* tmp = A; A = N[g]; @@ -539,9 +614,61 @@ return *new tree_type(current_cc); } + // F is the set in which we get the node. + template <typename P, typename V, typename F> + fllt_node(P, V)* + find_hole(fllt_node(P, V)& node, + const P p, + const image2d<fllt_node(P, V)*>& other_reg) + { + fllt_node(P, V)* s = other_reg(p); + mln_assertion(s); + while (s->parent() && F::compare(s->parent()->elt().value, node.elt().value)) + { + mln_assertion(s); + s = s->parent(); + mln_assertion(s); + } +// std::cout << " [Find the hole] of " << p +// << " from " << &node +// << " return " << s +// << std::endl; + return s; + } + + template <typename P, typename V> + bool shape_is_included(fllt_branch_iter_ind(P, V) A, + fllt_branch_iter_ind(P, V) B) + { + // TODO: optimize : take the smalest shape first. + typedef p_array<P> arr_t; + + for_all(A) + { + bool found = false; + mln_piter(arr_t) pA((*A).elt().points); + for_all(pA) + for_all(B) + { + found = false; + mln_piter(arr_t) pB((*B).elt().points); + for_all(pB) + if (pA == pB) + { + found = true; + break; + } + if (found) + break; + } + if (!found) + return false; + } + return true; + } template <typename I> - fllt_tree_ptr(mln_point(I), mln_value(I)) + fllt_tree(mln_point(I), mln_value(I)) merge_trees(fllt_tree(mln_point(I), mln_value(I))& lower_tree, fllt_tree(mln_point(I), mln_value(I))& upper_tree, const image2d<fllt_node(mln_point(I), mln_value(I))*>& low_reg, @@ -553,32 +680,104 @@ typedef mln_point(I) P; typedef mln_value(I) V; - typedef fllt_node_ptr(P, V) node_ptr_type; - typedef fllt_tree_ptr(P, V) tree_ptr_type; + typedef fllt_node(P, V) node_type; + typedef fllt_tree(P, V) tree_type; typedef p_array<P> arr_t; - fllt_node_ptr(P, V)* root = new node_ptr_type(); - fllt_node_ptr(P, V)* n = root; - root->elt() = &(lower_tree.root()->elt()); + std::vector<node_type*> to_fill; -// fllt_branch_iter_ind(P, V) p(lower_tree.main_branch()); -// for_all(p) -// { -// if (p->elt().tagged) -// continue; + fllt_branch_iter_ind(P, V) node_(lower_tree.main_branch()); + for_all(node_) + { + node_type& node = *node_; + if (node.elt().set_id != lower<V>::id) + continue; -// p->elt().tagged = true; -// fllt_node_ptr(P, V)* node = new node_ptr_type(); -// node->elt() = &(p->elt()); + // std::cout << "Fill " << &node << std::endl; -// mln_piter(arr_t) hole(p->elt().holes); -// for_all(hole) -// { + mln_piter(arr_t) hole_p(node.elt().holes); + for_all(hole_p) + { + fllt_node(P, V)* hole; + hole = find_hole<P,V,upper<V> >(node, P(hole_p), upp_reg); -// } -// } + bool child_has_bigger_hole = false; + typename fllt_node(P, V)::children_t::iterator it; + for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++) + { + // Browse the holes of each child. + mln_piter(arr_t) q((*it)->elt().holes); + for_all(q) + { + fllt_node(P, V)* child_hole = find_hole<P,V,upper<V> >((**it), point2d(q), upp_reg); + // std::cout << "hole : " << hole << " " << hole->elt().points << " " << std::endl; + // std::cout << "child hole : " << child_hole << " " << child_hole->elt().points << std::endl; + if (shape_is_included(fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(upper_tree, *hole)), + fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(upper_tree, *child_hole)))) + { + child_has_bigger_hole = true; + break; + } + } // end of browsing child's holes. + } // end of browsing childs. + if (!child_has_bigger_hole) + { + // // std::cout << "move " << hole << " as child of " << &node << std::endl; + node.add_child(hole); + to_fill.push_back(hole); + } + } // end of browsing holes of node. + node.elt().holes.clear(); + } // end of browsing lower_tree. + + for(typename std::vector<node_type*>::iterator node_ = to_fill.begin(); + node_ != to_fill.end(); + node_++) + { + node_type& node = **node_; + + fllt_branch_iter_ind(P, V) node_(fllt_branch(P, V)(upper_tree, node)); + for_all(node_) + { + node_type& node = *node_; + if (node.elt().set_id != upper<V>::id) + continue; - return tree_ptr_type(root); + mln_piter(arr_t) hole_p(node.elt().holes); + for_all(hole_p) + { + fllt_node(P, V)* hole; + hole = find_hole<P,V,lower<V> >(node, P(hole_p), low_reg); + + bool child_has_bigger_hole = false; + typename fllt_node(P, V)::children_t::iterator it; + for (it = node.children().begin(); it != node.children().end() && !child_has_bigger_hole; it++) + { + // Browse the holes of each child. + mln_piter(arr_t) q((*it)->elt().holes); + for_all(q) + { + fllt_node(P, V)* child_hole = find_hole<P,V,lower<V> >((**it), point2d(q), low_reg); + //if (hole->elt().points <= child_hole->elt().points) + if (shape_is_included(fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(lower_tree, *hole)), + fllt_branch_iter_ind(P, V)(fllt_branch(P, V)(lower_tree, *child_hole)))) + { + child_has_bigger_hole = true; + break; + } + } // end of browsing child's holes. + } // end of browsing childs. + + if (!child_has_bigger_hole) + node.add_child(hole); + + } // end of browsing holes of node. + node.elt().holes.clear(); + } // end of browsing lower_tree. + + } + + return lower_tree; } template <typename I> @@ -595,19 +794,18 @@ image2d<fllt_node(P, V)*> low_reg(input.domain()); image2d<fllt_node(P, V)*> upp_reg(input.domain()); - std::cout << "1/ Compute the lower level set." << std::endl; + std::cout << "1/ Compute the lower level set.----------------------------------------" << std::endl; lower_tree = level_set<I, lower<V> >(input, low_reg); -// draw_tree(input, lower_tree); + draw_tree(input, lower_tree); - std::cout << "2/ Compute the upper level set." << std::endl; + std::cout << "2/ Compute the upper level set.----------------------------------------" << std::endl; upper_tree = level_set<I, upper<V> >(input, upp_reg); // draw_tree(input, upper_tree); - fllt_tree_ptr(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input); - -// draw_tree(lena, tree); + std::cout << "3/ Merge.---------------------------------------------------------------" << std::endl; + fllt_tree(P, V) result_tree = merge_trees(lower_tree, upper_tree, low_reg, upp_reg, input); -// return fllt_tree(lower_tree); + return result_tree; } template <typename P, typename V> @@ -615,6 +813,8 @@ draw_tree(const image2d<V>& ima, fllt_tree(P, V)& tree) { + p_array<P> tmp; + fllt_branch_iter_ind(P, V) p(tree.main_branch()); for_all(p) { @@ -623,13 +823,22 @@ std::cout << " |" << std::endl; std::cout << "region : " << &*p << " value = " << (*p).elt().value << std::endl + << " from " << ((*p).elt().set_id == lower<V>::id ? "lower" : "upper") << " level set." << std::endl << " npoints = " << (*p).elt().npoints << std::endl << " holes = " << (*p).elt().holes << std::endl; std::cout << std::endl; + tmp.append((*p).elt().points); + + fllt_branch_iter_ind(P, V) n(fllt_branch(P, V)(tree, *p)); + for_all(n) + tmp.append((*n).elt().points); + if ((*p).elt().points.npoints() > 0) - debug::println(ima | (*p).elt().points); + debug::println(ima | tmp); + tmp.clear(); + std::cout << std::endl; } } @@ -647,42 +856,66 @@ typedef fllt_tree(point2d, int_u8) tree_type; - if (argc != 2) - { - std::cerr << "usage: " << argv[0] << " filename" << std::endl; - return 1; - } - image2d<int_u8> lena; - io::pgm::load(lena, argv[1]); + +// if (argc != 2) +// { +// std::cerr << "usage: " << argv[0] << " filename" << std::endl; +// return 1; +// } + +// image2d<int_u8> lena; +// io::pgm::load(lena, argv[1]); // int vs[8][9] = { {0,0,0,0,0,0,0,0,0}, // {0,0,0,0,0,0,0,0,0}, // {0,1,1,1,1,1,1,1,0}, // {0,1,0,0,1,3,3,1,0}, -// {0,1,0,0,1,3,3,1,0}, +// {0,1,0,0,1,3,4,1,0}, // {0,1,0,0,1,3,3,1,0}, // {0,1,1,1,1,1,1,1,0}, // {0,0,0,0,0,0,0,0,0} }; -// image2d<int> lena_(make::image2d(vs)); -// image2d<int_u8> lena(lena_.domain()); -// level::fill(lena, lena_); +// int vs[8][9] = { {2,2,2,2,2,2,2,2,2}, +// {2,2,2,2,2,2,2,2,2}, +// {2,1,1,1,1,1,1,1,2}, +// {2,1,2,2,1,0,0,1,2}, +// {2,1,2,2,1,0,0,1,2}, +// {2,1,2,2,1,0,0,1,2}, +// {2,1,1,1,1,1,1,1,2}, +// {2,2,2,2,2,2,2,2,2} }; + + +// int vs[8][9] = { {2,2,2,2,2,2,2,2,2}, +// {2,2,2,2,2,2,2,2,2}, +// {2,1,1,1,1,1,1,1,2}, +// {2,1,2,2,1,0,0,1,2}, +// {2,1,2,2,1,0,4,1,2}, +// {2,1,2,2,1,0,0,1,2}, +// {2,1,1,1,1,1,1,1,2}, +// {2,2,2,2,2,2,2,2,2} }; + + int vs[10][13] = { {1,1,1,1, 1,1,1,1, 1,1,1,1,1}, + {1,2,2,2,2,2,2,2,2,2,2,2,1}, + {1,2,2,2,2,2,2,2,2,2,2,2,1}, + {1,2,2,2,3,3,3,3,3,3,3,2,1}, + {1,2,2,2,3,3,3,2,2,2,3,2,1}, + {1,2,2,2,3,4,3,2,4,4,3,2,1}, + + {1,2,2,2,3,3,3,2,2,2,3,2,1}, + {1,2,2,2,3,3,3,3,3,3,3,2,1}, + {1,2,2,2,2,2,2,2,2,2,2,2,1}, + {1,1,1,1,1,1,1,1,1,1,1,1,1}}; + + + image2d<int> lena_(make::image2d(vs)); + image2d<int_u8> lena(lena_.domain()); + level::fill(lena, lena_); tree_type tree = my::fllt(lena); + draw_tree(lena, tree); + io::pgm::save(lena, "./out.pgm"); } - -// 16891 99970 -// ./a.out ../../img/lena.pgm 1.17s user 0.06s system 93% cpu 1.318 total -// matt @ ..k/lrde/oln/trunk/milena/sandbox/geraud $ time ./a.out ../../img/lena.pgm 12:50:12 -// 16891 99970 -// ./a.out ../../img/lena.pgm 1.22s user 0.02s system 87% cpu 1.413 total -// matt @ ..k/lrde/oln/trunk/milena/sandbox/geraud $ time ./a.out ../../img/lena.pgm 12:50:16 -// 16891 99970 -// ./a.out ../../img/lena.pgm 1.14s user 0.09s system 92% cpu 1.336 total -// matt @ ..k/lrde/oln/trunk/milena/sandbox/geraud $ time ./a.out ../../img/lena.pgm 12:50:18 -// 16891 99970 -// ./a.out ../../img/lena.pgm 1.20s user 0.04s system 92% cpu 1.329 total
participants (1)
-
Matthieu Garrigues