https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Binarization.
* mln/level/threshold.hh: Remove.
* mln/fun/v2b: New directory : value to bool function.
* mln/fun/v2b/threshold.hh: value to bool threshold.
* mln/fun/v2v/threshold.hh: Remove.
* mln/binarization: New directory.
* mln/binarization/includes.hh: include for binarization.
* mln/binarization/binarization.hh: generic binarization (v2b for now).
* mln/binarization/thresholding.hh: thresholding.
* mln/io/pnm/save.hh: Comments for dummy (me) users who try to save binary as pgm.
* tests/binarization: New test directory.
* tests/binarization/thresholding.cc: New test file.
mln/binarization/binarization.hh | 106 +++++++++++++++++++++++++++++++++++++
mln/binarization/includes.hh | 43 +++++++++++++++
mln/binarization/thresholding.hh | 89 +++++++++++++++++++++++++++++++
mln/fun/v2b/threshold.hh | 90 +++++++++++++++++++++++++++++++
mln/io/pnm/save.hh | 2
tests/binarization/thresholding.cc | 54 ++++++++++++++++++
6 files changed, 384 insertions(+)
Index: tests/binarization/thresholding.cc
--- tests/binarization/thresholding.cc (revision 0)
+++ tests/binarization/thresholding.cc (revision 0)
@@ -0,0 +1,54 @@
+// 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.
+
+/*! \file tests/binarization/thresholding.cc
+ *
+ * \brief Test on mln::binarization::thresholding
+ */
+
+
+#include <mln/core/image2d.hh>
+#include <mln/binarization/thresholding.hh>
+#include <mln/level/all.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pbm/save.hh>
+
+//#include "tests/data.hh"
+
+int main(int argc, char **)
+{
+ using namespace mln;
+ using value::int_u8;
+
+ typedef image2d<int_u8> I;
+
+ I lena;
+ io::pgm::load(lena, "../../img/lena.pgm");
+
+ io::pbm::save(binarization::thresholding(lena, argc), "out1.pgm");
+}
Index: tests/morpho/gradient.cc
Index: mln/fun/v2b/threshold.hh
--- mln/fun/v2b/threshold.hh (revision 0)
+++ mln/fun/v2b/threshold.hh (revision 0)
@@ -0,0 +1,90 @@
+// Copyright (C) 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
+// 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_FUN_V2B_THRESHOLD_HH
+# define MLN_FUN_V2B_THRESHOLD_HH
+
+/*! \file mln/fun/v2b/threshold.hh
+ *
+ * \brief FIXME.
+ */
+
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace v2b
+ {
+
+ /*!
+ *\brief Threshold function.
+ * f(v) = (v >= threshold).
+ *
+ */
+ template <typename V>
+ struct threshold : public Function_v2b< threshold<V> >
+ {
+ typedef bool result;
+ bool operator()(const V& v) const;
+
+ threshold(const V& a);
+ V a;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename V>
+ inline
+ threshold<V>::threshold(const V& a)
+ : a(a)
+ {
+ }
+
+ template <typename V>
+ inline
+ bool
+ threshold<V>::operator()(const V& v) const
+ {
+ return (v >= a);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::v2b
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_V2B_THRESHOLD_HH
Index: mln/binarization/includes.hh
--- mln/binarization/includes.hh (revision 0)
+++ mln/binarization/includes.hh (revision 0)
@@ -0,0 +1,43 @@
+// Copyright (C) 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
+// 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_BINARIZATION_INCLUDES_HH
+# define MLN_BINARIZATION_INCLUDES_HH
+
+/*! \file mln/binarization/includes.hh
+ *
+ * \brief Basic list of includes for all files in mln/binarization/.
+ */
+
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/window.hh>
+# include <mln/core/concept/neighborhood.hh>
+
+# include <mln/metal/has_neighborhood.hh>
+
+#endif // ! MLN_BINARIZATION_INCLUDES_HH
Index: mln/binarization/binarization.hh
--- mln/binarization/binarization.hh (revision 0)
+++ mln/binarization/binarization.hh (revision 0)
@@ -0,0 +1,106 @@
+// Copyright (C) 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
+// 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_BINARIZATION_BINARIZATION_HH
+# define MLN_BINARIZATION_BINARIZATION_HH
+
+/*! \file mln/binarization/threshold.hh
+ *
+ * \brief Threshold the contents of an image into another binary one.
+ */
+
+# include <mln/core/concept/function.hh>
+# include <mln/level/transform.hh>
+
+
+namespace mln
+{
+
+ namespace binarization
+ {
+
+ /*! Thresholds the values of \p input so that they can be stored in
+ * the \p output binary image.
+ *
+ * \param[in] input The input image.
+ * \param[in] fun The thresholding function, from value(I) to bool.
+ *
+ * for_all(p), output(p) = fun(p)
+ *
+ */
+ template <typename I, typename F>
+ inline
+ mln_concrete_ch_value(I, bool)
+ binarization(const Image<I>& input, const Function_v2b<F>& fun);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename I, typename F>
+ inline
+ mln_concrete_ch_value(I, bool)
+ binarization_(const I& input, const Function_v2b<F>& fun)
+ {
+ trace::entering("binarization::impl::binarization_");
+ mln_concrete_ch_value(I, bool) output(input.domain());
+
+ level::transform(input, fun, output);
+
+ trace::exiting("binarization::impl::binarization_");
+ return output;
+ }
+
+ } // end of namespace mln::binarization::impl
+
+
+ template <typename I, typename F>
+ inline
+ mln_concrete_ch_value(I, bool)
+ binarization(const Image<I>& input, const Function_v2b<F>& fun)
+ {
+ trace::entering("binarization::binarization");
+ mln_precondition(exact(input).has_data());
+ mlc_is(mln_trait_value_nature(mln_value(I)),
+ trait::value::nature::scalar)::check();
+
+ mln_concrete_ch_value(I, bool) output(exact(input).domain());
+ output = impl::binarization_(exact(input), fun);
+
+ trace::exiting("binarization::binarization");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::binarization
+
+} // end of namespace mln
+
+
+#endif // ! MLN_BINARIZATION_THRESHOLDING_HH
Index: mln/binarization/thresholding.hh
--- mln/binarization/thresholding.hh (revision 0)
+++ mln/binarization/thresholding.hh (revision 0)
@@ -0,0 +1,89 @@
+// Copyright (C) 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
+// 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_BINARIZATION_THRESHOLDING_HH
+# define MLN_BINARIZATION_THRESHOLDING_HH
+
+/*! \file mln/binarization/thresholding.hh
+ *
+ * \brief Threshold the contents of an image into another binary one.
+ */
+
+# include <mln/binarization/binarization.hh>
+# include <mln/fun/v2b/threshold.hh>
+
+
+namespace mln
+{
+
+ namespace binarization
+ {
+
+ /*! Thresholds the values of \p input so that they can be stored in
+ * the \p output binary image.
+ *
+ * \param[in] input The input image.
+ * \param[in] threshold The threshold.
+ *
+ * If input(p) is greater or equal than the threshold, the
+ * value in the output image in the same point will be TRUE, else FALSE.
+ *
+ */
+ template <typename I>
+ mln_concrete_ch_value(I, bool)
+ thresholding(const Image<I>& input, const mln_value(I) threshold);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ mln_concrete_ch_value(I, bool)
+ thresholding(const Image<I>& input, const mln_value(I) threshold)
+ {
+ trace::entering("binarization::thresholding");
+ mln_precondition(exact(input).has_data());
+ mlc_is(mln_trait_value_nature(mln_value(I)),
+ trait::value::nature::scalar)::check();
+
+ mln_concrete_ch_value(I, bool) output(exact(input).domain());
+
+ fun::v2b::threshold< mln_value(I) > f(threshold);
+ output = binarization::binarization(exact(input), f);
+
+ trace::exiting("binarization::thresholding");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::binarization
+
+} // end of namespace mln
+
+
+#endif // ! MLN_BINARIZATION_THRESHOLDING_HH
Index: mln/io/pnm/save.hh
--- mln/io/pnm/save.hh (revision 1734)
+++ mln/io/pnm/save.hh (working copy)
@@ -102,6 +102,8 @@
void write_value(std::ofstream& file,
const V& v)
{
+ // if V is not a struct you are probably trying to write binary images
+ // use pbm files for binary images
typedef typename V::enc E;
E c = v.to_enc();
https://svn.lrde.epita.fr/svn/oln/trunk/milena
I know I should probably move the tests related to the WST to
tests/morpho. Please recall this to me if I forget to do it. TIA.
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Add a test applying a full WST-based segmentation chain on a line
graph.
* tests/core/lena_line_graph_image_wst.cc: New test.
* tests/core/graph_image_wst.cc: Fix Doxygen header.
* tests/core/Makefile.am (check_PROGRAMS): Add
lena_line_graph_image_wst.
(lena_line_graph_image_wst_SOURCES)
(lena_line_graph_image_wst_CXXFLAGS):
New.
* tests/morpho/Makefile.am (meyer_wst_long_CXXFLAGS): Append
-ggdb.
core/Makefile.am | 5
core/graph_image_wst.cc | 4
core/lena_line_graph_image_wst.cc | 249 ++++++++++++++++++++++++++++++++++++++
morpho/Makefile.am | 2
4 files changed, 257 insertions(+), 3 deletions(-)
Index: tests/core/lena_line_graph_image_wst.cc
--- tests/core/lena_line_graph_image_wst.cc (revision 0)
+++ tests/core/lena_line_graph_image_wst.cc (revision 0)
@@ -0,0 +1,249 @@
+// 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/core/line_graph_image.cc
+/// \brief Tests on the Watershed Transform on a mln::line_graph_image.
+
+#include <vector>
+
+#include <mln/core/image2d.hh>
+#include <mln/core/point2d.hh>
+#include <mln/core/window2d.hh>
+#include <mln/core/neighb2d.hh>
+
+#include <mln/core/line_graph_image.hh>
+#include <mln/core/line_graph_elt_neighborhood.hh>
+#include <mln/core/line_graph_neighborhood_piter.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/value/int_u8.hh>
+// #include <mln/value/int_u16.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/black.hh>
+#include <mln/literal/colors.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/math/max.hh>
+#include <mln/math/abs.hh>
+
+#include "tests/data.hh"
+
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+// using value::int_u16;
+ using value::rgb8;
+
+ /*--------.
+ | Input. |
+ `--------*/
+
+ typedef int_u8 input_val_t;
+ image2d<input_val_t> input;
+// io::pgm::load(input, MLN_IMG_DIR "/small.pgm");
+ io::pgm::load(input, MLN_IMG_DIR "/tiny.pgm");
+
+ /* FIXME: Don't compute a gradient on the image2d input. Instead,
+ have the values of the line graph image /behaves/ as the gradient
+ of the input, i.e., edges should hold the absolute difference
+ between gray levels.
+ */
+ image2d<input_val_t> gradient =
+ morpho::gradient (input, convert::to_window(c4()));
+
+ // Simplify the input image.
+ image2d<input_val_t> work(input.domain());
+// morpho::closing_area(gradient, c4(), 50, work);
+ morpho::closing_area(gradient, c4(), 10, work);
+
+ /*-------------.
+ | Line graph. |
+ `-------------*/
+
+ // FIXME: Inlined conversion, to be reifed into a routine.
+
+ util::graph<point2d> g;
+
+ // Points.
+ /* FIXME: The need for such a structure during the conversion
+ exhibits the lack of a service from util::graph (or a another,
+ missing tool) regarding the retrieval of node ids from
+ points. */
+ std::map<point2d, util::node_id> points;
+ util::node_id id = 0;
+
+ // Nodes.
+ std::vector<int> node_values;
+ mln_fwd_piter_(image2d<input_val_t>) p(work.domain());
+ for_all (p)
+ {
+ g.add_node (p);
+ node_values.push_back (work(p));
+ /* FIXME: ``Guessing'' the id of the point just being inserted
+ is bad. utill:graph<N,E>::add_node should return this
+ id. */
+ points[p] = id;
+ ++id;
+ }
+
+ // Edges.
+ window2d next_c4_win;
+ next_c4_win.insert(0, 1).insert(1, 0);
+ std::vector<int> edge_values;
+ mln_fwd_qiter_(window2d) q(next_c4_win, p);
+ for_all (p)
+ for_all (q)
+ if (work.has(q))
+ {
+ g.add_edge(points[p], points[q]);
+ // FIXME: Keep this valuation function?
+ edge_values.push_back(math::max(work(p), work(q)));
+ }
+
+ // Line graph point set.
+ p_line_graph<point2d> plg(g);
+
+ // Line graph image.
+ /* FIXME: Shouldn't we use `input_val_t' instead of plain `int' as value
+ type here? */
+ typedef line_graph_image<point2d, int> ima_t;
+ ima_t lg_ima(plg, node_values, edge_values);
+
+ /*------.
+ | WST. |
+ `------*/
+
+ typedef line_graph_elt_neighborhood<point2d> nbh_t;
+ nbh_t nbh;
+
+ // Perform a Watershed Transform.
+ typedef int_u8 wst_val_t;
+ wst_val_t nbasins;
+ typedef line_graph_image<point2d, wst_val_t> wst_ima_t;
+ wst_ima_t wshed = morpho::meyer_wst(lg_ima, nbh, nbasins);
+ std::cout << "nbasins = " << nbasins << std::endl;
+
+ /*---------.
+ | Output. |
+ `---------*/
+
+ // FIXME: Inlined conversion, to be reifed into a routine.
+
+ // Save the result in gray levels (data) + color (wshed).
+
+ // Data.
+ typedef rgb8 output_val_t;
+ typedef image2d<output_val_t> output_t;
+ point2d output_pmin = input.domain().pmin();
+ point2d output_pmax(input.domain().pmax()[0] * 2,
+ input.domain().pmax()[1] * 2);
+ output_t output(box2d(output_pmin, output_pmax));
+ level::fill(output, literal::black);
+ // Reuse the piter on INPUT.
+ for_all(p)
+ {
+ // Equivalent of P in OUTPUT.
+ point2d q(p[0] * 2, p[1] * 2);
+ input_val_t v = input(p);
+ /* FIXME: Use a conversion function from input_val_t to
+ output_val_t instead of an explicit construction. */
+ output(q) = output_val_t(v, v, v);
+ }
+ // Interpolate missing points in OUTPUT.
+ mln_piter_(output_t) p_out(output.domain());
+// mln_niter_(neighb2d) n_out(c4(), p_out);
+ for_all(p_out)
+ {
+ // Process points on even rows and odd columns
+ if (p_out[0] % 2 == 0 && p_out[1] % 2 == 1)
+ output(p_out) = (output(p_out + left) + output(p_out + right)) / 2;
+ // Process points on odd rows and even columns
+ if (p_out[0] % 2 == 1 && p_out[1] % 2 == 0)
+ output(p_out) = (output(p_out + up) + output(p_out + down)) / 2;
+ // Process points on odd rows and odd columns
+ if (p_out[0] % 2 == 1 && p_out[1] % 2 == 1)
+ output(p_out) =
+ (output(p_out + make::dpoint2d(-1, -1)) +
+ output(p_out + make::dpoint2d(-1, +1)) +
+ output(p_out + make::dpoint2d(+1, -1)) +
+ output(p_out + make::dpoint2d(+1, +1))) / 4;
+ }
+ // Draw the watershed.
+ /* FIXME: We should draw the watershed on another image and
+ superimpose it on OUTPUT instead of drawing it directly into
+ OUTPUT. */
+ mln_piter_(wst_ima_t) pw(wshed.domain());
+ for_all(pw)
+ {
+ if (wshed(pw) == 0)
+ {
+ mln_point_(wst_ima_t) pp(pw);
+ // Equivalent of the line (edge) PP in OUTPUT.
+ int row1 = pp.first()[0] * 2;
+ int col1 = pp.first()[1] * 2;
+ int row2 = pp.second()[0] * 2;
+ int col2 = pp.second()[1] * 2;
+ point2d q((row1 + row2) / 2, (col1 + col2) / 2);
+ // Print the watershed in red.
+ output(q) = literal::red;
+ }
+ }
+ // Fill the holes, so that the watershed looks connected.
+ /* FIXME: This approach is bad: it creates thick lines of watershed.
+ We should probably solve this when we ``paint'' the watershed
+ over the ``doubled'' image.
+
+ A better approach is probably to iterate over the set of nodes,
+ and ``connect'' edges according to patterns (vertically or
+ horizontally connected egdes member of the watershed, etc.). */
+ // Reuse the piter on OUTPUT.
+ for_all (p_out)
+ // Only handle points on odd rows and columns.
+ if (p_out[0] % 2 == 1 && p_out[1] % 2 == 1)
+ {
+ // Count the number of adjacent watershed points. If there are
+ // two or more, consider, create a watershed point.
+ /* FIXME: Iterating over a c4 window would be more elegant, of
+ course. */
+ unsigned nwsheds =
+ (output.has(p_out + up ) && output(p_out + up ) == literal::red) +
+ (output.has(p_out + down ) && output(p_out + down ) == literal::red) +
+ (output.has(p_out + left ) && output(p_out + right) == literal::red) +
+ (output.has(p_out + right) && output(p_out + left ) == literal::red);
+ if (nwsheds >= 2)
+ output(p_out) = literal::red;
+ }
+ io::ppm::save(output, "out.ppm");
+}
Index: tests/core/graph_image_wst.cc
--- tests/core/graph_image_wst.cc (revision 1719)
+++ tests/core/graph_image_wst.cc (working copy)
@@ -25,8 +25,8 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/// \file tests/core/graph_image.cc
-/// \brief Tests on mln::graph_image.
+/// \file tests/core/graph_image_wst.cc
+/// \brief Tests on the Watershed Transform on a mln::graph_image.
#include <vector>
Index: tests/core/Makefile.am
--- tests/core/Makefile.am (revision 1731)
+++ tests/core/Makefile.am (working copy)
@@ -10,6 +10,7 @@
initialize \
graph_elt_window \
graph_image \
+ lena_line_graph_image_wst \
line_graph_elt_window \
line_graph_image \
line_graph_image_wst \
@@ -51,4 +52,8 @@
t_image_SOURCES = t_image.cc
tr_image_SOURCES = tr_image.cc
+# FIXME: We should isolate this test, as it takes a long time.
+lena_line_graph_image_wst_SOURCES = lena_line_graph_image_wst.cc
+lena_line_graph_image_wst_CXXFLAGS = -O3 -ggdb
+
TESTS = $(check_PROGRAMS)
Index: tests/morpho/Makefile.am
--- tests/morpho/Makefile.am (revision 1731)
+++ tests/morpho/Makefile.am (working copy)
@@ -35,6 +35,6 @@
meyer_wst_SOURCES = meyer_wst.cc
# FIXME: We should isolate this test, as it takes a long time.
meyer_wst_long_SOURCES = meyer_wst_long.cc
-meyer_wst_long_CXXFLAGS = -O3
+meyer_wst_long_CXXFLAGS = -O3 -ggdb
TESTS = $(check_PROGRAMS)
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Roland Levillain <roland(a)lrde.epita.fr>
Improve the robustness of psites on graphs.
* mln/core/graph_psite.hh, mln/core/line_graph_psite.hh
(to_psite): New method.
(operator=): Don't copy the point set from the argument. Instead,
ensure that that point set in compatible with the point set of the
psite.
graph_psite.hh | 19 ++++++++++++++++---
line_graph_psite.hh | 19 ++++++++++++++++---
2 files changed, 32 insertions(+), 6 deletions(-)
Index: mln/core/graph_psite.hh
--- mln/core/graph_psite.hh (revision 1725)
+++ mln/core/graph_psite.hh (working copy)
@@ -58,10 +58,14 @@
/// \{
graph_psite(const p_graph<P>& pg_, unsigned id);
graph_psite(const self_& rhs);
+ /// \pre This psite must have the same graph point set as \a rhs.
self_& operator= (const self_& rhs);
/// \}
- /// Access to point/psite.
+ /// Access to psite.
+ const self_& to_psite() const;
+
+ /// Access to point.
/// \{
operator P() const;
const point& to_point() const;
@@ -107,14 +111,23 @@
{
if (&rhs == this)
return *this;
- // FIXME: Could we get rid of this cast?
- const_cast< p_graph<P>& >(pg_) = rhs.pg_;
+ // Assigning a psite from a graph point set to a psite from
+ // another graph point set is meaningless.
+ mln_assertion(&pg_ == &rhs.pg_);
id_ = rhs.id_;
return *this;
}
template<typename P>
inline
+ const graph_psite<P>&
+ graph_psite<P>::to_psite() const
+ {
+ return *this;
+ }
+
+ template<typename P>
+ inline
graph_psite<P>::operator P() const
{
return pg_.gr_.node_data(id_);
Index: mln/core/line_graph_psite.hh
--- mln/core/line_graph_psite.hh (revision 1725)
+++ mln/core/line_graph_psite.hh (working copy)
@@ -62,10 +62,14 @@
/// \{
line_graph_psite(const p_line_graph<P>& plg_, unsigned id);
line_graph_psite(const self_& rhs);
+ /// \pre This psite must have the same graph point set as \a rhs.
self_& operator= (const self_& rhs);
/// \}
- /// Access to point/psite.
+ /// Access to psite.
+ const self_& to_psite() const;
+
+ /// Access to point.
/// \{
operator point() const;
const point& to_point() const;
@@ -142,8 +146,9 @@
{
if (&rhs == this)
return *this;
- // FIXME: Could we get rid of this cast?
- const_cast< p_line_graph<P>& >(plg_) = rhs.plg_;
+ // Assigning a psite from a line graph point set to a psite from
+ // another line graph point set is meaningless.
+ mln_assertion(&plg_ == &rhs.plg_);
id_ = rhs.id_;
update_();
return *this;
@@ -167,6 +172,14 @@
template<typename P>
inline
+ const line_graph_psite<P>&
+ line_graph_psite<P>::to_psite() const
+ {
+ return *this;
+ }
+
+ template<typename P>
+ inline
const point_pair<P>&
line_graph_psite<P>::to_point() const
{