https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add Meyer's Watershed Transform algorithm.
* mln/util/greater_point.hh: New.
A ``greater than'' functor comparing points w.r.t. the
values they refer to in an image.
* mln/morpho/meyer_wst.hh: New.
Meyer's Watershed Transform algorithm.
* tests/morpho/meyer_wst.cc: New tests.
mln/morpho/meyer_wst.hh | 169 ++++++++++++++++++++++++++++++++++++++++++++++
mln/util/greater_point.hh | 95 +++++++++++++++++++++++++
tests/morpho/meyer_wst.cc | 65 +++++++++++++++++
3 files changed, 329 insertions(+)
Index: mln/util/greater_point.hh
--- mln/util/greater_point.hh (revision 0)
+++ mln/util/greater_point.hh (revision 0)
@@ -0,0 +1,95 @@
+// 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
+// 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, 59 Temple Place - Suite 330, 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_UTIL_GREATER_POINT_HH
+# define MLN_UTIL_GREATER_POINT_HH
+
+# include <mln/core/concept/image.hh>
+
+
+namespace mln {
+
+ namespace util {
+
+ /** \brief A ``greater than'' functor comparing points w.r.t. the
+ values they refer to in an image.
+
+ This functor used in useful to implement ordered queues of
+ points. */
+ template <typename I>
+ class greater_point
+ {
+ public:
+ typedef mln_point(I) point;
+
+ greater_point(const Image<I>& ima);
+
+ /// Is \a x greater than \a y?
+ bool operator()(const point& x, const point& y);
+
+ private:
+ const I& ima_;
+ };
+
+
+ /// Helper to build a mln::util::greater_point.
+ /* FIXME: To be moved into mln/make/? */
+ template <typename I>
+ greater_point<I>
+ make_greater_point(const Image<I>& ima);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ greater_point<I>::greater_point(const Image<I>& ima)
+ : ima_ (exact(ima))
+ {
+ }
+
+ template <typename I>
+ bool
+ greater_point<I>::operator()(const mln_point(I)& x, const mln_point(I)& y)
+ {
+ return ima_(x) > ima_(y);
+ }
+
+
+ template <typename I>
+ greater_point<I>
+ make_greater_point(const Image<I>& ima)
+ {
+ return greater_point<I>(ima);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::util
+
+} // end of namespace mln
+
+#endif // ! MLN_UTIL_GREATER_POINT_HH
Index: mln/morpho/meyer_wst.hh
--- mln/morpho/meyer_wst.hh (revision 0)
+++ mln/morpho/meyer_wst.hh (revision 0)
@@ -0,0 +1,169 @@
+// 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.
+
+#ifndef MLN_MORPHO_MEYER_WST_HH
+# define MLN_MORPHO_MEYER_WST_HH
+
+/** \file mln/morpho/meyer_wst.hh
+ \brief Meyer's Watershed Transform (WST) algorithm.
+
+ The Watershed Transform algorithm from Meyer using a hierarchical
+ queue.
+
+ Reference:
+ Fernand Meyer. Un algorithme optimal de ligne de partage des
+ eaux. In: Actes du 8�me Congr�s AFCET, Lyon-Villeurbanne, France
+ (1991), pages 847--859. */
+
+# include <queue>
+
+# include <mln/trait/ch_value.hh>
+
+# include <mln/util/greater_point.hh>
+# include <mln/morpho/includes.hh>
+# include <mln/morpho/extrema_components.hh>
+
+
+namespace mln
+{
+
+ namespace morpho
+ {
+ /* FIXME: Provide also a version of the algorithm taking an image
+ of minima as input. */
+
+ /* FIXME: See also the interface of the Shortest-Path Watershed
+ Transform, which proposes to lower-complete the image before
+ processing it. Then, add a reference to
+ mln/morpho/lower_completion.hh. */
+
+ /* FIXME: More doc. */
+
+ /// Meyer's Watershed Transform (WST) algorithm.
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ meyer_wst(const Image<I>& input, const Window<W>& win, unsigned& nbasins);
+
+ /// Meyer's Watershed Transform (WST) algorithm, with no count of
+ /// basins.
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ meyer_wst(const Image<I>& input, const Window<W>& win);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ meyer_wst(const Image<I>& input, const Window<W>& win, unsigned& nbasins)
+ {
+ /* FIXME: Ensure the input image has scalar values. */
+
+ typedef DestValue marker;
+ const marker unmarked = mln_min(marker);
+
+ // Initialize the output with the markers (minima components).
+ mln_ch_value(I, marker) markers =
+ minima_components<marker>(input, win, nbasins);
+
+ // Ordered queue.
+ typedef mln_point(I) point;
+ typedef
+ std::priority_queue< point, std::vector<point>, util::greater_point<I> >
+ ordered_queue_type;
+ ordered_queue_type queue(util::make_greater_point(input));
+
+ // Insert every neighbor P of every marked area in a
+ // hierarchical queue, with a priority level corresponding to
+ // the grey level input(P).
+ mln_piter(I) p(markers.domain());
+ mln_qiter(W) q(win, p);
+ for_all (p)
+ if (markers(p) == unmarked)
+ for_all(q)
+ if (markers.has(q) && markers(q) != unmarked)
+ {
+ queue.push(p);
+ break;
+ }
+
+ /* Until the queue is empty, extract a point P from the
+ hierarchical queue, at the highest priority level, that is,
+ the lowest level. */
+ while (!queue.empty())
+ {
+ point p = queue.top();
+ queue.pop();
+ // Last seen marker adjacent to P.
+ marker adjacent_marker = unmarked;
+ // Has P a single adjacent marker?
+ bool single_adjacent_marker_p = true;
+ mln_qiter(W) q(win, p);
+ for_all(q)
+ if (markers.has(q) && markers(q) != unmarked)
+ if (adjacent_marker == unmarked)
+ {
+ adjacent_marker = markers(q);
+ single_adjacent_marker_p = true;
+ }
+ else
+ if (adjacent_marker != markers(q))
+ {
+ single_adjacent_marker_p = false;
+ break;
+ }
+ /* If the neighborhood of P contains only points with the
+ same label, then P is marked with this label, and its
+ neighbors that are not yet marked are put into the
+ hierarchical queue. */
+ if (single_adjacent_marker_p)
+ {
+ markers(p) = adjacent_marker;
+ for_all(q)
+ if (markers.has(q) && markers(q) == unmarked)
+ queue.push(q);
+ }
+ }
+ return markers;
+ }
+
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ meyer_wst(const Image<I>& input, const Window<W>& win)
+ {
+ unsigned nbasins;
+ return meyer_wst<DestValue>(input, nbasins);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MORPHO_MEYER_WST_HH
Index: tests/morpho/meyer_wst.cc
--- tests/morpho/meyer_wst.cc (revision 0)
+++ tests/morpho/meyer_wst.cc (revision 0)
@@ -0,0 +1,65 @@
+// 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/extrema_components.cc
+// /\brief Test on mln::morpho::extrema_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/meyer_wst.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");
+
+ typedef int_u8 output_val;
+
+ unsigned nbasins;
+ // FIXME: Do we really need to use a neighborood to express a 4-c window?
+ image2d<int_u8> output =
+ morpho::meyer_wst<output_val>(input, convert::to_window(c4()), nbasins);
+ std::cout << "nbasins = " << nbasins << std::endl;
+ io::pgm::save(output, "out.pgm");
+}
https://svn.lrde.epita.fr/svn/oln/trunk/milena
(Same remark as my previous patch.)
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add a computation of the extrema level components.
* mln/morpho/extrema_components.hh: New.
Imported from Olena proto-1.0.
* tests/morpho/extrema_components.cc: New test.
* tests/morpho/Makefile.am (check_PROGRAMS): Add extrema_components.
(extrema_components_SOURCES): New.
* img/squares.pgm, img/squares-lc.pgm: New images.
mln/morpho/extrema_components.hh | 229 ++++++++++++++++++++++++++++---------
tests/morpho/Makefile.am | 2
tests/morpho/extrema_components.cc | 69 +++++++++++
3 files changed, 247 insertions(+), 53 deletions(-)
Index: mln/morpho/extrema_components.hh
--- mln/morpho/extrema_components.hh (revision 1680)
+++ mln/morpho/extrema_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,51 +25,152 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef OLENA_MORPHO_EXTREMA_COMPONENTS_HH
-# define OLENA_MORPHO_EXTREMA_COMPONENTS_HH
+#ifndef MLN_MORPHO_EXTREMA_COMPONENTS_HH
+# define MLN_MORPHO_EXTREMA_COMPONENTS_HH
+
+// FIXME: This file seems to contain the same algorithm as
+// mln/labeling/regional_minima.hh and
+// mln/labeling/regional_maxima.hh. Merge or remove to avoid
+// duplication.
+
+// FIXME: Provide neighborhood-aware versions of these algorithms.
# include <map>
# include <queue>
# include <functional>
-# include "oln/level/level_components.hh"
+# include <mln/trait/ch_value.hh>
+
+# include <mln/level/fill.hh>
+
+# include <mln/morpho/includes.hh>
+# include <mln/morpho/level_components.hh>
+
+
+namespace mln {
+
+ namespace morpho {
+
+ /*--------------------------.
+ | Minima level components. |
+ `--------------------------*/
+
+ /** \brief Compute the minima level components of \a input.
+
+ \p DestValue is the value type of the output.
+
+ The result is an image where each minima is given a value
+ between \c mln_value(DestValue) + 1 and \c nminima (the number
+ of minima level components). Points which do not belong to a
+ minimum are gien the value mln_value(DestValue).
+
+ \param[in] input The image whose minima are computed.
+ \param[in] win The window describing the connexity of \a input.
+ \param[out] nminima The number of minima found by the algorithm.
+ \return The image of minima.
+
+ \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)
+ minima_components(const Image<I>& input, const Window<W>& win,
+ unsigned& nminima);
+
+ /// \brief Like the 3-argument version of mln::moprho::minima_components,
+ /// without the out argument \c nminima.
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ minima_components(const Image<I>& input, const Window<W>& win);
+
+
+ /*--------------------------.
+ | Maxima level components. |
+ `--------------------------*/
+
+ /** \brief Compute the maxima level components of \a input.
+
+ \p DestValue is the value type of the output.
+
+ The result is an image where each maxima is given a value
+ between \c mln_value(DestValue) + 1 and \c nmaxima (the number
+ of maxima level components). Points which do not belong to a
+ maximum are gien the value mln_value(DestValue).
+
+ \param[in] input The image whose maxima are computed.
+ \param[in] win The window describing the connexity of \a input.
+ \param[out] nmaxima The number of maxima found by the algorithm.
+ \return The image of maxima.
-namespace oln {
+ \pre \p DestValue is large enough to hold a number of values
+ equal to \c nmaxima + 1, so as to tag all the maxima points
+ plus the non-maxima points. */
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ maxima_components(const Image<I>& input, const Window<W>& win,
+ unsigned& nmaxima);
- namespace level {
+ /// \brief Like the 3-argument version of mln::moprho::maxima_components,
+ /// without the out argument \c nmaxima.
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ maxima_components(const Image<I>& input, const Window<W>& win);
- namespace internal {
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl {
/// Find the extrema level components of \a input, using \param
/// Cmp as comparison function.
- template <typename DestValue, typename Cmp, typename I>
- typename ch_value_type<I, DestValue>::ret
- extrema_components(const abstract::image_with_nbh<I>& input)
+ template <typename DestValue, typename Cmp, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ extrema_components(const Image<I>& input_, const Window<W>& win_,
+ unsigned& nextrema)
{
- mlc_is_a(I, abstract::scalar_valued_image)::ensure();
+
+ /* 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! */
+
+ const I& input = exact(input_);
+ const W& win = exact(win_);
+
+ // Instantiate a comparison functor.
Cmp cmp;
// Compute level components.
- typedef ntg_cumul_type(DestValue) cumul_type;
+ /* FIXME: Should we deduce cumul_type from DestValue? Or
+ stick to unsigned? */
+ typedef unsigned cumul_type;
typedef cumul_type comp_type;
- typename ch_value_type<I, comp_type>::ret comps =
- level_components<comp_type>(input);
+ mln_ch_value(I, comp_type) comps =
+ level_components<comp_type>(input, win);
+ /* FIXME: Does Milena provide better data structures to
+ store this information? */
std::set<comp_type> extrema;
std::set<comp_type> non_extrema;
// Search extrema components.
- oln_type_of(I, piter) p(input.size());
- for_all_p (p)
+ mln_piter(I) p(input.domain());
+ for_all(p)
{
- comp_type comp = comps[p];
+ comp_type comp = comps(p);
if (non_extrema.find(comp) == non_extrema.end())
{
// A new level is a (potential) extrema by default.
extrema.insert(comp);
- oln_type_of(I, niter) n(input);
- for_all_n_of_p (n, p)
- if (input.hold(n) and cmp(input[n], input[p]))
+ mln_qiter(W) q(win, p);
+ for_all(q)
+ if (input.has(q) and cmp(input(q), input(p)))
{
extrema.erase(comp);
non_extrema.insert(comp);
@@ -78,57 +179,79 @@
}
}
+ // Update nextrema.
+ nextrema = extrema.size();
+
// Re-label the extrema. label_map hold the assigned labels.
std::map<comp_type, DestValue> label_map;
{
- DestValue cur_label = ntg_min_val(DestValue) + 1;
- for (typename std::set<comp_type>::const_iterator i =
- extrema.begin(); i != extrema.end(); ++i, ++cur_label)
- {
+ DestValue cur_label = mln_min(DestValue) + 1;
+ for (typename std::set<comp_type>::const_iterator i = extrema.begin();
+ i != extrema.end();
+ ++i, ++cur_label)
label_map[*i] = cur_label;
}
- }
- typename ch_value_type<I, DestValue>::ret output (input.size(),
- input.nbh_get());
- level::fill (output, ntg_min_val(DestValue));
- for_all_p (p)
+ mln_ch_value(I, DestValue) output (input.domain());
+ level::fill (output, mln_min(DestValue));
+ for_all(p)
{
- comp_type comp = comps[p];
+ comp_type comp = comps(p);
if (label_map.find(comp) != label_map.end())
- output[p] = label_map[comp];
+ output(p) = label_map[comp];
}
return output;
}
- } // end of namespace oln::level::internal.
+ } // end of namespace mln::morpho::impl.
- /// Find the minima level components of \a input.
- template <typename DestValue, typename I>
- typename ch_value_type<I, DestValue>::ret
- minima_components(const abstract::image_with_nbh<I>& input)
+ /*----------.
+ | Facades. |
+ `----------*/
+
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ minima_components(const Image<I>& input, const Window<W>& win,
+ unsigned& nminima)
{
- mlc_is_a(I, abstract::scalar_valued_image)::ensure();
- typedef oln_type_of(I, value) input_value_type;
- return
- internal::extrema_components< DestValue,
- std::less<input_value_type> >(input);
+ /* FIXME: Ensure the input image has scalar values. */
+ typedef std::less< mln_value(I) > cmp_t;
+ return impl::extrema_components<DestValue, cmp_t>(input, win, nminima);
}
- /// Find the maxima level components of \a input.
- template <typename DestValue, typename I>
- typename ch_value_type<I, DestValue>::ret
- maxima_components(const abstract::image_with_nbh<I>& input)
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ minima_components(const Image<I>& input, const Window<W>& win)
+ {
+ // Dummy value.
+ unsigned nminima;
+ return minima_components<DestValue>(input, win, nminima);
+ }
+
+
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ maxima_components(const Image<I>& input, const Window<W>& win,
+ unsigned& nmaxima)
{
- mlc_is_a(I, abstract::scalar_valued_image)::ensure();
- typedef oln_type_of(I, value) input_value_type;
- return
- internal::extrema_components< DestValue,
- std::greater<input_value_type> >(input);
+ /* FIXME: Ensure the input image has scalar values. */
+ typedef std::greater< mln_value(I) > cmp_t;
+ return impl::extrema_components<DestValue, cmp_t>(input, win, nmaxima);
}
- } // end of namespace oln::level.
+ template <typename DestValue, typename I, typename W>
+ mln_ch_value(I, DestValue)
+ maxima_components(const Image<I>& input, const Window<W>& win)
+ {
+ // Dummy value.
+ unsigned nmaxima;
+ return maxima_components<DestValue>(input, win, nmaxima);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::morpho.
-} // end of namespace oln.
+} // end of namespace mln.
-#endif // ! OLENA_MORPHO_EXTREMA_COMPONENTS_HH
+#endif // ! MLN_MORPHO_EXTREMA_COMPONENTS_HH
Index: tests/morpho/extrema_components.cc
--- tests/morpho/extrema_components.cc (revision 0)
+++ tests/morpho/extrema_components.cc (revision 0)
@@ -0,0 +1,69 @@
+// 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/extrema_components.cc
+// /\brief Test on mln::morpho::extrema_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/extrema_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 nminima;
+ // FIXME: Do we really need to use a neighborood to express a 4-c window?
+ image2d<int_u8> minima =
+ morpho::minima_components<int_u8>(input, convert::to_window(c4()), nminima);
+ std::cout << "nminima = " << nminima << std::endl;
+ io::pgm::save(minima, "minima.pgm");
+
+ unsigned nmaxima;
+ image2d<int_u8> maxima =
+ morpho::maxima_components<int_u8>(input, convert::to_window(c4()), nmaxima);
+ std::cout << "nmaxima = " << nmaxima << std::endl;
+ io::pgm::save(maxima, "maxima.pgm");
+}
Index: tests/morpho/Makefile.am
--- tests/morpho/Makefile.am (revision 1693)
+++ tests/morpho/Makefile.am (working copy)
@@ -8,6 +8,7 @@
dilation_max_h \
erosion \
erosion_min_h \
+ extrema_components \
gradient \
hit_or_miss \
laplacian \
@@ -20,6 +21,7 @@
dilation_max_h_SOURCES = dilation_max_h.cc
erosion_SOURCES = erosion.cc
erosion_min_h_SOURCES = erosion_min_h.cc
+extrema_components_SOURCES = extrema_components.cc
gradient_SOURCES = gradient.cc
hit_or_miss_SOURCES = hit_or_miss.cc
laplacian_SOURCES = laplacian.cc
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(a)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
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2008-01-25 Matthieu Garrigues <garrigues(a)lrde.epita.fr>
* tests/level/replace.cc: Fix licence in replace.cc.
---
replace.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Index: trunk/milena/tests/level/replace.cc
===================================================================
--- trunk/milena/tests/level/replace.cc (revision 1683)
+++ trunk/milena/tests/level/replace.cc (revision 1684)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Miscellaneous corrections in documentation and aesthetics changes.
* mln/core/macros.hh: Use Doxygen delimiters to document pairs of
macros.
* mln/value/stack.hh: Wrap long lines.
Fix Doxygen comments.
* mln/border/get.hh: Fix header inclusions.
Fix Doxygen comments.
* tests/stack.cc: Don't include unnecessary files.
mln/border/get.hh | 9 +--
mln/core/concept/README | 2
mln/core/macros.hh | 142 ++++++++++++++++++++++++++++++++++--------------
mln/core/neighb2d.hh | 2
mln/value/stack.hh | 13 +++-
tests/stack.cc | 4 -
6 files changed, 119 insertions(+), 53 deletions(-)
Index: mln/core/macros.hh
--- mln/core/macros.hh (revision 1689)
+++ mln/core/macros.hh (working copy)
@@ -36,186 +36,246 @@
// a
-/// Shortcut to access the argument type associated to T.
+/// Shortcuts to access the argument type associated to T.
+/// \{
# define mln_argument(T) typename T::argument
# define mln_argument_(T) T::argument
+/// \}
// b
-/// Shortcut to access the bkd_niter type associated to T.
+/// Shortcuts to access the bkd_niter type associated to T.
+/// \{
# define mln_bkd_niter(T) typename T::bkd_niter
# define mln_bkd_niter_(T) T::bkd_niter
+/// \}
-/// Shortcut to access the bkd_piter type associated to T.
+/// Shortcuts to access the bkd_piter type associated to T.
+/// \{
# define mln_bkd_piter(T) typename T::bkd_piter
# define mln_bkd_piter_(T) T::bkd_piter
+/// \}
-/// Shortcut to access the bkd_qiter type associated to T.
+/// Shortcuts to access the bkd_qiter type associated to T.
+/// \{
# define mln_bkd_qiter(T) typename T::bkd_qiter
# define mln_bkd_qiter_(T) T::bkd_qiter
+/// \}
-/// Shortcut to access the bkd_viter type associated to T.
+/// Shortcuts to access the bkd_viter type associated to T.
+/// \{
# define mln_bkd_viter(T) typename T::bkd_viter
# define mln_bkd_viter_(T) T::bkd_viter
+/// \}
-/// Shortcut to access the box type associated to T.
+/// Shortcuts to access the box type associated to T.
+/// \{
# define mln_box(T) typename T::box
# define mln_box_(T) T::box
+/// \}
// c
-/// Shortcut to access the coord type associated to T.
+/// Shortcuts to access the coord type associated to T.
+/// \{
# define mln_coord(T) typename T::coord
# define mln_coord_(T) T::coord
+/// \}
// d
-/// Shortcut to access the dpoint type associated to T.
+/// Shortcuts to access the dpoint type associated to T.
+/// \{
# define mln_dpoint(T) typename T::dpoint
# define mln_dpoint_(T) T::dpoint
+/// \}
// e
-/// Shortcut to access the encoding type associated to T.
+/// Shortcuts to access the encoding type associated to T.
+/// \{
# define mln_enc(T) typename T::enc
# define mln_enc_(T) T::enc
+/// \}
-/// Shortcut to access the equivalent type associated to T.
+/// Shortcuts to access the equivalent type associated to T.
+/// \{
# define mln_equiv(T) typename T::equiv
# define mln_equiv_(T) T::equiv
+/// \}
// f
-/// Shortcut to access the fwd_niter type associated to T.
+/// Shortcuts to access the fwd_niter type associated to T.
+/// \{
# define mln_fwd_niter(T) typename T::fwd_niter
# define mln_fwd_niter_(T) T::fwd_niter
+/// \}
-/// Shortcut to access the fwd_piter type associated to T.
+/// Shortcuts to access the fwd_piter type associated to T.
+/// \{
# define mln_fwd_piter(T) typename T::fwd_piter
# define mln_fwd_piter_(T) T::fwd_piter
+/// \}
-/// Shortcut to access the fwd_qiter type associated to T.
+/// Shortcuts to access the fwd_qiter type associated to T.
+/// \{
# define mln_fwd_qiter(T) typename T::fwd_qiter
# define mln_fwd_qiter_(T) T::fwd_qiter
+/// \}
-/// Shortcut to access the fwd_viter type associated to T.
+/// Shortcuts to access the fwd_viter type associated to T.
+/// \{
# define mln_fwd_viter(T) typename T::fwd_viter
# define mln_fwd_viter_(T) T::fwd_viter
+/// \}
// i
-/// Shortcut to access the image type associated to T.
+/// Shortcuts to access the image type associated to T.
+/// \{
# define mln_image(T) typename T::image
# define mln_image_(T) T::image
+/// \}
-/// Shortcut to access the invert type associated to T.
+/// Shortcuts to access the invert type associated to T.
+/// \{
# define mln_invert(T) typename T::invert
# define mln_invert_(T) T::invert
+/// \}
// l
-
-/// Shortcut to access the lvalue type associated to T.
+/// Shortcuts to access the lvalue type associated to T.
+/// \{
# define mln_lvalue(T) typename T::lvalue
# define mln_lvalue_(T) T::lvalue
+/// \}
// m
-/// Shortcut to access the mesh type associated to T.
+/// Shortcuts to access the mesh type associated to T.
+/// \{
# define mln_mesh(T) typename T::mesh
# define mln_mesh_(T) T::mesh
-
-
-// n
-
-/// Shortcut to access the neighborhood type associated to T.
-# define mln_neighb(T) typename T::neighb
-# define mln_neighb_(T) T::neighb
+/// \}
// p
-/// Shortcut to access the type of point iterator (piter) associated to T.
+/// Shortcuts to access the type of point iterator (piter) associated to T.
+/// \{
# define mln_piter(T) typename T::fwd_piter
# define mln_piter_(T) T::fwd_piter
+/// \}
-/// Shortcut to access the type of point by line iterator (line_piter) associated to T.
+/// Shortcuts to access the type of point by line iterator
+/// (line_piter) associated to T.
+/// \{
# define mln_line_piter(T) typename T::line_piter
# define mln_line_piter_(T) T::line_piter
+/// \}
-/// Shortcut to access the type of point set (pset) associated to T.
+/// Shortcuts to access the type of point set (pset) associated to T.
+/// \{
# define mln_pset(T) typename T::pset
# define mln_pset_(T) T::pset
+/// \}
-/// Shortcut to access the type of point site (psite) associated to T.
+/// Shortcuts to access the type of point site (psite) associated to T.
+/// \{
# define mln_psite(T) typename T::psite
# define mln_psite_(T) T::psite
+/// \}
-/// Shortcut to access the point type associated to T.
+/// Shortcuts to access the point type associated to T.
+/// \{
# define mln_point(T) typename T::point
# define mln_point_(T) T::point
+/// \}
// q
-/// Shortcut to access the qualified (const or mutable) value type associated to T.
+/// Shortcuts to access the qualified (const or mutable) value type
+/// associated to T.
+/// \{
# define mln_qlf_value(T) typename mln::trait::qlf_value< T >::ret
# define mln_qlf_value_(T) mln::trait::qlf_value< T >::ret
+/// \}
-/// Shortcut to access the qiter type associated to T.
+/// Shortcuts to access the qiter type associated to T.
+/// \{
# define mln_qiter(T) typename T::fwd_qiter
# define mln_qiter_(T) T::fwd_qiter
+/// \}
// n
-/// Shortcut to access the niter type associated to T.
+/// Shortcuts to access the niter type associated to T.
+/// \{
# define mln_niter(T) typename T::fwd_niter
# define mln_niter_(T) T::fwd_niter
+/// \}
// r
-/// Shortcut to access the result type associated to T.
+/// Shortcuts to access the result type associated to T.
+/// \{
# define mln_result(T) typename T::result
# define mln_result_(T) T::result
+/// \}
-/// Shortcut to access the rvalue type associated to T.
+/// Shortcuts to access the rvalue type associated to T.
+/// \{
# define mln_rvalue(T) typename T::rvalue
# define mln_rvalue_(T) T::rvalue
+/// \}
// v
-/// Shortcut to access the value type associated to T.
+/// Shortcuts to access the value type associated to T.
+/// \{
# define mln_value(T) typename T::value
# define mln_value_(T) T::value
+/// \}
-/// Shortcut to access the type of value set (vset) associated to T.
+/// Shortcuts to access the type of value set (vset) associated to T.
+/// \{
# define mln_vset(T) typename T::vset
# define mln_vset_(T) T::vset
+/// \}
-/// Shortcut to access the viter type associated to T.
+/// Shortcuts to access the viter type associated to T.
+/// \{
# define mln_viter(T) typename T::fwd_viter
# define mln_viter_(T) T::fwd_viter
+/// \}
// w
-/// Shortcut to access the weight type associated to T.
+/// Shortcuts to access the weight type associated to T.
+/// \{
# define mln_weight(T) typename T::weight
# define mln_weight_(T) T::weight
+/// \}
-/// Shortcut to access the window type associated to T.
+/// Shortcuts to access the window type associated to T.
+/// \{
# define mln_window(T) typename T::window
# define mln_window_(T) T::window
+/// \}
Index: mln/value/stack.hh
--- mln/value/stack.hh (revision 1689)
+++ mln/value/stack.hh (working copy)
@@ -131,8 +131,10 @@
namespace value
{
- /*! \brief stack image class. stack_image stores a
- * vector of n images of the same domain.
+ /*! \brief Stack image class.
+ *
+ * mln::value::stack_image stores a vector of n images of the same
+ * domain.
*
* The parameter \c n is the number of images, \c I is the type of
* a stack element. Acces a value will compute a vector which
@@ -143,7 +145,8 @@
* stack[n](p)]
*/
template <unsigned n, typename I>
- struct stack_image : public mln::internal::image_value_morpher_< I, stack_image<n,I> >
+ struct stack_image
+ : public mln::internal::image_value_morpher_< I, stack_image<n,I> >
{
/// Point_Site associated type.
typedef mln_psite(I) psite;
@@ -168,9 +171,11 @@
typedef stack_image< n, tag::image_<I> > skeleton;
- /// Constructor.
+ /// Constructors.
+ /// \{
stack_image(const metal::vec<n,I>& imas);
stack_image();
+ /// \}
/// Test if this image has been initialized.
Index: mln/border/get.hh
--- mln/border/get.hh (revision 1689)
+++ mln/border/get.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// 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
@@ -33,7 +33,7 @@
* \brief Define function that returns the real border thickness of image.
*/
-# include <mln/border/find.hh>
+# include <mln/trait/images.hh>
namespace mln
@@ -42,13 +42,12 @@
namespace border
{
- /*! Get the virtual (outer) border thickness of image \p ima.
+ /*! Get the virtual (outer) border thickness of image \a ima.
*
* \param[in] ima The image.
* \result The border thickness (0 if there is no border).
*
- * \pre \p ima has to be initialized.
- *
+ * \pre \a ima has to be initialized.
*/
template <typename I>
unsigned get(const Image<I>& ima);
Index: tests/stack.cc
--- tests/stack.cc (revision 1689)
+++ tests/stack.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// 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
@@ -32,8 +32,6 @@
#include <mln/core/image2d.hh>
#include <mln/value/stack.hh>
-#include <mln/debug/iota.hh>
-#include <mln/debug/println.hh>
int main()
Index: mln/core/neighb2d.hh
--- mln/core/neighb2d.hh (revision 1689)
+++ mln/core/neighb2d.hh (working copy)
@@ -98,6 +98,8 @@
inline
const neighb2d& c4()
{
+ // FIXME: `flower' is probably not a canonical name to state
+ // whether the neighborhood is initialized or not. :)
static bool flower = true;
static neighb2d it;
if (flower)
Index: mln/core/concept/README
--- mln/core/concept/README (revision 1689)
+++ mln/core/concept/README (working copy)
@@ -5,6 +5,8 @@
concept files themselves, but we'd like a kind of centralized summary
too. An index would be nice.
+See what Doxygen's \page provides.
+
* Image
Images are functions mapping point sites from a given domain (point
site set) to a value.
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Adjust the morphological dilation w.r.t. a neighborhood.
* mln/morpho/includes.hh: Include mln/metal/has_neighborhood.hh.
* mln/morpho/dilation.hh: Remove dead code.
(dilation(const Image<I>&, Image<O>&)): Update preconditions.
Fix delegation to mln::morpho::impl::dilation_wrt_nbh.
* tests/morpho/dilation.cc: Peform tests using neighborhoods.
Use smaller structural elemements to speed up tests.
mln/morpho/dilation.hh | 84 +++++++++++++++--------------------------------
mln/morpho/includes.hh | 2 +
tests/morpho/dilation.cc | 26 ++++++++++----
3 files changed, 48 insertions(+), 64 deletions(-)
Index: mln/morpho/includes.hh
--- mln/morpho/includes.hh (revision 1687)
+++ mln/morpho/includes.hh (working copy)
@@ -38,6 +38,8 @@
# include <mln/core/concept/window.hh>
# include <mln/core/concept/neighborhood.hh>
+# include <mln/metal/has_neighborhood.hh>
+
# include <mln/value/ops.hh>
# include <mln/accu/min.hh>
Index: mln/morpho/dilation.hh
--- mln/morpho/dilation.hh (revision 1687)
+++ mln/morpho/dilation.hh (working copy)
@@ -92,32 +92,6 @@
namespace impl
{
- /*---------------------.
- | Neighborhood-based. |
- `---------------------*/
-
- /* FIXME: We might want to move this function into the body of
- the facade (see at the bottom of the file. */
- // Sole case. Convert the neighborhood into a window, and
- // delegate to the window-based implementation.
- template <typename I, typename N, typename O>
- inline
- void dilation_wrt_nbh(const Image<I>& input,
- const Neighborhood<N>& nbh,
- Image<O>& output)
- {
- /* FIXME: The following comment applies to every algorithm
- having a neighborhood and a window flavor: move it
- elsewhere.
-
- We solely depend on the neighborhood-to-window conversion
- here. This means the conversion should be smart enough to
- produce a working window, even in the case of a non
- dpoint-set-based neighborhood. */
- dilation_wrt_win(input, to_window(nbh), output);
- }
-
-
/*---------------.
| Window-based. |
`---------------*/
@@ -171,24 +145,6 @@
}
}
- // FIXME: Seems to be duplicate code!
-
-// /// Stage 1: dispatch w.r.t. the window type.
-// /// \{
-
-// /// Default case.
-// template <typename I, typename W, typename O>
-// inline
-// void dilation_wrt_win(const Image<I>& input, const Window<W>& win,
-// Image<O>& output)
-// {
-// // Perform stage 2: dispatch w.r.t. the value kind.
-// dilation_wrt_value(mln_trait_image_kind(I)(), exact(input),
-// exact(win), output);
-// }
-
- // ...
-
// ------------- //
// Dispatchers. //
@@ -284,6 +240,31 @@
/// \}
+
+ /*---------------------.
+ | Neighborhood-based. |
+ `---------------------*/
+
+ /* FIXME: We might want to move this function into the body of
+ the facade (see at the bottom of the file. */
+ // Sole case. Convert the neighborhood into a window, and
+ // delegate to the window-based implementation.
+ template <typename I, typename N, typename O>
+ inline
+ void dilation_wrt_nbh(const Image<I>& input, const Neighborhood<N>& nbh,
+ Image<O>& output)
+ {
+ /* FIXME: The following comment applies to every algorithm
+ having a neighborhood and a window flavor: move it
+ elsewhere.
+
+ We solely depend on the neighborhood-to-window conversion
+ here. This means the conversion should be smart enough to
+ produce a working window, even in the case of a non
+ dpoint-set-based neighborhood. */
+ dilation_wrt_win(input, convert::to_window(nbh), output);
+ }
+
} // end of namespace mln::morpho::impl
@@ -301,22 +282,13 @@
{
trace::entering("morpho::dilation");
+ metal::has_neighborhood<I>::check();
+
mln_precondition(exact(output).domain() == exact(input).domain());
- // Ensure the image has a `neighb' typedef.
typedef mln_neighb(I) neighb;
- // FIXME: Encapsulate this in a class + a macro.
- // FIXME: Do we have better concept checking tools?
- {
- // Ensure the image has a `neighb' method.
- neighb (I::*m)() const = &I::neighb;
- m = 0;
-
- // FIXME: Do we need to check for more?
- }
-
- impl::dilation_wrt_nbh(input, output);
+ impl::dilation_wrt_nbh(input, exact(input).neighborhood(), output);
trace::exiting("morpho::dilation");
}
Index: tests/morpho/dilation.cc
--- tests/morpho/dilation.cc (revision 1687)
+++ tests/morpho/dilation.cc (working copy)
@@ -51,6 +51,9 @@
#include <mln/convert/to_p_array.hh>
#include <mln/convert/to_window.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/neighb/image.hh>
+
#include "tests/data.hh"
@@ -70,23 +73,30 @@
io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
{
- // FIXME: This struct. elt. is far too big for a routinely run
- // test; either use a smaller one or qualify this test as
- // ``long''.
- win::rectangle2d rec(21, 21);
+ win::rectangle2d rec(5, 3);
image2d<int_u8> out(lena.domain());
morpho::dilation(lena, rec, out);
io::pgm::save(out, "out1.pgm");
}
{
- win::octagon2d oct(6);
+ win::octagon2d oct(7);
image2d<int_u8> out(lena.domain());
morpho::dilation(lena, oct, out);
io::pgm::save(out, "out2.pgm");
}
- // FIXME: Add tests using neighborhoods, too.
+ {
+ image2d<int_u8> out(lena.domain());
+ morpho::dilation(lena + c4(), out);
+ io::pgm::save(out, "out3.pgm");
+ }
+
+ {
+ image2d<int_u8> out(lena.domain());
+ morpho::dilation(lena + c8(), out);
+ io::pgm::save(out, "out4.pgm");
+ }
// {
// p_array<point2d> vec = convert::to_p_array(rec, point2d::zero);
@@ -95,7 +105,7 @@
// image2d<int_u8> out(lena.domain());
// level::ero(lena, win, out);
// morpho::dilation(lena, win, out);
-// io::pgm::save(out, "out.pgm");
+// io::pgm::save(out, "out5.pgm");
// }
// {
@@ -107,7 +117,7 @@
// image2d<int_u8>::fwd_piter p(lena.domain());
// for_all(p)
// test(p) = out(p) ? 255 : 0;
-// io::pgm::save(test, "test.pgm");
+// io::pgm::save(test, "out6.pgm");
// }
}
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add a morpher adding a neighborhood to an image.
* mln/neighb/image.hh: New.
Provide a morpher adding a neighborhood to an image.
* mln/neighb/get.hh: New.
Get the neighborhood from an image with neighborhood.
* mln/metal/has_neighborhood.hh: New.
Provide a static assertion `has_neighborhood' for images.
* mln/tag/skeleton.hh (mln::tag::neighb_): New tag.
* mln/trait/ch_value.hh
(trait::impl::ch_value_< M< tag::image_<I>, tag::neighb_<N> >, V >):
New specialization for mln::neighb::image<I, N>.
* tests/Makefile.am (SUBDIRS): Add neighb.
* tests/neighb/Makefile.am: New.
* tests/neighb/image.cc: New.
Exercize mln/neighb/images.cc and mln/neighb/get.cc.
mln/metal/has_neighborhood.hh | 53 +++++++++++
mln/neighb/get.hh | 194 ++++++++++++++++++++++++++++++++++++++++++
mln/neighb/image.hh | 191 +++++++++++++++++++++++++++++++++++++++++
mln/tag/skeleton.hh | 3
mln/trait/ch_value.hh | 10 +-
tests/Makefile.am | 1
tests/neighb/Makefile.am | 10 ++
tests/neighb/image.cc | 59 ++++++++++++
8 files changed, 519 insertions(+), 2 deletions(-)
Index: mln/neighb/image.hh
--- mln/neighb/image.hh (revision 0)
+++ mln/neighb/image.hh (revision 0)
@@ -0,0 +1,191 @@
+// 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.
+
+#ifndef MLN_NEIGHB_IMAGE_HH
+# define MLN_NEIGHB_IMAGE_HH
+
+/// \file mln/neighb/image.hh
+/// \brief An image morpher adding a neighborhood to an image.
+
+# include <mln/core/internal/image_identity.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+
+namespace mln
+{
+
+ // Fwd decl.
+ namespace neighb { template <typename I, typename N> struct image; }
+
+ /// Create an image with a neighborhood from an image and a
+ /// neighborhood.
+ template <typename I, typename N>
+ neighb::image<I, N>
+ operator+ (Image<I>& ima, const Neighborhood<N>& nbh);
+
+
+ namespace internal
+ {
+
+ /// \internal Data structure for mln::neighb::image
+ template <typename I, typename N>
+ struct data_< mln::neighb::image<I, N> >
+ {
+ data_(I& ima, const N& nbh);
+
+ I ima_;
+ N nbh_;
+ };
+
+ } // end of namespace mln::internal
+
+
+
+ namespace trait
+ {
+
+ template <typename I, typename N>
+ struct image_< neighb::image<I, N> >
+ : public default_image_morpher_< I, mln_value(I), neighb::image<I, N> >
+
+ {
+ typedef trait::image::category::morpher category;
+
+ typedef trait::image::neighb::some neighb;
+ };
+
+ } // end of namespace mln::trait
+
+
+ namespace neighb
+ {
+ /// \brief A class that embodies an image with an attached
+ /// neighborhood.
+ ///
+ /// Parameter \c I is the actual type of the image, and \c N is
+ /// the one of the neighborhood.
+ ///
+ /// \pre The domains of \c I and \c N must be compatible.
+ template <typename I, typename N>
+ struct image
+ : public internal::image_identity_ < I, mln_pset(I), image <I, N> >
+ {
+ /// Point_Site associated type.
+ typedef mln_psite(I) psite;
+
+ /// Point_Set associated type.
+ typedef mln_pset(I) pset;
+
+ /// Neighborhood associated type.
+ typedef N neighb;
+
+ /// Skeleton.
+ typedef image< tag::image_<I>, tag::neighb_<N> > skeleton;
+
+ /// Constructor.
+ image(Image<I>& ima, const Neighborhood<N>& nbh);
+
+ /// Test if this image has been initialized.
+ bool has_data() const;
+
+ /// Return the neighborhood associated to this image.
+ const neighb& neighborhood() const;
+ };
+
+ } // end of namespace mln::neighb
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ /*------------.
+ | operator+. |
+ `------------*/
+
+ template <typename I, typename N>
+ neighb::image<I, N>
+ operator+ (Image<I>& ima, const Neighborhood<N>& nbh)
+ {
+ neighb::image<I, N> tmp(ima, nbh);
+ return tmp;
+ }
+
+ /*--------------------------------------.
+ | internal::data_< cast_image_<T,I> >. |
+ `--------------------------------------*/
+
+ namespace internal
+ {
+ template <typename I, typename N>
+ inline
+ data_< neighb::image<I, N> >::data_(I& ima, const N& nbh)
+ : ima_(ima),
+ nbh_(nbh)
+ {
+ }
+ }
+
+ /*----------------------.
+ | neighb::image<I, N>. |
+ `----------------------*/
+
+ namespace neighb
+ {
+
+ template <typename I, typename N>
+ inline
+ image<I, N>::image(Image<I>& ima, const Neighborhood<N>& nbh)
+ {
+ this->data_ =
+ new mln::internal::data_< mln::neighb::image<I, N> >(exact(ima),
+ exact(nbh));
+ }
+
+ template <typename I, typename N>
+ inline
+ bool
+ image<I, N>::has_data() const
+ {
+ return this->delegatee_()->has_data();
+ }
+
+ template <typename I, typename N>
+ inline
+ const N&
+ image<I, N>::neighborhood() const
+ {
+ return this->data_->nbh_;
+ }
+
+ } // end of namespace mln::neighb
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+#include <mln/neighb/get.hh>
+
+#endif // ! MLN_NEIGHB_IMAGE_HH
Index: mln/neighb/get.hh
--- mln/neighb/get.hh (revision 0)
+++ mln/neighb/get.hh (revision 0)
@@ -0,0 +1,194 @@
+// 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.
+
+#ifndef MLN_NEIGHB_GET_HH
+# define MLN_NEIGHB_GET_HH
+
+/// \file mln/neighb/get.hh
+/// \brief Define function that returns the neighborhood assocoatied
+/// to an image.
+
+# include <mln/trait/images.hh>
+# include <mln/neighb/image.hh>
+
+
+/// Shortcuts to access the neighborhood type associated to I.
+/// \{
+# define mln_neighb(T) typename mln::neighb::get_helper<I>::type
+# define mln_neighb_(T) mln::neighb::get_helper<I>::type
+/// \}
+
+
+namespace mln
+{
+
+ namespace neighb
+ {
+
+ // Fwd decl.
+ template <typename I>
+ struct get_helper;
+
+ template <typename I>
+ typename get_helper<I>::type
+ get(const Image<I>& ima);
+
+
+ /// FIXME: Move this to mln/trait/neighb.hh? And split
+ /// neighborhood type deduction from neighborhood access (fun)?
+
+ /// Get the (possible) neighborhood type associated to an image
+ /// type \c I.
+ template <typename I>
+ struct get_helper
+ {
+ /// Select the neighborhood from the presence of the
+ /// neighborhood and the category of the image.
+ /// {
+
+ // FIXME: Rename select_from_traits.
+
+ template <typename image_neighb, typename image_category, typename I_>
+ struct select_from_traits;
+
+ /// Case where the image has a neighborhood and is a primary
+ /// image.
+ template <typename I_>
+ struct select_from_traits<trait::image::neighb::some,
+ trait::image::category::primary,
+ I_>
+ {
+ typedef typename I_::neighb type;
+
+ static const type&
+ run(const I_& ima) { return ima.neighborhood(); }
+ };
+
+ /// Special case: neighb::image<I_, N_>.
+ template <typename I_, typename N_>
+ struct select_from_traits<trait::image::neighb::some,
+ trait::image::category::morpher,
+ mln::neighb::image<I_, N_> >
+ {
+ typedef typename neighb::image<I_, N_>::neighb type;
+
+ static const type&
+ run(const neighb::image<I_, N_>& ima) { return ima.neighborhood(); }
+ };
+
+ /// Case where the image has a neighborhood and is a morpher.
+ template <typename I_>
+ struct select_from_traits<trait::image::neighb::some,
+ trait::image::category::morpher,
+ I_>
+ {
+ typedef typename get_helper<typename I_::delegatee>::type type;
+
+ static const type&
+ run(const I_& ima) { return neighb::get( *ima.delegatee_() ); }
+ };
+
+ /// Case where the image has a neighborhood and is a identity morpher.
+ template <typename I_>
+ struct select_from_traits<trait::image::neighb::some,
+ trait::image::category::identity_morpher,
+ I_>
+ {
+ typedef typename get_helper<typename I_::delegatee>::type type;
+
+ static const type&
+ run(const I_& ima) { return neighb::get( *ima.delegatee_() ); }
+ };
+
+ /// Case where the image has a neighborhood and is a value morpher.
+ template <typename I_>
+ struct select_from_traits<trait::image::neighb::some,
+ trait::image::category::value_morpher,
+ I_>
+ {
+ typedef typename get_helper<typename I_::delegatee>::type type;
+
+ static const type&
+ run(const I_& ima) { return neighb::get( *ima.delegatee_() ); }
+ };
+
+ /// \brief Default case: error.
+ ///
+ /// Causes:
+ /// \li the image has no neighborhood;
+ /// \li the image category is of an invalid morpher type (e.g.,
+ /// a domain morpher);
+ /// \li the trait for the neighborhood of the image is not
+ /// defined or ill-defined;
+ /// \li the trait for the image category is not defined or
+ /// ill-defined.
+ template <typename image_neighb, typename image_category, typename I_>
+ struct select_from_traits
+ {
+ /// Nothing.
+ };
+
+ /// \}
+
+ typedef select_from_traits< mln_trait_image_neighb(I),
+ mln_trait_image_category(I),
+ I > selection_;
+
+ typedef typename selection_::type type;
+
+ static const type& run(const I& ima) { return selection_::run(ima); }
+ };
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // Facade.
+
+ template <typename I>
+ inline
+ typename get_helper<I>::type
+ get(const Image<I>& ima)
+ {
+ trace::entering("neighb::get");
+
+ mln_precondition(exact(ima).has_data());
+ typename neighb::get_helper<I>::type res =
+ neighb::get_helper<I>::run(exact(ima));
+
+ trace::exiting("neighb::get");
+ return res;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::neighb
+
+} // end of namespace mln
+
+
+#endif // ! MLN_NEIGHB_GET_HH
Index: mln/metal/has_neighborhood.hh
--- mln/metal/has_neighborhood.hh (revision 0)
+++ mln/metal/has_neighborhood.hh (revision 0)
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef MLN_METAL_HAS_NEIGHBORHOOD_HH
+# define MLN_METAL_HAS_NEIGHBORHOOD_HH
+
+# include <mln/neighb/get.hh>
+
+namespace mln
+{
+
+ namespace metal
+ {
+
+ template <typename I>
+ struct has_neighborhood
+ {
+ static void check()
+ {
+ // Ensure the image has a `neighb' property.
+ typedef mln_neighb(I) neighb;
+ }
+ };
+
+ } // end of namespace mln::metal
+
+} // end of namespace mln
+
+#endif // ! MLN_METAL_HAS_NEIGHBORHOOD_HH
Index: mln/tag/skeleton.hh
--- mln/tag/skeleton.hh (revision 1685)
+++ mln/tag/skeleton.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// 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
@@ -48,6 +48,7 @@
template <typename S> struct pset_ { typedef S param; };
template <typename D> struct data_ { typedef D param; };
template <typename F> struct function_ { typedef F param; };
+ template <typename N> struct neighb_ { typedef N param; };
// With value.
template <unsigned u> struct unsigned_ { enum { value = u }; };
Index: mln/trait/ch_value.hh
--- mln/trait/ch_value.hh (revision 1685)
+++ mln/trait/ch_value.hh (working copy)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// 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
@@ -109,6 +109,14 @@
typedef mln_ch_value(I, V) ret;
};
+ // For mln::neighb::image<I, N>.
+ template < template <class, class> class M, typename I, typename N,
+ typename V >
+ struct ch_value_< M< tag::image_<I>, tag::neighb_<N> >, V >
+ {
+ typedef M < mln_ch_value(I, V), N > ret;
+ };
+
template < template <class, class> class M, typename I, typename S,
typename V >
struct ch_value_< M< tag::image_<I>, tag::pset_<S> >, V >
Index: tests/Makefile.am
--- tests/Makefile.am (revision 1685)
+++ tests/Makefile.am (working copy)
@@ -18,6 +18,7 @@
level \
logical \
morpho \
+ neighb \
norm \
set \
util \
Index: tests/neighb/image.cc
--- tests/neighb/image.cc (revision 0)
+++ tests/neighb/image.cc (revision 0)
@@ -0,0 +1,59 @@
+// 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/neighb/image.cc
+ *
+ * \brief Tests on mln::neighb::image.
+ */
+
+#include <mln/neighb/image.hh>
+#include <mln/core/image2d.hh>
+#include <mln/core/neighb2d.hh>
+#include <mln/metal/has_neighborhood.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d<int> ima_t;
+ typedef neighb2d nbh_t;
+
+ typedef neighb::image<ima_t, nbh_t> ima_with_nbh_t;
+
+ metal::has_neighborhood<ima_with_nbh_t>::check();
+
+ ima_t ima (make::box2d(5, 5));
+
+ // Explicit construction.
+ ima_with_nbh_t ima1 (ima, c4());
+ neighb::get(ima1);
+
+ // Construction using operator+.
+ ima_with_nbh_t ima2 = ima + c4();
+ neighb::get(ima2);
+}
Index: tests/neighb/Makefile.am
--- tests/neighb/Makefile.am (revision 0)
+++ tests/neighb/Makefile.am (revision 0)
@@ -0,0 +1,10 @@
+## Process this file through Automake to create Makefile.in -*- Makefile -*-
+
+include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ image
+
+image_SOURCES = image.cc
+
+TESTS = $(check_PROGRAMS)