1693: Add a computation of the level components.
https://svn.lrde.epita.fr/svn/oln/trunk/milena I've just remembered mln/labeling/level.hh existed, and probably does the same job as the file I'm checking in. I needed it to implement Meyer's Watershed Transfom algorithm, so I'll remove it as soon as I merge both files. Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Add a computation of the level components. * mln/morpho/level_components.hh: New. Imported from Olena proto-1.0. * tests/morpho/level_components.cc: New test. * tests/morpho/Makefile.am (check_PROGRAMS): Add level_components. (level_components_SOURCES): New. mln/morpho/level_components.hh | 138 ++++++++++++++++++++++++++++----------- tests/morpho/Makefile.am | 2 tests/morpho/level_components.cc | 62 +++++++++++++++++ 3 files changed, 166 insertions(+), 36 deletions(-) Index: mln/morpho/level_components.hh --- mln/morpho/level_components.hh (revision 1680) +++ mln/morpho/level_components.hh (working copy) @@ -1,4 +1,4 @@ -// Copyright (C) 2005 EPITA Research and Development Laboratory +// Copyright (C) 2005, 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 @@ -25,62 +25,128 @@ // reasons why the executable file might be covered by the GNU General // Public License. -#ifndef OLENA_MORPHO_LEVEL_COMPONENTS_HH -# define OLENA_MORPHO_LEVEL_COMPONENTS_HH +#ifndef MLN_MORPHO_MORPHO_COMPONENTS_HH +# define MLN_MORPHO_MORPHO_COMPONENTS_HH + +// FIXME: This file seems to contain the same algorithm as +// mln/labeling/level.hh. Merge or remove to avoid duplication. + +// FIXME: Provide neighborhood-aware versions of these algorithms. # include <queue> -# include "oln/level/fill.hh" +# include <mln/trait/value_.hh> +# include <mln/trait/ch_value.hh> + +# include <mln/level/fill.hh> + +# include <mln/morpho/includes.hh> + + +namespace mln { + + namespace morpho { + + /** Compute the level components of \a input. + + \p DestValue is the value type of the output. + + The result is an image where each level component is given a + value between \c mln_value(DestValue) and \c ncomps (the + number of level components). + + \param[in] input The image whose minima are computed. + \param[in] win The window describing the connexity of \a input. + \param[out] ncomps The number of minima found by the algorithm. + \return The image of components -namespace oln { + \pre \p DestValue is large enough to hold a number of values + equal to \c nminima + 1, so as to tag all the minima points + plus the non-minima points. */ + template <typename DestValue, typename I, typename W> + mln_ch_value(I, DestValue) + level_components(const Image<I>& input, const Window<W>& win, + unsigned& ncomps); - namespace level { + /// \brief Like the 3-argument version of mln::moprho::level_components, + /// without the out argument \c ncomps. + template <typename DestValue, typename I, typename W> + mln_ch_value(I, DestValue) + level_components(const Image<I>& input, const Window<W>& win); - /// Compute the level components of \a input. - template <typename DestValue, typename I> - typename ch_value_type<I, DestValue>::ret - level_components(const abstract::image_with_nbh<I>& input) + +# ifndef MLN_INCLUDE_ONLY + + template <typename DestValue, typename I, typename W> + mln_ch_value(I, DestValue) + level_components(const Image<I>& input_, const Window<W>& win_, + unsigned& ncomps) { - mlc_is_a(I, abstract::scalar_valued_image)::ensure(); + /* FIXME: Ensure the input image has scalar values. */ + + /* FIXME: Errors due to a too small DestValue type should be + reported more explicitely. Currently, we abort with messages + akin to this one: + + Assertion failed: + (unsigned(i) <= mln::trait::value_< enc_ >::max()), + function operator=, file ../../../../milena/mln/value/int_u.hh, + line 243. + + This is not user-friendly at all! */ - typename ch_value_type<I, DestValue>::ret labels(input.size(), - input.nbh_get()); - typename ch_value_type<I, bool>::ret processed(input.size(), - input.nbh_get()); + const I& input = exact(input_); + const W& win = exact(win_); + + mln_ch_value(I, DestValue) labels(input.domain()); + mln_ch_value(I, bool) processed(input.domain()); level::fill (processed, false); - DestValue cur_label = ntg_min_val(DestValue); + DestValue cur_label = mln_min(DestValue); - typedef oln_type_of(I, point) point_type; - std::queue<point_type> q; + typedef mln_point(I) point_type; + std::queue<point_type> queue; - oln_type_of(I, piter) p(input.size()); - for_all_p (p) - if (!processed[p]) + mln_piter(I) p(input.domain()); + for_all(p) + if (!processed(p)) { - labels[p] = cur_label; - processed[p] = true; - q.push(p); - while (!q.empty()) + labels(p) = cur_label; + processed(p) = true; + queue.push(p); + while (!queue.empty()) { - point_type s = q.front(); - q.pop(); - oln_type_of(I, niter) n(input); - for_all_n_of_p (n, s) - if (input.hold(n) and !processed[n] and input[n] == input[s]) + point_type s = queue.front(); + queue.pop(); + mln_qiter(W) q(win, s); + for_all(q) + if (input.has(q) and !processed(q) and input(q) == input(s)) { - labels[n] = cur_label; - processed[n] = true; - q.push(n); + labels(q) = cur_label; + processed(q) = true; + queue.push(q); } } ++cur_label; } + // Update ncomps. + ncomps = cur_label; return labels; } - } // end of namespace oln::level + template <typename DestValue, typename I, typename W> + mln_ch_value(I, DestValue) + level_components(const Image<I>& input, const Window<W>& win) + { + // Dummy value. + unsigned ncomps; + return level_components<DestValue>(input, win, ncomps); + } + +# endif // ! MLN_INCLUDE_ONLY + + } // end of namespace mln::morpho -} // end of namespace oln +} // end of namespace mln -#endif // ! OLENA_MORPHO_LEVEL_COMPONENTS_HH +#endif // ! MLN_MORPHO_MORPHO_COMPONENTS_HH Index: tests/morpho/level_components.cc --- tests/morpho/level_components.cc (revision 0) +++ tests/morpho/level_components.cc (revision 0) @@ -0,0 +1,62 @@ +// Copyright (C) 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. + +/// \file tests/morpho/level_components.cc +// /\brief Test on mln::morpho::level_components + +#include <iostream> + +#include <mln/core/image2d.hh> +#include <mln/core/window2d.hh> +#include <mln/core/neighb2d.hh> + +#include <mln/convert/to_window.hh> + +#include <mln/value/int_u8.hh> + +#include <mln/morpho/level_components.hh> + +#include <mln/io/pgm/load.hh> +#include <mln/io/pgm/save.hh> + +#include "tests/data.hh" + + +int main() +{ + using namespace mln; + using value::int_u8; + + image2d<int_u8> input; + io::pgm::load(input, MLN_IMG_DIR "/squares.pgm"); + unsigned ncomps; + // FIXME: Do we really need to use a neighborood to express a 4-c window? + image2d<int_u8> output = + morpho::level_components<int_u8>(input, convert::to_window(c4()), ncomps); + std::cout << "ncomps = " << ncomps << std::endl; + io::pgm::save(output, "out.pgm"); +} Index: tests/morpho/Makefile.am --- tests/morpho/Makefile.am (revision 1692) +++ tests/morpho/Makefile.am (working copy) @@ -11,6 +11,7 @@ gradient \ hit_or_miss \ laplacian \ + level_components \ opening_area \ thinning @@ -22,6 +23,7 @@ gradient_SOURCES = gradient.cc hit_or_miss_SOURCES = hit_or_miss.cc laplacian_SOURCES = laplacian.cc +level_components_SOURCES = level_components.cc opening_area_SOURCES = opening_area.cc thinning_SOURCES = thinning.cc
participants (1)
-
Roland Levillain