
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox ChangeLog: 2008-11-26 Matthieu Garrigues <garrigues@lrde.epita.fr> Try an auto dual area filter using TUFA. * garrigues/area_filter_auto_dual.cc: New, the test. --- area_filter_auto_dual.cc | 268 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 268 insertions(+) Index: trunk/milena/sandbox/garrigues/area_filter_auto_dual.cc =================================================================== --- trunk/milena/sandbox/garrigues/area_filter_auto_dual.cc (revision 0) +++ trunk/milena/sandbox/garrigues/area_filter_auto_dual.cc (revision 2952) @@ -0,0 +1,268 @@ +// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory +// (LRDE) +// +// This file is part of the Olena Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License version 2 as published by the +// Free Software Foundation. +// +// This library 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 this library; see the file COPYING. If not, write to +// the Free Software Foundation, 51 Franklin Street, Fifth Floor, +// Boston, MA 02111-1307, USA. +// +// As a special exception, you may use this file as part of a free +// software library 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_AREA_FILTER_HH +# define MLN_AREA_FILTER_HH + +# include <mln/core/image/image2d.hh> +# include <mln/level/fill.hh> +# include <mln/literal/zero.hh> +# include <mln/convert/to_upper_window.hh> +# include <mln/accu/count.hh> +# include <mln/util/pix.hh> + +# include <mln/core/alias/neighb2d.hh> + +# include <mln/io/pbm/save.hh> +# include <mln/io/pbm/load.hh> + +namespace mln +{ + + + template <typename I> + static inline + mln_psite(I) + find_root(I& parent, + const mln_psite(I)& x) + { + if (parent(x) == x) + return x; + else + return parent(x) = find_root(parent, parent(x)); + } + + template <typename I, typename N, typename F, typename O> + void + algebraic_union_find(const Image<I>& input_, + const Neighborhood<N>& nbh_, + F& f, + Image<O>& output_) + { + trace::entering("canvas::morpho::algebraic_union_find"); + + // FIXME: Tests? + + typedef typename F::S S; + typedef typename F::A A; + + const I& input = exact(input_); + const N& nbh = exact(nbh_); + O& output = exact(output_); + + mln_precondition(output.domain() == input.domain()); + + // Local type. + typedef mln_psite(I) P; + + // Auxiliary data. + mln_ch_value(O, bool) deja_vu; + mln_ch_value(O, P) parent; + mln_ch_value(O, A) data; + + // init + { + initialize(deja_vu, input); + mln::level::fill(deja_vu, false); + initialize(parent, input); + initialize(data, input); + f.init(); // init required. + } + + // first pass + { + mln_fwd_piter(I) p(input.domain()); + mln_niter(N) n(nbh, p); + for_all(p) + { + + if (input(p) == true) + // Body for foreground + { + // Make set. + parent(p) = p; + data(p).take_as_init(make::pix(input, p)); + + for_all(n) + if (input.domain().has(n) && input(n) && deja_vu(n)) + { + //do_union(n, p); + P r = find_root(parent, n); + if (r != p) + { + if (input(r) == input(p) || f.is_active(data(r))) // Equiv(r, p) + // Either a flat zone or the component of r is still growing. + { + // p is now the new root. + data(p).take(data(r)); + parent(r) = p; + } + else + // Stop the growing connected component. + f.inactivate(data(p)); + } + } + deja_vu(p) = true; + } + else + // Body for background + { + // Make set. + parent(p) = p; + data(p).take_as_init(make::pix(input, p)); + + for_all(n) + if (input.domain().has(n) && !input(n) && deja_vu(n)) + { + //do_union(n, p); + P r = find_root(parent, n); + if (r != p) + { + if (input(r) == input(p) || f.is_active(data(r))) // Equiv(r, p) + // Either a flat zone or the component of r is still growing. + { + data(p).take(data(r)); + parent(r) = p; + } + else + f.inactivate(data(p)); + } + } + deja_vu(p) = true; + + } + + + } + } + + // second pass + { + mln_bkd_piter(I) p(input.domain()); + for_all(p) + if (input(p)) // Foreground + if (parent(p) == p) + output(p) = !f.is_active(data(p)); + else + output(p) = output(parent(p)); + else // Background. + if (parent(p) == p) + output(p) = f.is_active(data(p)); + else + output(p) = output(parent(p)); + } + + trace::exiting("canvas::morpho::algebraic_union_find"); + } + + + struct area_filter_t + { + // requirements from mln::canvas::morpho::algebraic_union_find + + typedef image2d<bool> I; + typedef util::pix<I> pix_t; + typedef accu::count<pix_t> A; + typedef mln_psite_(I) P; + typedef p_array<P> S; + + mln_result_(A) lambda; + + inline + void init() + { + } + + inline + bool is_active(const A& attr) const + { + return attr.to_result() < lambda; + } + + inline + void inactivate(A& attr) + { + attr.set_value(lambda); + } + + // end of requirements + + inline + area_filter_t(const image2d<bool>& input, mln_result_(A) lambda) + : lambda(lambda) + { + } + + }; + + + + template <typename N> + inline + void area_filter(const image2d<bool>& input, + const Neighborhood<N>& nbh, unsigned lambda, + image2d<bool>& output) + { + typedef area_filter_t F; + F f(input, lambda); + algebraic_union_find(input, nbh, f, output); + } + +} // end of namespace mln + +int main(int argc, char** argv) +{ + using namespace mln; + image2d<bool> input; + + if (argc < 2) + { + std::cerr << "Usage: " << argv[0] << " in.pbm area out.pbm" << std::endl; + return 1; + } + + io::pbm::load(input, argv[1]); + + + image2d<bool> output1(input.domain()); + image2d<bool> output2(input.domain()); + image2d<bool> output3(input.domain()); + image2d<bool> output4(input.domain()); + + area_filter(input, c4(), atoi(argv[2]), output1); + area_filter(output1, c4(), atoi(argv[2]), output2); + area_filter(output2, c4(), atoi(argv[2]), output3); + area_filter(output3, c4(), atoi(argv[2]), output4); + + io::pbm::save(output1, "out1.pgm"); + io::pbm::save(output2, "out2.pgm"); + io::pbm::save(output3, "out3.pgm"); + io::pbm::save(output3, "out4.pgm"); +} + +#endif // ! MLN_AREA_FILTER_HH