* mln/accu/center.hh: New accu.
* mln/accu/all.hh,
* mln/accu/essential.hh: add center.hh.
* mln/make/all.hh,
* mln/make/essential.hh,
* mln/debug/essential.hh,
* mln/debug/all.hh: update includes.
* mln/debug/graph.hh: Rename as...
* mln/debug/draw_graph.hh: ...this.
* mln/make/graph.hh: Add make::graph().
* mln/util/array.hh: cleanup.
* mln/util/edge.hh: cleanup comments.
* mln/util/graph.hh: add new constructors.
---
milena/ChangeLog | 25 ++++
milena/mln/accu/all.hh | 1 +
milena/mln/accu/center.hh | 154 +++++++++++++++++++++++++
milena/mln/accu/essential.hh | 1 +
milena/mln/debug/all.hh | 10 +-
milena/mln/debug/{graph.hh => draw_graph.hh} | 80 +++++---------
milena/mln/debug/essential.hh | 9 +-
milena/mln/make/all.hh | 1 +
milena/mln/make/essential.hh | 7 +-
milena/mln/make/graph.hh | 159 ++++++++++++++++++++++++++
milena/mln/util/array.hh | 35 +++----
milena/mln/util/edge.hh | 2 +-
milena/mln/util/graph.hh | 37 ++++++
13 files changed, 434 insertions(+), 87 deletions(-)
create mode 100644 milena/mln/accu/center.hh
rename milena/mln/debug/{graph.hh => draw_graph.hh} (53%)
create mode 100644 milena/mln/make/graph.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index f6f62e5..813df7d 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,28 @@
+2008-11-18 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update graph related classes.
+
+ * mln/accu/center.hh: New accu.
+
+ * mln/accu/all.hh,
+ * mln/accu/essential.hh: add center.hh.
+
+ * mln/make/all.hh,
+ * mln/make/essential.hh,
+ * mln/debug/essential.hh,
+ * mln/debug/all.hh: update includes.
+
+ * mln/debug/graph.hh: Rename as...
+ * mln/debug/draw_graph.hh: ...this.
+
+ * mln/make/graph.hh: Add make::graph().
+
+ * mln/util/array.hh: cleanup.
+
+ * mln/util/edge.hh: cleanup comments.
+
+ * mln/util/graph.hh: add new constructors.
+
2008-11-19 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update canvas labelingand labeling level.
diff --git a/milena/mln/accu/all.hh b/milena/mln/accu/all.hh
index cda8581..1d8b9bc 100644
--- a/milena/mln/accu/all.hh
+++ b/milena/mln/accu/all.hh
@@ -58,6 +58,7 @@ namespace mln
# include <mln/accu/bbox.hh>
# include <mln/accu/count.hh>
+# include <mln/accu/center.hh>
//# include <mln/accu/count_adjacent_vertices.hh>
# include <mln/accu/height.hh>
# include <mln/accu/histo.hh>
diff --git a/milena/mln/accu/center.hh b/milena/mln/accu/center.hh
new file mode 100644
index 0000000..2aacfce
--- /dev/null
+++ b/milena/mln/accu/center.hh
@@ -0,0 +1,154 @@
+// 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_ACCU_CENTER_HH
+# define MLN_ACCU_CENTER_HH
+
+/// \file mln/accu/center.hh
+///
+/// Define an accumulator that computes the center of a site set.
+
+# include <mln/accu/internal/base.hh>
+# include <mln/accu/bbox.hh>
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+
+ /// Generic center accumulator class.
+ template <typename P>
+ struct center : public mln::accu::internal::base< P , center<P> >
+ {
+ typedef P argument;
+ typedef P result;
+
+ center();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const argument& t);
+ void take(const center<P>& other);
+ /// \}
+
+ /// Get the value of the accumulator.
+ P to_result() const;
+ operator P () const;
+
+ /// Check whether this accu is able to return a result.
+ bool is_valid() const;
+
+ protected:
+ accu::bbox<P> bbox_;
+ };
+
+ namespace meta
+ {
+
+ /// Meta accumulator for center.
+ struct center : public Meta_Accumulator< center >
+ {
+
+ template <typename P>
+ struct with
+ {
+ typedef accu::center<P> ret;
+ };
+
+ };
+
+ } // end of namespace mln::accu::meta
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ inline
+ center<P>::center()
+ {
+ init();
+ }
+
+ template <typename P>
+ inline
+ void
+ center<P>::init()
+ {
+ bbox_.init();
+ }
+
+ template <typename P>
+ inline
+ void center<P>::take(const argument& t)
+ {
+ bbox_.take(t);
+ }
+
+ template <typename P>
+ inline
+ void
+ center<P>::take(const center<P>& other)
+ {
+ bbox_.take(other.bbox_);
+ }
+
+ template <typename P>
+ inline
+ P
+ center<P>::to_result() const
+ {
+ return bbox_.to_result().center();
+ }
+
+ template <typename P>
+ inline
+ center<P>::operator P() const
+ {
+ return P(bbox_.to_result().center());
+ }
+
+ template <typename P>
+ inline
+ bool
+ center<P>::is_valid() const
+ {
+ return bbox_.is_valid();
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_CENTER_HH
diff --git a/milena/mln/accu/essential.hh b/milena/mln/accu/essential.hh
index 18498f2..e8c57cc 100644
--- a/milena/mln/accu/essential.hh
+++ b/milena/mln/accu/essential.hh
@@ -33,6 +33,7 @@
/// File that includes the most useful accumulator types.
# include <mln/accu/bbox.hh>
+# include <mln/accu/center.hh>
# include <mln/accu/count.hh>
# include <mln/accu/histo.hh>
# include <mln/accu/max.hh>
diff --git a/milena/mln/debug/all.hh b/milena/mln/debug/all.hh
index a17fb37..a0a27c6 100644
--- a/milena/mln/debug/all.hh
+++ b/milena/mln/debug/all.hh
@@ -1,4 +1,5 @@
// 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
@@ -28,10 +29,9 @@
#ifndef MLN_DEBUG_ALL_HH
# define MLN_DEBUG_ALL_HH
-/*! \file mln/debug/all.hh
- *
- * \brief File that includes all debug-related routines.
- */
+/// \file mln/debug/all.hh
+///
+/// File that includes all debug-related routines.
namespace mln
@@ -48,7 +48,7 @@ namespace mln
# include <mln/debug/colorize.hh>
# include <mln/debug/format.hh>
-//# include <mln/debug/graph.hh>
+# include <mln/debug/draw_graph.hh>
# include <mln/debug/iota.hh>
# include <mln/debug/println.hh>
# include <mln/debug/println_with_border.hh>
diff --git a/milena/mln/debug/graph.hh b/milena/mln/debug/draw_graph.hh
similarity index 53%
rename from milena/mln/debug/graph.hh
rename to milena/mln/debug/draw_graph.hh
index e92b802..159b974 100644
--- a/milena/mln/debug/graph.hh
+++ b/milena/mln/debug/draw_graph.hh
@@ -30,7 +30,10 @@
# define MLN_DEBUG_DRAW_GRAPH_HH
/// \file mln/debug/graph.hh
+///
/// \brief Draw an (classical) image from a mln::graph_image.
+///
+/// \todo write a version for graph images.
# include <mln/pw/image.hh>
# include <mln/level/fill.hh>
@@ -43,83 +46,56 @@ namespace mln
namespace debug
{
- /*! \brief Draw an image \p ima from a mln::p_graph \p pg, with
- * value \p vertex_v for vertices, value \p edge_v for edges and 0 for
- * the background.
- *
- * \param[in,out] ima The image to be drawn.
- * \param[in] pv The p_vertices which contains vertices positions.
- * \param[in] vertex_v The value to assign to pixels which contains
- * vertices.
- * \param[in] edge_v The value to assign to pixels which contains
- * edges.
- */
+ /// Draw an image \p ima from a mln::p_graph \p pg, with
+ /// value \p vertex_v for vertices, value \p edge_v for edges and 0 for
+ /// the background.
+ ///
+ /// \param[in,out] ima The image to be drawn.
+ /// \param[in] pv The p_vertices which contains vertices positions.
+ /// \param[in] vertex_v The value to assign to pixels which contains
+ /// vertices.
+ /// \param[in] edge_v The value to assign to pixels which contains
+ /// edges.
template <typename I, typename G, typename F>
void
draw_graph(Image<I>& ima, const p_vertices<G, F>& pv,
mln_value(I) vertex_v, mln_value(I) edge_v);
- /*! \brief Draw an image \p ima from a mln::graph_image \p gi.
- *
- * The background is filled with value 0.
- *
- * \param[in,out] ima The image to be drawn.
- * \param[in] gi The graph_image which contains the vertices,
- * edges positions and the values of it.
- * \param[in] edge_v The value to assign to pixels which contains
- * edges, defaulting to 1.
- */
- // FIXME: The type of the last argument cannot always been
- // constructed from `int'! We should remove this last argument.
-// template <typename I, typename P, typename V>
-// void
-// draw_graph(Image<I>& ima, const graph_image<P, V>& gi,
-// mln_value(I) edge_v = 1);
+
# ifndef MLN_INCLUDE_ONLY
+
+
// FIXME: Add assertions on the size of the image: it must be large
// enough to hold the representation of the graph/graph_image.
template <typename I, typename G, typename F>
inline
void
- draw_graph(Image<I>& ima, const p_vertices<G, F>& pv,
- mln_value(I) vertex_v, mln_value(I) edge_v)
+ draw_graph(Image<I>& ima,
+ const p_vertices<G, F>& pv,
+ mln_value(I) vertex_v,
+ mln_value(I) edge_v)
{
- // Debug the background.
- level::fill(ima, 0);
+ // Fill the background.
+ level::fill(ima, literal::black);
- // Debug the lines (edges).
+ // Draw edges.
const G& g = pv.graph();
typedef p_vertices<G, F> pv_t;
mln_edge_iter(G) ei(g);
for_all(ei)
draw::line(exact(ima), pv(ei.v1()), pv(ei.v2()), edge_v);
- // Debug the points (vertices).
+ // Draw vertices.
mln_piter(pv_t) p(pv);
for_all(p)
- exact(ima)(p) = vertex_v;
+ if (exact(ima).has(p))
+ exact(ima)(p) = vertex_v;
}
-/*
- template <typename I, typename P, typename V>
- inline
- void
- draw_graph(Image<I>& ima, const graph_image<P, V>& gi,
- mln_value(I) edge_v)
- {
- // Debug the background.
- level::fill(ima, 0);
- // Debug the lines (edges).
- for (unsigned l = 0; l < gi.domain().nedges(); ++l)
- line (exact(ima), gi.vertex1(l), gi.vertex2(l), edge_v);
- // Debug the points (vertices).
- for (unsigned p = 0; p < gi.domain().nvertices(); ++p)
- exact(ima)(gi.domain().point_from_id(p)) = gi.vertex_values()[p];
- }
-*/
+
# endif // ! MLN_INCLUDE_ONLY
@@ -127,4 +103,4 @@ namespace mln
} // end of namespace mln
-#endif // MLN_DEBUG_DRAW_GRAPH_HH
+#endif // ! MLN_DEBUG_DRAW_GRAPH_HH
diff --git a/milena/mln/debug/essential.hh b/milena/mln/debug/essential.hh
index 122a6c0..a28563b 100644
--- a/milena/mln/debug/essential.hh
+++ b/milena/mln/debug/essential.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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
@@ -28,10 +28,9 @@
#ifndef MLN_DEBUG_ESSENTIAL_HH
# define MLN_DEBUG_ESSENTIAL_HH
-/*! \file mln/debug/essential.hh
- *
- * \brief File that includes essential debug-related routines.
- */
+/// \file mln/debug/essential.hh
+///
+/// File that includes essential debug-related routines.
# include <mln/debug/all.hh>
diff --git a/milena/mln/make/all.hh b/milena/mln/make/all.hh
index 910d943..5dc232c 100644
--- a/milena/mln/make/all.hh
+++ b/milena/mln/make/all.hh
@@ -48,6 +48,7 @@ namespace mln
# include <mln/make/box3d.hh>
# include <mln/make/dpoint2d_h.hh>
# include <mln/make/dual_neighb.hh>
+# include <mln/make/graph.hh>
# include <mln/make/image.hh>
# include <mln/make/image2d.hh>
# include <mln/make/mat.hh>
diff --git a/milena/mln/make/essential.hh b/milena/mln/make/essential.hh
index 856e75a..33aa0e7 100644
--- a/milena/mln/make/essential.hh
+++ b/milena/mln/make/essential.hh
@@ -29,10 +29,9 @@
#ifndef MLN_MAKE_ESSENTIAL_HH
# define MLN_MAKE_ESSENTIAL_HH
-/*! \file mln/make/essential.hh
- *
- * \brief File that includes essential make routines.
- */
+/// \file mln/make/essential.hh
+///
+/// File that includes essential make routines.
# include <mln/make/dual_neighb.hh>
# include <mln/make/image.hh>
diff --git a/milena/mln/make/graph.hh b/milena/mln/make/graph.hh
new file mode 100644
index 0000000..c3ae618
--- /dev/null
+++ b/milena/mln/make/graph.hh
@@ -0,0 +1,159 @@
+// 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.
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MAKE_GRAPH_HH
+# define MLN_MAKE_GRAPH_HH
+
+/// \file mln/make/graph.hh
+///
+/// Create a graph from an influence zone image.
+///
+/// \sa transform::influence_zone_geodesic.
+
+# include <mln/util/graph.hh>
+
+namespace mln
+{
+
+ namespace make
+ {
+
+ /// Create a graph from an influence zone image.
+ ///
+ /// \param[in] iz influence zone image.
+ /// \param[in] nlabels number of influence zone in \p iz.
+ ///
+ /// \return util::graph Graph based on the adjacency of the influence zones.
+ template <typename I>
+ util::graph graph(const Image<I>& iz, mln_value(I) nlabels);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ namespace internal
+ {
+
+ template <typename I>
+ void
+ graph_tests(const Image<I>& iz, mln_value(I))
+ {
+ mln_precondition(exact(iz).has_data());
+
+ (void) iz;
+ }
+
+ } // end of namespace mln::make::internal
+
+
+
+ namespace impl
+ {
+
+ namespace generic
+ {
+
+ template <typename I>
+ util::graph
+ graph(const Image<I>& iz_, mln_value(I) nlabels)
+ {
+ trace::entering("make::impl::generic::graph");
+
+ internal::graph_tests(iz_, nlabels);
+ const I& iz = exact(iz_);
+
+ util::graph g;
+ g.add_vertices(nlabels + 1);
+
+ mln_piter(I) p(iz.domain());
+ for_all(p)
+ {
+ // Checking 'forward' neighboors and create an edge if necessary.
+ for (unsigned dim = 0; dim < mln_site_(I)::dim; ++dim)
+ {
+ mln_site(I) n = p;
+ ++n[dim];
+
+ // FIXME: check that calling iz.domain().has() is correct
+ // and that we don't prefer iz.has().
+ if (iz.domain().has(n) && iz(p) != iz(n))
+ g.add_edge(iz(p), iz(n));
+ }
+ }
+
+ trace::exiting("make::impl::generic::graph");
+ return g;
+ }
+
+ } // end of namespace mln::make::impl::generic
+
+ } // end of namespace mln::make::impl
+
+
+
+ namespace internal
+ {
+
+ template <typename I>
+ util::graph
+ graph_dispatch(const Image<I>& iz, mln_value(I) nlabels)
+ {
+ return make::impl::generic::graph(iz, nlabels);
+ }
+
+ } // end of namespace mln::make::internal
+
+
+
+ // Facade
+
+ template <typename I>
+ inline
+ util::graph
+ graph(const Image<I>& iz, mln_value(I) nlabels)
+ {
+ trace::entering("make::graph");
+
+ internal::graph_tests(iz, nlabels);
+
+ util::graph g = internal::graph_dispatch(iz, nlabels);
+
+ trace::exiting("make::graph");
+ return g;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+
+ } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MAKE_GRAPH_HH
diff --git a/milena/mln/util/array.hh b/milena/mln/util/array.hh
index 66b41a8..5f49839 100644
--- a/milena/mln/util/array.hh
+++ b/milena/mln/util/array.hh
@@ -1,4 +1,4 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory
+// 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
@@ -28,13 +28,12 @@
#ifndef MLN_UTIL_ARRAY_HH
# define MLN_UTIL_ARRAY_HH
-/*! \file mln/util/array.hh
- *
- * \brief Definition of mln::util::array.
- *
- * \todo Zed: Add a lazy removal method (based on an extra attribute
- * std::vector<bool> has_). Then add a purge/compress method.
- */
+/// \file mln/util/array.hh
+///
+/// Definition of mln::util::array.
+///
+/// \todo Zed: Add a lazy removal method (based on an extra attribute
+/// std::vector<bool> has_). Then add a purge/compress method.
# include <vector>
# include <iostream>
@@ -55,15 +54,12 @@ namespace mln
template <typename T> class array_bkd_iter;
- /*! \brief A dynamic array class.
- *
- *
- *
- * Elements are stored by copy. Implementation is lazy.
- *
- * The parameter \c T is the element type, which shall not be
- * const-qualified.
- */
+ /// A dynamic array class.
+ ///
+ /// Elements are stored by copy. Implementation is lazy.
+ ///
+ /// The parameter \c T is the element type, which shall not be
+ /// const-qualified.
template <typename T>
class array : public Object< mln::util::array<T> >
{
@@ -141,7 +137,7 @@ namespace mln
/// Operator<<.
template <typename T>
std::ostream& operator<<(std::ostream& ostr,
- const mln::util::array<T>& a);
+ const mln::util::array<T>& a);
@@ -240,7 +236,6 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
-
// util::array<T>
@@ -546,7 +541,7 @@ namespace mln
template <typename T>
std::ostream& operator<<(std::ostream& ostr,
- const mln::util::array<T>& a)
+ const mln::util::array<T>& a)
{
ostr << '[';
const unsigned n = a.nelements();
diff --git a/milena/mln/util/edge.hh b/milena/mln/util/edge.hh
index a6ce803..ba34a12 100644
--- a/milena/mln/util/edge.hh
+++ b/milena/mln/util/edge.hh
@@ -299,7 +299,7 @@ namespace mln
std::ostream&
operator<<(std::ostream& ostr, const edge<G>& p)
{
- return ostr << p.id();
+ return ostr << "(" << p.v1() << "," << p.v2() << ")";
}
template <typename G>
diff --git a/milena/mln/util/graph.hh b/milena/mln/util/graph.hh
index 1b22c43..7c003a2 100644
--- a/milena/mln/util/graph.hh
+++ b/milena/mln/util/graph.hh
@@ -62,6 +62,9 @@ namespace mln
typedef std::set<util::ord_pair<unsigned> > edges_set_t;
data();
+ /// Constructor.
+ /// Allocate enough space in order to support \p nvertices vertices.
+ data(unsigned nvertices);
~data();
/// The vertices.
@@ -134,19 +137,29 @@ namespace mln
/// \}
/// \}
+ /// Constructor.
graph();
+ /// Construct a graph with \p nvertices vertices.
+ graph(unsigned nvertices);
/// Vertex oriented.
/// \{
+
/// Shortcuts factoring the insertion of vertices and edges.
/// \{
+
/// Add a vertex.
///
/// \return The id of the new vertex.
unsigned add_vertex();
+ /// Add \p n vertices to the graph.
+ ///
+ /// \return A range of vertex ids.
+ std::pair<unsigned, unsigned> add_vertices(unsigned n);
+
/// Return the vertex whose id is \a v.
/// \{
vertex_t vertex(unsigned id_v) const;
@@ -239,6 +252,12 @@ namespace mln
}
inline
+ data<util::graph>::data(unsigned nvertices)
+ {
+ vertices_.resize(nvertices);
+ }
+
+ inline
data<util::graph>::~data()
{
}
@@ -254,6 +273,12 @@ namespace mln
this->data_ = new mln::internal::data<util::graph>();
}
+ inline
+ graph::graph(unsigned nvertices)
+ {
+ this->data_ = new mln::internal::data<util::graph>(nvertices);
+ }
+
/*---------------.
| Vertex related |
`---------------*/
@@ -270,6 +295,18 @@ namespace mln
}
inline
+ std::pair<unsigned, unsigned>
+ graph::add_vertices(unsigned n)
+ {
+ /* FIXME: This is not thread-proof (these two lines should
+ form an atomic section). */
+ data_->vertices_.resize(data_->vertices_.size() + n);
+
+ return std::make_pair(v_nmax() - n,
+ v_nmax() - 1);
+ }
+
+ inline
graph::vertex_t
graph::vertex(unsigned id_v) const
{
--
1.5.6.5
* apps/statues/mesh-complex-segm.cc: New.
* apps/statues/Makefile.am (bin_PROGRAMS): Add mesh-complex-segm.
(mesh_complex_segm_SOURCES): New.
* apps/statues/test.in: Exercise mesh-complex-segm.
* mln/core/alias/complex_image.hh
(mln::unsigned_2complex_image3df): New typedef.
---
milena/ChangeLog | 11 ++
milena/apps/statues/Makefile.am | 8 ++
milena/apps/statues/mesh-complex-segm.cc | 163 ++++++++++++++++++++++++++++++
milena/apps/statues/test.in | 4 +
milena/mln/core/alias/complex_image.hh | 11 ++-
5 files changed, 195 insertions(+), 2 deletions(-)
create mode 100644 milena/apps/statues/mesh-complex-segm.cc
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 9224c7f..e35b296 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,5 +1,16 @@
2008-11-19 Roland Levillain <roland(a)lrde.epita.fr>
+ New application: surface segmentation using complex-based images.
+
+ * apps/statues/mesh-complex-segm.cc: New.
+ * apps/statues/Makefile.am (bin_PROGRAMS): Add mesh-complex-segm.
+ (mesh_complex_segm_SOURCES): New.
+ * apps/statues/test.in: Exercise mesh-complex-segm.
+ * mln/core/alias/complex_image.hh
+ (mln::unsigned_2complex_image3df): New typedef.
+
+2008-11-19 Roland Levillain <roland(a)lrde.epita.fr>
+
* mln/core/site_set/p_array.hh (nsites): Fix return type.
2008-11-18 Roland Levillain <roland(a)lrde.epita.fr>
diff --git a/milena/apps/statues/Makefile.am b/milena/apps/statues/Makefile.am
index 971a4ec..d1e65f7 100644
--- a/milena/apps/statues/Makefile.am
+++ b/milena/apps/statues/Makefile.am
@@ -53,4 +53,12 @@ mesh_max_curv_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS_trimesh)
mesh_max_curv_LDFLAGS = $(LDFLAGS_trimesh)
mesh_max_curv_LDADD = $(LDADD_trimesh)
+## ---------------------------------------------------- ##
+## Complex-based applications, independent of Trimesh. ##
+## ---------------------------------------------------- ##
+
+bin_PROGRAMS += mesh-complex-segm
+mesh_complex_segm_SOURCES = mesh-complex-segm.cc
+
+
TESTS = test
diff --git a/milena/apps/statues/mesh-complex-segm.cc b/milena/apps/statues/mesh-complex-segm.cc
new file mode 100644
index 0000000..05fffe0
--- /dev/null
+++ b/milena/apps/statues/mesh-complex-segm.cc
@@ -0,0 +1,163 @@
+// 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 apps/statues/mesh-complex-segm.cc
+/// \brief A program performing a WST-based segmentation of the
+/// surface of the (triangle) mesh of a statue, using a complex-based
+/// image.
+
+#include <cstdlib>
+#include <cmath>
+
+#include <utility>
+#include <iostream>
+
+#include <mln/core/image/complex_image.hh>
+#include <mln/core/image/complex_neighborhoods.hh>
+
+#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/literal/white.hh>
+
+#include <mln/io/off/load.hh>
+#include <mln/io/off/save.hh>
+
+
+
+int main(int argc, char* argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "usage: " << argv[0] << " input.off lambda output.off"
+ << std::endl;
+ exit(1);
+ }
+
+ std::string input_filename = argv[1];
+ unsigned lambda = atoi(argv[2]);
+ std::string output_filename = argv[3];
+
+ /*----------------.
+ | Complex image. |
+ `----------------*/
+
+ // Image type.
+ typedef mln::float_2complex_image3df ima_t;
+ // Dimension of the image (and therefore of the complex).
+ static const unsigned D = ima_t::dim;
+ // Geometry of the image.
+ typedef mln_geom_(ima_t) G;
+
+ ima_t input;
+ mln::io::off::load(input, input_filename);
+
+ // Values on edges.
+
+ /* FIXME: To be improved: instead of computing the curvature on
+ edges from a mean of the curvature on adjacent polygons, compute
+ it directly from the curvature on vertices. We should probably
+ integrate Trimesh's curvature computation into Milena. */
+ mln::p_n_faces_fwd_piter<D, G> e(input.domain(), 1);
+ typedef mln::complex_higher_neighborhood<D, G> adj_polygons_nbh_t;
+ adj_polygons_nbh_t adj_polygons_nbh;
+ mln_niter_(adj_polygons_nbh_t) p(adj_polygons_nbh, e);
+ // Iterate on edges (1-faces).
+ for_all(e)
+ {
+ float s = 0.0f;
+ unsigned n = 0;
+ for_all(p)
+ {
+ s += input(p);
+ ++n;
+ }
+ input(e) = s / n;
+ // An edge should be adjacent to two polygons at most.
+ mln_invariant(n <= 2);
+ }
+
+ /*-----------------.
+ | Simplification. |
+ `-----------------*/
+
+ /// Adjancent edges are connected by shared polygons.
+ typedef
+ mln::complex_higher_dim_connected_n_face_neighborhood<D, G>
+ adj_edges_nbh_t;
+ adj_edges_nbh_t adj_edges_nbh;
+
+ ima_t closed_input(input.domain());
+ mln::morpho::closing_area(input, adj_edges_nbh, lambda, closed_input);
+
+ /*------.
+ | WST. |
+ `------*/
+
+ /* FIXME: Note that the WST is either doing too much work, since we
+ have not constrained the domain of the image to 1-faces only.
+
+ It would be great if we could use something like this:
+
+ closed_input | mln::p_faces<1, D, G>(closed_input.domain())
+
+ as input of the WST. */
+
+ // Compute the WST on edges.
+ typedef unsigned wst_val_t;
+ wst_val_t nbasins;
+ typedef mln::unsigned_2complex_image3df wst_ima_t;
+ wst_ima_t wshed =
+ mln::morpho::meyer_wst(closed_input, adj_edges_nbh, nbasins);
+ std::cout << "nbasins = " << nbasins << std::endl;
+
+ // Label polygons (i.e., propagate labels from edges to polygons).
+ for_all(e)
+ if (wshed(e) != 0)
+ for_all(p)
+ wshed(p) = wshed(e);
+
+ /*---------.
+ | Output. |
+ `---------*/
+
+ mln::rgb8_2complex_image3df output(wshed.domain());
+ mln::level::fill(output, mln::literal::white);
+
+ // FIXME: Use a colorize functor instead.
+ // Choose random colors for each basin number.
+ std::vector<mln::value::rgb8> basin_color (nbasins + 1);
+ for (unsigned i = 0; i <= nbasins; ++i)
+ basin_color[i] = mln::value::rgb8(random() % 256,
+ random() % 256,
+ random() % 256);
+ mln_piter_(ima_t) f(wshed.domain());
+ for_all(f)
+ output(f) = basin_color[wshed(f)];
+
+ mln::io::off::save(output, output_filename);
+}
diff --git a/milena/apps/statues/test.in b/milena/apps/statues/test.in
index 181a1fd..92c9d31 100755
--- a/milena/apps/statues/test.in
+++ b/milena/apps/statues/test.in
@@ -7,3 +7,7 @@ mesh_dir=@top_srcdir@/milena/mesh
time ./mesh-segm $mesh_dir/socket.off 25 socket-segm.off
time ./mesh-segm $mesh_dir/teapot.off 50 teapot-segm.off
time ./mesh-segm $mesh_dir/bunny-holefilled.off 500 bunny-holefilled-segm.off
+
+time ./mesh-complex-segm $mesh_dir/socket-max-curv.off 25 socket-max-curv-segm.off
+time ./mesh-complex-segm $mesh_dir/teapot-max-curv.off 50 teapot-max-curv-segm.off
+time ./mesh-complex-segm $mesh_dir/bunny-holefilled-pinv-curv.off 500 bunny-holefilled-pinv-curv-segm.off
diff --git a/milena/mln/core/alias/complex_image.hh b/milena/mln/core/alias/complex_image.hh
index 9dc5956..6336d6b 100644
--- a/milena/mln/core/alias/complex_image.hh
+++ b/milena/mln/core/alias/complex_image.hh
@@ -47,12 +47,19 @@ namespace mln
mln::complex_image<2, mln::space_2complex_geometry, bool>
bin_2complex_image3df;
+ /// \brief Type alias for an 8-bit grey-level image based on a
+ /// 2-complex, where 0-faces are located at floating-point
+ /// 3-dimensional points.
+ typedef
+ mln::complex_image<2, mln::space_2complex_geometry, mln::value::int_u8>
+ int_u8_2complex_image3df;
+
/// \brief Type alias for a grey-level image based on a 2-complex,
/// where 0-faces are located at floating-point 3-dimensional
/// points.
typedef
- mln::complex_image<2, mln::space_2complex_geometry, mln::value::int_u8>
- int_u8_2complex_image3df;
+ mln::complex_image<2, mln::space_2complex_geometry, unsigned>
+ unsigned_2complex_image3df;
/// \brief Type alias for a floating-point image based on a
/// 2-complex, where 0-faces are located at floating-point
--
1.6.0.1