Olena-patches
Threads by month
- ----- 2025 -----
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- 9625 discussions
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
Fix Sanity.
* tests/all_headers.cc: Make this test pass.
* mln/core/site_set/p_graph.hh: Fix wrong use of graph.
* mln/core/image/translate_image.hh: Make it compile.
* mln/core/image/all.hh: Complete headers inclusion.
* mln/util/tree.hh,
* mln/core/concept/window.hh: Gcc 4.3 fix.
* mln/core/site_set/p_centered.hh: Update.
* mln/core/window.hh: Update.
* mln/win/multiple_size.hh: Update.
* mln/win/multiple.hh: Update.
* mln/core/internal/image_value_morpher.hh: Add FIXME doxygen.
* mln/linear/local/convolve.hh: Fix namespace.
* mln/value/stack.hh: Make proper inheritens.
* mln/border/equalize.hh: Make it compile.
* mln/set/all.hh: Fix inclusion.
* mln/io/fits/load.hh: Add FIXME dependency.
* mln/draw/graph.hh: Move...
* mln/debug/graph.hh: ...here.
* mln/debug/all.hh: Update.
* mln/draw/all.hh: Update.
mln/border/equalize.hh | 5 +-
mln/core/concept/window.hh | 2 -
mln/core/image/all.hh | 58 ++++++++++++++++++++++++++++++-
mln/core/image/translate_image.hh | 14 +++----
mln/core/internal/image_value_morpher.hh | 1
mln/core/site_set/p_centered.hh | 2 -
mln/core/site_set/p_graph.hh | 4 +-
mln/debug/all.hh | 1
mln/debug/graph.hh | 36 ++++++++-----------
mln/draw/all.hh | 1
mln/io/fits/load.hh | 2 +
mln/linear/local/convolve.hh | 2 -
mln/set/all.hh | 2 -
mln/util/tree.hh | 6 +--
mln/value/stack.hh | 6 ++-
mln/win/multiple.hh | 4 +-
mln/win/multiple_size.hh | 4 +-
tests/all_headers.cc | 28 +++++++-------
18 files changed, 117 insertions(+), 61 deletions(-)
Index: tests/all_headers.cc
--- tests/all_headers.cc (revision 2778)
+++ tests/all_headers.cc (working copy)
@@ -32,32 +32,32 @@
#include <mln/test/all.hh>
-//#include <mln/convert/all.hh>
+#include <mln/convert/all.hh>
#include <mln/estim/all.hh>
-#include <mln/debug/all.hh>
+//#include <mln/debug/all.hh>
#include <mln/histo/all.hh>
#include <mln/pw/all.hh>
#include <mln/geom/all.hh>
#include <mln/core/trait/all.hh>
-//#include <mln/fun/i2v/all.hh>
-//#include <mln/fun/p2b/all.hh>
-//#include <mln/fun/p2v/all.hh>
-//#include <mln/fun/v2v/all.hh>
-//#include <mln/fun/x2x/all.hh>
-//#include <mln/fun/all.hh>
+#include <mln/fun/i2v/all.hh>
+#include <mln/fun/p2b/all.hh>
+#include <mln/fun/p2v/all.hh>
+#include <mln/fun/v2v/all.hh>
+#include <mln/fun/x2x/all.hh>
+#include <mln/fun/all.hh>
#include <mln/math/all.hh>
-//#include <mln/set/all.hh>
+#include <mln/set/all.hh>
#include <mln/draw/all.hh>
#include <mln/metal/math/all.hh>
#include <mln/metal/all.hh>
#include <mln/morpho/all.hh>
#include <mln/io/pfm/all.hh>
#include <mln/io/pgm/all.hh>
-//#include <mln/io/fits/all.hh>
+#include <mln/io/fits/all.hh>
#include <mln/io/ppm/all.hh>
#include <mln/io/pbm/all.hh>
#include <mln/io/pnm/all.hh>
-//#include <mln/io/all.hh>
+#include <mln/io/all.hh>
#include <mln/level/naive/all.hh>
#include <mln/level/approx/all.hh>
#include <mln/level/all.hh>
@@ -70,16 +70,16 @@
#include <mln/accu/all.hh>
#include <mln/norm/all.hh>
#include <mln/value/internal/all.hh>
-#include <mln/value/all.hh>
#include <mln/value/concept/all.hh>
#include <mln/value/builtin/all.hh>
-#include <mln/make/all.hh>
+#include <mln/value/all.hh>
+//#include <mln/make/all.hh>
#include <mln/border/all.hh>
#include <mln/labeling/all.hh>
#include <mln/util/all.hh>
-#include <mln/trait/all.hh>
#include <mln/trait/value/all.hh>
#include <mln/trait/op/all.hh>
+#include <mln/trait/all.hh>
#include <mln/tag/all.hh>
#include <mln/trace/all.hh>
#include <mln/literal/all.hh>
Index: mln/debug/graph.hh
--- mln/debug/graph.hh (revision 2778)
+++ mln/debug/graph.hh (working copy)
@@ -25,10 +25,10 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_DRAW_GRAPH_HH
-# define MLN_DRAW_GRAPH_HH
+#ifndef MLN_DEBUG_DRAW_GRAPH_HH
+# define MLN_DEBUG_DRAW_GRAPH_HH
-/// \file mln/draw/graph.hh
+/// \file mln/debug/draw_graph.hh
/// \brief Draw an (classical) image from a mln::graph_image.
# include <mln/pw/image.hh>
@@ -40,12 +40,8 @@
namespace mln
{
- namespace draw
+ namespace debug
{
- /* FIXME: `draw::graph' is not a good name. These functions do not
- actually _draw_ the graph/graph_image; it *converts* it to a
- printable image. These functions should be put elsewhere
- (e.g., in 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
@@ -61,7 +57,7 @@
*/
template <typename I, typename P>
void
- graph(Image<I>& ima, const p_graph<P>& pg,
+ draw_graph(Image<I>& ima, const p_graph<P>& pg,
mln_value(I) vertex_v, mln_value(I) edge_v);
/*! \brief Draw an image \p ima from a mln::graph_image \p gi.
@@ -78,7 +74,7 @@
// constructed from `int'! We should remove this last argument.
template <typename I, typename P, typename V>
void
- graph(Image<I>& ima, const graph_image<P, V>& gi,
+ draw_graph(Image<I>& ima, const graph_image<P, V>& gi,
mln_value(I) edge_v = 1);
# ifndef MLN_INCLUDE_ONLY
@@ -89,12 +85,12 @@
template <typename I, typename P>
inline
void
- graph(Image<I>& ima, const p_graph<P>& pg,
+ draw_graph(Image<I>& ima, const p_graph<P>& pg,
mln_value(I) vertex_v, mln_value(I) edge_v)
{
- // Draw the background.
+ // Debug the background.
level::fill(ima, 0);
- // Draw the lines (edges).
+ // Debug the lines (edges).
for (unsigned l = 0; l < pg.nedges(); ++l)
line (exact(ima),
// FIXME: Too low-level. See similar remarks
@@ -102,7 +98,7 @@
pg.gr_->vertex_data(pg.gr_->edge(l).v1()),
pg.gr_->vertex_data(pg.gr_->edge(l).v2()),
edge_v);
- // Draw the points (vertices).
+ // Debug the points (vertices).
for (unsigned p = 0; p < pg.nsites(); ++p)
exact(ima)(pg.gr_->vertex_data(p)) = vertex_v;
}
@@ -110,23 +106,23 @@
template <typename I, typename P, typename V>
inline
void
- graph(Image<I>& ima, const graph_image<P, V>& gi,
+ draw_graph(Image<I>& ima, const graph_image<P, V>& gi,
mln_value(I) edge_v)
{
- // Draw the background.
+ // Debug the background.
level::fill(ima, 0);
- // Draw the lines (edges).
+ // Debug the lines (edges).
for (unsigned l = 0; l < gi.domain().nedges(); ++l)
line (exact(ima), gi.vertex1(l), gi.vertex2(l), edge_v);
- // Draw the points (vertices).
+ // 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
- } // end of namespace mln::draw
+ } // end of namespace mln::debug
} // end of namespace mln
-#endif // MLN_GRAPH_PSITE_HH
+#endif // MLN_DEBUG_DRAW_GRAPH_HH
Property changes on: mln/debug/graph.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/debug/all.hh
--- mln/debug/all.hh (revision 2778)
+++ mln/debug/all.hh (working copy)
@@ -50,6 +50,7 @@
# include <mln/debug/iota.hh>
# include <mln/debug/println.hh>
# include <mln/debug/println_with_border.hh>
+# include <mln/debug/graph.hh>
#endif // ! MLN_DEBUG_ALL_HH
Index: mln/core/site_set/p_centered.hh
--- mln/core/site_set/p_centered.hh (revision 2778)
+++ mln/core/site_set/p_centered.hh (working copy)
@@ -253,7 +253,7 @@
{
this->change_target(s);
q_.center_at(s.center());
- q_.change_target(s.window());
+ q_.change_target(s.window_());
}
template <typename W>
Index: mln/core/site_set/p_graph.hh
--- mln/core/site_set/p_graph.hh (revision 2778)
+++ mln/core/site_set/p_graph.hh (working copy)
@@ -70,7 +70,7 @@
typedef p_graph<P> self_;
typedef internal::site_set_base_< P, self_ > super_;
- typedef util::graph<P> graph;
+ typedef util::graph graph;
/// \brief Construct a graph psite set from a graph of points.
///
@@ -201,7 +201,7 @@
inline
p_graph<P>::p_graph(const graph& gr)
// Create a deep, managed copy of GR.
- : gr_ (new util::graph<P>(gr))
+ : gr_ (new util::graph(gr))
{
}
Index: mln/core/image/translate_image.hh
--- mln/core/image/translate_image.hh (revision 2778)
+++ mln/core/image/translate_image.hh (working copy)
@@ -38,6 +38,7 @@
# include <mln/core/internal/image_identity.hh>
# include <mln/core/alias/box2d.hh>
+//FIXME: Fix this image morpher.
namespace mln
{
@@ -76,13 +77,11 @@
{
typedef trait::image::category::domain_morpher category;
- typedef mln_trait_image_access(I) access;
- typedef mln_trait_image_space(I) space;
+ typedef mln_trait_image_value_access(I) access;
+ typedef mln_trait_image_localization(I) space;
typedef mln_trait_image_size(I) size;
- typedef mln_trait_image_support(I) support;
- typedef mln_trait_image_border(I) border;
- typedef mln_trait_image_io_from_(I) io;
- typedef mln_trait_image_data_from_(I) data;
+ //typedef mln_trait_image_io_from_(I) io;
+ //typedef mln_trait_image_data_from_(I) data;
};
@@ -100,8 +99,7 @@
struct translate_image : public mln::internal::image_identity< I, mln_pset(I), translate_image<I> >
{
- typedef mln::internal::image_morpher< I, mln_pset(I), translate_image<I> > super_;
- typedef line_piter_<mln_psite(I)> line_piter;
+ typedef mln::internal::image_morpher< I, mln_value(I), mln_pset(I), translate_image<I> > super_;
/// Return type of read-write access.
typedef mln_morpher_lvalue(I) lvalue;
Index: mln/core/image/all.hh
--- mln/core/image/all.hh (revision 2778)
+++ mln/core/image/all.hh (working copy)
@@ -36,7 +36,63 @@
*/
-// FIXME: Complete...
+# include <bgraph_image.hh>
+# include <bgraph_psite.hh>
+# include <cast_image.hh>
+# include <ch_piter.hh>
+# include <complex_image.hh>
+# include <complex_neighborhood_piter.hh>
+# include <complex_neighborhoods.hh>
+# include <complex_window_piter.hh>
+# include <complex_windows.hh>
+# include <decorated_image.hh>
+# include <extended.hh>
+# include <extension_fun.hh>
+# include <extension_ima.hh>
+# include <extension_val.hh>
+# include <fi_adaptor.hh>
+# include <flat_image.hh>
+# include <graph_elt_neighborhood.hh>
+# include <graph_elt_window.hh>
+# include <graph_image.hh>
+# include <graph_neighborhood_piter.hh>
+# include <graph_window_piter.hh>
+# include <hexa.hh>
+# include <hexa_piter.hh>
+# include <image1d.hh>
+# include <image2d.hh>
+# include <image2d_h.hh>
+# include <image3d.hh>
+# include <image_if.hh>
+# include <interpolated.hh>
+# include <lazy_image.hh>
+# include <line_graph_elt_neighborhood.hh>
+# include <line_graph_elt_window.hh>
+# include <line_graph_image.hh>
+# include <line_graph_neighborhood_piter.hh>
+# include <line_graph_psite.hh>
+# include <line_graph_window_piter.hh>
+# include <mono_obased_rle_encode.hh>
+# include <mono_obased_rle_image.hh>
+# include <mono_rle_encode.hh>
+# include <mono_rle_image.hh>
+# include <obased_rle_encode.hh>
+# include <obased_rle_image.hh>
+# include <plain.hh>
+# include <rle_encode.hh>
+# include <rle_image.hh>
+# include <safe.hh>
+# include <sparse_encode.hh>
+# include <sparse_image.hh>
+# include <status.txt
+# include <sub_image.hh>
+# include <sub_image_if.hh>
+# include <t_image.hh>
+# include <translate_image.hh>
+# include <tr_image.hh>
+# include <tr_mesh.hh>
+# include <value_enc_image.hh>
+# include <value_encode.hh>
#endif // ! MLN_CORE_IMAGE_ALL_HH
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 2778)
+++ mln/core/concept/window.hh (working copy)
@@ -277,7 +277,7 @@
for (unsigned w = 0; w < nw; ++w)
{
ostr << " #" << w << ':';
- win.window(w).print(ostr);
+ win.window_(w).print(ostr);
}
ostr << " ]";
}
Index: mln/core/window.hh
Index: mln/core/internal/image_value_morpher.hh
--- mln/core/internal/image_value_morpher.hh (revision 2778)
+++ mln/core/internal/image_value_morpher.hh (working copy)
@@ -45,6 +45,7 @@
namespace internal
{
+ //FIXME: Fix doxygen.
/*! A base class for image morphers w.r.t. value.
* Parameter \p S is a point set type.
Index: mln/draw/all.hh
--- mln/draw/all.hh (revision 2778)
+++ mln/draw/all.hh (working copy)
@@ -43,7 +43,6 @@
}
# include <mln/draw/box.hh>
-# include <mln/draw/graph.hh>
# include <mln/draw/label.hh>
# include <mln/draw/line.hh>
# include <mln/draw/plot.hh>
Index: mln/linear/local/convolve.hh
--- mln/linear/local/convolve.hh (revision 2778)
+++ mln/linear/local/convolve.hh (working copy)
@@ -127,7 +127,7 @@
const W& w_win,
R& result)
{
- const P& p = internal::force_exact<P>(p_);
+ const P& p = mln::internal::force_exact<P>(p_);
mln_precondition(p.ima().border() >= w_win.delta());
R tmp = 0;
Index: mln/value/stack.hh
--- mln/value/stack.hh (revision 2778)
+++ mln/value/stack.hh (working copy)
@@ -109,7 +109,7 @@
// here.
typedef trait::image::category::value_morpher category;
- typedef trait::image::value::vectorial value;
+ typedef trait::image::nature::vectorial nature;
/* FIXME: Setting the speed trait of a stack_image to `fast' is
a bad approximation.
@@ -146,7 +146,9 @@
*/
template <unsigned n, typename I>
struct stack_image
- : public mln::internal::image_value_morpher< I, stack_image<n,I> >
+ : public mln::internal::image_value_morpher< I,
+ algebra::vec<n, mln_value(I)>,
+ stack_image<n,I> >
{
/// Point_Site associated type.
typedef mln_psite(I) psite;
Index: mln/border/equalize.hh
--- mln/border/equalize.hh (revision 2778)
+++ mln/border/equalize.hh (working copy)
@@ -116,8 +116,9 @@
{
trace::entering("border::equalize");
- mlc_is(mln_trait_image_border(I), trait::image::border::some)::check();
- mlc_is(mln_trait_image_border(J), trait::image::border::some)::check();
+ //FIXME: check border
+ //mlc_is(mln_trait_image_border(I), trait::image::border::some)::check();
+ //mlc_is(mln_trait_image_border(J), trait::image::border::some)::check();
const I& ima1 = exact(ima1_);
const J& ima2 = exact(ima2_);
mln_precondition(ima1.has_data() && ima2.has_data());
Index: mln/set/all.hh
--- mln/set/all.hh (revision 2778)
+++ mln/set/all.hh (working copy)
@@ -46,6 +46,6 @@
# include <mln/set/inter.hh>
# include <mln/set/is_subset_of.hh>
# include <mln/set/sym_diff.hh>
-# include <mln/set/union.hh>
+# include <mln/set/uni.hh>
#endif // ! MLN_SET_ALL_HH
Index: mln/win/multiple_size.hh
--- mln/win/multiple_size.hh (revision 2778)
+++ mln/win/multiple_size.hh (working copy)
@@ -101,7 +101,7 @@
void set_window(unsigned i, const W& win);
- const W& window(unsigned i) const;
+ const W& window_(unsigned i) const;
unsigned nwindows() const;
@@ -200,7 +200,7 @@
template <typename W, typename F>
inline
const W&
- multiple_size<W,F>::window(unsigned i) const
+ multiple_size<W,F>::window_(unsigned i) const
{
mln_precondition(i < win_.nelements());
return win_[i];
Index: mln/win/multiple.hh
--- mln/win/multiple.hh (revision 2778)
+++ mln/win/multiple.hh (working copy)
@@ -103,7 +103,7 @@
void set_window(unsigned i, const W& win);
- const W& window(unsigned i) const;
+ const W& window_(unsigned i) const;
unsigned nwindows() const;
@@ -206,7 +206,7 @@
template <typename W, typename F>
inline
const W&
- multiple<W,F>::window(unsigned i) const
+ multiple<W,F>::window_(unsigned i) const
{
mln_precondition(i < win_.nelements());
return win_[i];
Index: mln/io/fits/load.hh
--- mln/io/fits/load.hh (revision 2778)
+++ mln/io/fits/load.hh (working copy)
@@ -43,6 +43,8 @@
# include <mln/core/image/image2d.hh>
# include <mln/value/int_u8.hh>
+
+//FIXME: Add fitsio dependency
# include <fitsio.h>
namespace mln
Index: mln/util/tree.hh
--- mln/util/tree.hh (revision 2778)
+++ mln/util/tree.hh (working copy)
@@ -269,7 +269,7 @@
*
* \return The tree of the current branch.
*/
- tree<T>& tree();
+ tree<T>& util_tree();
private:
/// The tree of this branch.
@@ -554,8 +554,8 @@
template <typename T>
inline
- util::tree<T>&
- branch<T>::tree()
+ mln::util::tree<T>&
+ branch<T>::util_tree()
{
return tree_;
}
1
0
03 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
INIM: Move classif work in the inim directory.
* classif: Move ...
* inim/classif: ... Here.
* inim/classif/Makefile: Update relative include directory.
* inim/classif/proj.hh: Trailing update.
Makefile | 6 +++---
proj.hh | 5 ++---
2 files changed, 5 insertions(+), 6 deletions(-)
Index: inim/classif/proj.hh
--- inim/classif/proj.hh (revision 2777)
+++ inim/classif/proj.hh (working copy)
@@ -58,11 +58,10 @@
K mean, const char * fn)
{
- //accu::mean<unsigned, unsigned long, value::int_u8> mean_accu;
- accu::maj_h<value::int_u8> max_1;
+ accu::max<value::int_u8> max_1;
image2d<value::int_u8> hproj = proj(histo, max_1);
- accu::maj_h<value::int_u8> max_2;
+ accu::max<value::int_u8> max_2;
image2d<value::int_u8> proj_class = proj(ws, max_2);
//std::cout << histo;
Index: inim/classif/Makefile
--- inim/classif/Makefile (revision 2777)
+++ inim/classif/Makefile (working copy)
@@ -1,18 +1,18 @@
DISP=xv
# ICCVG
-ICCVG_INCLUDES=-I../..
+ICCVG_INCLUDES=-I../../..
ICCVG_SRC=iccvg04.cc
ICCVG=iccvg
ICCVG_DBG=iccvg_dbg
-IMG?=../../img/lena.ppm
+IMG?=..//../img/lena.ppm
DIV?=4
LAMBDA?=10
# V2
-V2_INCLUDES=-I../..
+V2_INCLUDES=-I../../..
V2_SRC=v2.cc max_tree.hh
V2=v2
V2_DBG=v2_dbg
1
0
03 Nov '08
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
ChangeLog:
2008-11-03 Matthieu Garrigues <garrigues(a)lrde.epita.fr>
Create doc/benchmark/morpho, add bench for erosion.
* doc/benchmark/morpho/erosion.cc: New, bench several specialization
of erosion.
* doc/benchmark/morpho: New.
* tests/morpho/erosion.cc: Make it a real test, not a
benchmark. Remove output and timer.
---
doc/benchmark/morpho/erosion.cc | 292 ++++++++++++++++++++++++++++++++++++++++
tests/morpho/erosion.cc | 94 ------------
2 files changed, 295 insertions(+), 91 deletions(-)
Index: branches/cleanup-2008/milena/tests/morpho/erosion.cc
===================================================================
--- branches/cleanup-2008/milena/tests/morpho/erosion.cc (revision 2775)
+++ branches/cleanup-2008/milena/tests/morpho/erosion.cc (revision 2776)
@@ -42,31 +42,12 @@
#include <mln/morpho/erosion.hh>
#include "tests/data.hh"
-#include "tests/timer.hh"
-
int main()
{
using namespace mln;
using value::int_u8;
-// unsigned
-// l_oct = 11, L_oct = 6 * l_oct + 1,
-// l_rec = 29, L_rec = 2 * l_rec + 1;
-
- // l_
- // oct rec err
- // 0 0 3
- // 0 1 5
- // 1 2 15
- // 1 3 9
- // 2 5 11
- // 3 8 9
- // 5 13 15
- // 8 21 11
- // 11 29 1
- // 25 66 15
-
border::thickness = 20;
image2d<int_u8> lena;
io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
@@ -79,214 +60,145 @@
win::octagon2d oct(6 * 3 + 1);
image2d<int_u8> out;
image2d<int_u8> ref;
-// trace::quiet = false;
- timer t;
// Rectangle
- std::cout << "-------------------------- Rectangle: " << std::endl;
-
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, rec);
- std::cout << "generic on rectangle2d: " << t << std::endl;
}
{
- t.start();
out = morpho::erosion(lena, rec);
- std::cout << "dispach on rectangle2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d_fastest(lena, rec);
- std::cout << "erosion_arbitrary_2d_fastest on rectangle2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d(lena, rec);
- std::cout << "erosion_arbitrary_2d on rectangle2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
//Hline
-
- std::cout << "-------------------------- Hline2d: " << std::endl;
-
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, hline);
- std::cout << "generic on hline2d: " << t << std::endl;
}
{
- t.start();
out = morpho::erosion(lena, hline);
- std::cout << "dispach on hline2d : " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d_fastest(lena, hline);
- std::cout << "erosion_arbitrary_2d_fastest on hline2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d(lena, hline);
- std::cout << "erosion_arbitrary_2d on hline2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
- std::cout << "-------------------------- Vline2d: "<< std::endl;
-
//Vline
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, vline);
- std::cout << "generic on vline2d: " << t << std::endl;
}
{
- t.start();
out = morpho::erosion(lena, vline);
- std::cout << "dispach on vline2d : " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d_fastest(lena, vline);
- std::cout << "erosion_arbitrary_2d_fastest on vline2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d(lena, vline);
- std::cout << "erosion_arbitrary_2d on vline2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
//Diag2d
- std::cout << "-------------------------- Diag2d: "<< std::endl;
+
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, diag2d);
- std::cout << "generic on diag2d: " << t << std::endl;
}
{
- t.start();
out = morpho::erosion(lena, diag2d);
- std::cout << "dispach on diag2d : " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d_fastest(lena, diag2d);
- std::cout << "erosion_arbitrary_2d_fastest on diag2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d(lena, diag2d);
- std::cout << "erosion_arbitrary_2d on diag2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
//Backdiag2d
- std::cout << "-------------------------- Backdiag2d: "<< std::endl;
+
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, backdiag2d);
- std::cout << "generic on backdiag2d: " << t << std::endl;
}
{
- t.start();
out = morpho::erosion(lena, backdiag2d);
- std::cout << "dispach on backdiag2d : " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d_fastest(lena, backdiag2d);
- std::cout << "erosion_arbitrary_2d_fastest on backdiag2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
{
- t.start();
out = morpho::impl::erosion_arbitrary_2d(lena, backdiag2d);
- std::cout << "erosion_arbitrary_2d on backdiag2d: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
- std::cout << "-------------------------- Octagon: " << std::endl;
+
// Octagon
{
- t.start();
ref = morpho::impl::generic::erosion_on_function(lena, oct);
- std::cout << "generic on octagon: " << t << std::endl;
io::pgm::save(ref, "out_oct_ref.pgm");
}
{
- t.start();
out = morpho::erosion(lena, oct);
- std::cout << "dispach on octagon: " << t << std::endl;
bool test = out == ref;
mln_assertion(test);
- std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
}
}
Index: branches/cleanup-2008/milena/doc/benchmark/morpho/erosion.cc
===================================================================
--- branches/cleanup-2008/milena/doc/benchmark/morpho/erosion.cc (revision 0)
+++ branches/cleanup-2008/milena/doc/benchmark/morpho/erosion.cc (revision 2776)
@@ -0,0 +1,292 @@
+// 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/morpho/erosion.cc
+ *
+ * \brief Test on mln::morpho::erosion.
+ */
+
+#include <mln/core/image/image2d.hh>
+#include <mln/win/all.hh>
+
+#include <mln/debug/iota.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/morpho/erosion.hh>
+
+#include "tests/data.hh"
+#include "tests/timer.hh"
+
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+
+// unsigned
+// l_oct = 11, L_oct = 6 * l_oct + 1,
+// l_rec = 29, L_rec = 2 * l_rec + 1;
+
+ // l_
+ // oct rec err
+ // 0 0 3
+ // 0 1 5
+ // 1 2 15
+ // 1 3 9
+ // 2 5 11
+ // 3 8 9
+ // 5 13 15
+ // 8 21 11
+ // 11 29 1
+ // 25 66 15
+
+ border::thickness = 20;
+ image2d<int_u8> lena;
+ io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
+
+ win::rectangle2d rec(21, 21);
+ win::hline2d hline(31);
+ win::vline2d vline(31);
+ win::diag2d diag2d(31);
+ win::backdiag2d backdiag2d(31);
+ win::octagon2d oct(6 * 3 + 1);
+ image2d<int_u8> out;
+ image2d<int_u8> ref;
+// trace::quiet = false;
+ timer t;
+
+
+ // Rectangle
+ std::cout << "-------------------------- Rectangle: " << std::endl;
+
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, rec);
+ std::cout << "generic on rectangle2d: " << t << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, rec);
+ std::cout << "dispach on rectangle2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d_fastest(lena, rec);
+ std::cout << "erosion_arbitrary_2d_fastest on rectangle2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d(lena, rec);
+ std::cout << "erosion_arbitrary_2d on rectangle2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ //Hline
+
+ std::cout << "-------------------------- Hline2d: " << std::endl;
+
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, hline);
+ std::cout << "generic on hline2d: " << t << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, hline);
+ std::cout << "dispach on hline2d : " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d_fastest(lena, hline);
+ std::cout << "erosion_arbitrary_2d_fastest on hline2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d(lena, hline);
+ std::cout << "erosion_arbitrary_2d on hline2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ std::cout << "-------------------------- Vline2d: "<< std::endl;
+
+ //Vline
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, vline);
+ std::cout << "generic on vline2d: " << t << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, vline);
+ std::cout << "dispach on vline2d : " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d_fastest(lena, vline);
+ std::cout << "erosion_arbitrary_2d_fastest on vline2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d(lena, vline);
+ std::cout << "erosion_arbitrary_2d on vline2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ //Diag2d
+ std::cout << "-------------------------- Diag2d: "<< std::endl;
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, diag2d);
+ std::cout << "generic on diag2d: " << t << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, diag2d);
+ std::cout << "dispach on diag2d : " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d_fastest(lena, diag2d);
+ std::cout << "erosion_arbitrary_2d_fastest on diag2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d(lena, diag2d);
+ std::cout << "erosion_arbitrary_2d on diag2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ //Backdiag2d
+ std::cout << "-------------------------- Backdiag2d: "<< std::endl;
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, backdiag2d);
+ std::cout << "generic on backdiag2d: " << t << std::endl;
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, backdiag2d);
+ std::cout << "dispach on backdiag2d : " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d_fastest(lena, backdiag2d);
+ std::cout << "erosion_arbitrary_2d_fastest on backdiag2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+
+ {
+ t.start();
+ out = morpho::impl::erosion_arbitrary_2d(lena, backdiag2d);
+ std::cout << "erosion_arbitrary_2d on backdiag2d: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+ std::cout << "-------------------------- Octagon: " << std::endl;
+
+ // Octagon
+ {
+ t.start();
+ ref = morpho::impl::generic::erosion_on_function(lena, oct);
+ std::cout << "generic on octagon: " << t << std::endl;
+ io::pgm::save(ref, "out_oct_ref.pgm");
+ }
+
+ {
+ t.start();
+ out = morpho::erosion(lena, oct);
+ std::cout << "dispach on octagon: " << t << std::endl;
+ bool test = out == ref;
+ mln_assertion(test);
+ std::cout << " " << (test ? "OK" : "KO!!!") << std::endl;
+ }
+
+}
1
0
cleanup-2008 2775: Make linear::convolve work properly with heterogenous types.
by Thierry Geraud 03 Nov '08
by Thierry Geraud 03 Nov '08
03 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Make linear::convolve work properly with heterogenous types.
* tests/core/routine/primary.cc: New.
* tests/core/routine/Makefile.am: Update.
* tests/border/duplicate.cc: Layout.
* mln/core/routine/primary.hh: Complete.
* mln/core/internal/image_morpher.hh
(unmorph_): New overload from const target.
* mln/accu/convolve.hh: New.
* mln/accu/all.hh: Update.
(todo): New.
* mln/border/duplicate.hh: Fix.
* mln/extension/adjust_duplicate.hh: New.
* mln/linear/convolve.hh: Update.
mln/accu/all.hh | 7 +
mln/accu/convolve.hh | 148 +++++++++++++++++++++++++++++++++++++
mln/border/duplicate.hh | 140 ++++++++++++++++++++++-------------
mln/core/internal/image_morpher.hh | 16 +++-
mln/core/routine/primary.hh | 49 +++++++++++-
mln/extension/adjust_duplicate.hh | 112 ++++++++++++----------------
mln/linear/convolve.hh | 24 +++---
tests/border/duplicate.cc | 2
tests/core/routine/Makefile.am | 4 -
tests/core/routine/primary.cc | 46 +++++++++++
10 files changed, 420 insertions(+), 128 deletions(-)
Index: tests/core/routine/primary.cc
--- tests/core/routine/primary.cc (revision 0)
+++ tests/core/routine/primary.cc (revision 0)
@@ -0,0 +1,46 @@
+// 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/routine/primary.cc
+///
+/// Tests on mln::primary.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/sub_image.hh>
+#include <mln/core/routine/primary.hh>
+
+
+
+int main()
+{
+ using namespace mln;
+
+ image2d<int> ima(1, 1);
+ box2d b = ima.domain();
+
+ mln_assertion(primary((ima | b) | b).id_() == ima.id_());
+}
Index: tests/core/routine/Makefile.am
--- tests/core/routine/Makefile.am (revision 2774)
+++ tests/core/routine/Makefile.am (working copy)
@@ -6,11 +6,13 @@
clone \
exact \
extend \
- initialize
+ initialize \
+ primary
clone_SOURCES = clone.cc
exact_SOURCES = exact.cc
extend_SOURCES = extend.cc
initialize_SOURCES = initialize.cc
+primary_SOURCES = primary.cc
TESTS = $(check_PROGRAMS)
Index: tests/border/duplicate.cc
--- tests/border/duplicate.cc (revision 2774)
+++ tests/border/duplicate.cc (working copy)
@@ -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
@@ -70,6 +71,5 @@
mln_assertion(ima.element(22) == 8);
mln_assertion(ima.element(23) == 9);
mln_assertion(ima.element(24) == 9);
-
}
Index: mln/core/routine/primary.hh
--- mln/core/routine/primary.hh (revision 2774)
+++ mln/core/routine/primary.hh (working copy)
@@ -42,9 +42,17 @@
namespace mln
{
+ // Forward declaration.
+ namespace internal
+ {
+ template <typename I> struct primary_type;
+ }
+
+
/// FIXME: Doc!
template <typename I>
- void primary(const Image<I>& ima);
+ const typename internal::primary_type<I>::ret&
+ primary(const Image<I>& input);
# ifndef MLN_INCLUDE_ONLY
@@ -60,7 +68,8 @@
template <typename I, typename C>
struct primary_type_helper
{
- typedef typename primary_type<mln_delegatee(I)>::ret ret;
+ typedef typename I::delegatee D;
+ typedef typename primary_type<D>::ret ret;
};
template <typename I>
@@ -79,6 +88,37 @@
// Routine.
+ template <typename I>
+ const typename internal::primary_type<I>::ret&
+ primary_(const Image<I>& input); // Forward declaration.
+
+ template <typename I>
+ inline
+ const typename internal::primary_type<I>::ret&
+ primary_(trait::image::category::primary,
+ const Image<I>& input)
+ {
+ return exact(input);
+ }
+
+ template <typename I>
+ inline
+ const typename internal::primary_type<I>::ret&
+ primary_(trait::image::category::morpher,
+ const Image<I>& input)
+ {
+ return primary_(exact(input).unmorph_());
+ }
+
+ template <typename I>
+ inline
+ const typename internal::primary_type<I>::ret&
+ primary_(const Image<I>& input)
+ {
+ return primary_(mln_trait_image_category(I)(),
+ input);
+ }
+
} // end of namespace mln::internal
@@ -87,8 +127,11 @@
template <typename I>
inline
- void primary(const Image<I>&)
+ const typename internal::primary_type<I>::ret&
+ primary(const Image<I>& input)
{
+ mln_precondition(exact(input).has_data());
+ return internal::primary_(input);
}
Index: mln/core/internal/image_morpher.hh
--- mln/core/internal/image_morpher.hh (revision 2774)
+++ mln/core/internal/image_morpher.hh (working copy)
@@ -65,9 +65,12 @@
I* delegatee_();
- /// Give the morphed image.
+ /// Give the morphed image (mutable version).
I& unmorph_();
+ /// Give the morphed image (const version).
+ mlc_const(I)& unmorph_() const;
+
/* \brief Test if this image has been initialized; default impl.
*
@@ -154,6 +157,17 @@
template <typename I, typename T, typename S, typename E>
inline
+ mlc_const(I)&
+ image_morpher<I, T, S, E>::unmorph_() const
+ {
+ mlc_const(I)* ptr = delegatee_();
+ mln_assertion(ptr != 0);
+ return *ptr;
+ }
+
+
+ template <typename I, typename T, typename S, typename E>
+ inline
image_morpher<I, T, S, E>::operator I() const
{
mln_precondition(exact(this)->has_data());
Index: mln/linear/convolve.hh
--- mln/linear/convolve.hh (revision 2774)
+++ mln/linear/convolve.hh (working copy)
@@ -38,8 +38,8 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/weighted_window.hh>
-# include <mln/border/resize.hh>
-# include <mln/border/duplicate.hh>
+# include <mln/extension/adjust_duplicate.hh>
+# include <mln/accu/convolve.hh>
@@ -105,21 +105,23 @@
const W& w_win = exact(w_win_);
internal::convolve_tests(input, w_win);
- // extension::adjust_duplicate(input, w_win);
+ extension::adjust_duplicate(input, w_win);
typedef mln_concrete(I) O;
O output;
initialize(output, input);
+ accu::convolve<mln_value(I), mln_weight(W)> a;
+
mln_piter(I) p(input.domain());
mln_qiter(W) q(w_win, p);
for_all(p)
{
- mln_value(O) v = literal::zero;
+ a.init();
for_all(q) if (input.has(q))
- v += input(q) * q.w();
- output(p) = v;
+ a.take(input(q), q.w());
+ output(p) = a.to_result();
}
trace::exiting("linear::impl::generic::convolve");
@@ -140,23 +142,25 @@
const W& w_win = exact(w_win_);
internal::convolve_tests(input, w_win);
- // extension::adjust_duplicate(input, w_win);
+ extension::adjust_duplicate(input, w_win);
typedef mln_concrete(I) O;
O output;
initialize(output, input);
mln_pixter(O) p_out(output);
+ accu::convolve<mln_value(I), mln_weight(W)> a;
+
mln_pixter(const I) p(input);
mln_qixter(const I, W) q(p, w_win);
for_all_2(p, p_out)
{
- mln_value(O) v = literal::zero;
+ a.init();
unsigned i = 0;
for_all(q)
- v += w_win.w(i++) * q.val();
- p_out.val() = v;
+ a.take(q.val(), w_win.w(i++));
+ p_out.val() = a.to_result();
}
trace::exiting("linear::impl::convolve_fastest");
Index: mln/accu/all.hh
--- mln/accu/all.hh (revision 2774)
+++ mln/accu/all.hh (working copy)
@@ -1,4 +1,5 @@
-// 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
@@ -35,6 +36,8 @@
* \todo Update accumulators s.a. count so that they are like min_/min.
*
* \todo Propagate those updates to mln/estim/.
+ *
+ * \todo Update the include list...
*/
@@ -46,6 +49,7 @@
{
/// Implementation namespace of accumulator namespace.
namespace impl {}
+
/// Internal namespace of accumulators.
namespace internal {}
}
@@ -55,6 +59,7 @@
# include <mln/accu/bbox.hh>
# include <mln/accu/count.hh>
+# include <mln/accu/convolve.hh>
# include <mln/accu/histo.hh>
# include <mln/accu/max.hh>
# include <mln/accu/mean.hh>
Index: mln/accu/convolve.hh
--- mln/accu/convolve.hh (revision 0)
+++ mln/accu/convolve.hh (revision 0)
@@ -0,0 +1,148 @@
+// 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_CONVOLVE_HH
+# define MLN_ACCU_CONVOLVE_HH
+
+/*! \file mln/accu/convolve.hh
+ *
+ * \brief Define an accumulator that computes a convolution.
+ */
+
+# include <mln/accu/internal/base.hh>
+# include <mln/value/ops.hh>
+# include <mln/literal/zero.hh>
+
+
+namespace mln
+{
+
+ namespace accu
+ {
+
+
+ /*! \brief Generic convolution accumulator class.
+ *
+ * Parameters \c T1 and \c T2 are the type of values to be
+ * convolved. Parameter \c R is the result type.
+ */
+ template <typename T1, typename T2,
+ typename R = mln_sum_x(T1, T2)>
+ struct convolve : public mln::accu::internal::base< R, convolve<T1,T2,R> >
+ {
+ typedef std::pair<T1,T2> argument;
+
+ convolve();
+
+ /// Manipulators.
+ /// \{
+ void init();
+ void take(const argument& t);
+ void take(const T1& t1, const T2& t2);
+ void take(const convolve<T1,T2,R>& other);
+ /// \}
+
+ /// Get the value of the accumulator.
+ R to_result() const;
+
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
+ bool is_valid() const;
+
+ protected:
+
+ typedef mln_sum_x(T1, T2) S;
+ S s_;
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename T1, typename T2, typename R>
+ inline
+ convolve<T1,T2,R>::convolve()
+ {
+ init();
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ void
+ convolve<T1,T2,R>::init()
+ {
+ static S zero = literal::zero;
+ s_ = zero;
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ void
+ convolve<T1,T2,R>::take(const argument& t)
+ {
+ s_ += t.first * t.second;
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ void
+ convolve<T1,T2,R>::take(const T1& t1, const T2& t2)
+ {
+ s_ += t1 * t2;
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ void
+ convolve<T1,T2,R>::take(const convolve<T1,T2,R>& other)
+ {
+ s_ += other.s_;
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ R
+ convolve<T1,T2,R>::to_result() const
+ {
+ return s_;
+ }
+
+ template <typename T1, typename T2, typename R>
+ inline
+ bool
+ convolve<T1,T2,R>::is_valid() const
+ {
+ return true;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::accu
+
+} // end of namespace mln
+
+
+#endif // ! MLN_ACCU_CONVOLVE_HH
Index: mln/border/duplicate.hh
--- mln/border/duplicate.hh (revision 2774)
+++ mln/border/duplicate.hh (working copy)
@@ -1,4 +1,5 @@
-// 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
@@ -34,8 +35,9 @@
*/
# include <mln/core/concept/image.hh>
-# include <mln/level/memset_.hh>
-# include <mln/core/pixel.hh>
+# include <mln/core/routine/primary.hh>
+# include <mln/core/box_runstart_piter.hh>
+# include <mln/border/get.hh>
namespace mln
@@ -64,37 +66,37 @@
template <typename I>
inline
- void duplicate_1d_(const I& ima)
+ void duplicate_1D(I& ima)
{
- trace::entering("border::impl::duplicate_1d_");
+ trace::entering("border::impl::duplicate_1D");
typedef mln_psite(I) P;
- typename I::line_piter pl(ima.domain());
- unsigned len_c = exact(ima).bbox().len(P::dim - 1);
+ mln_box_runstart_piter(I) pl(ima.domain());
+ unsigned len_c = ima.bbox().len(P::dim - 1);
unsigned border = ima.border ();
for (unsigned i = 0; i < border; ++i)
- const_cast<I&>(ima)[i] = ima[border];
+ ima.element(i) = ima.element(border);
unsigned st = border + len_c - 1;
for (unsigned i = st + 1; i < ima.nelements (); ++i)
- const_cast<I&>(ima)[i] = ima[st];
+ ima.element(i) = ima.element(st);
- trace::exiting("border::impl::duplicate_1d_");
+ trace::exiting("border::impl::duplicate_1D");
}
template <typename I>
inline
- void duplicate_2d_(const I& ima)
+ void duplicate_2D(I& ima)
{
- trace::entering("border::impl::duplicate_2d_");
+ trace::entering("border::impl::duplicate_2D");
typedef mln_psite(I) P;
- typename I::line_piter pl(ima.domain());
+ mln_box_runstart_piter(I) pl(ima.domain());
unsigned border = ima.border ();
unsigned border_2x = 2 * ima.border ();
- unsigned len_c = exact(ima).bbox().len(1);
- unsigned len_r = exact(ima).bbox().len(0);
+ unsigned len_c = ima.bbox().len(1);
+ unsigned len_r = ima.bbox().len(0);
unsigned real_len_c = len_c + border_2x;
unsigned st;
@@ -103,43 +105,42 @@
{
st = ima.index_of_point (pl);
for (unsigned i = 1; i <= border; ++i)
- const_cast<I&>(ima)[st - i] = ima[st];
+ ima.element(st - i) = ima.element(st);
st = st + len_c - 1;
for (unsigned i = 1; i <= border; ++i)
- const_cast<I&>(ima)[st + i] = ima[st];
+ ima.element(st + i) = ima.element(st);
}
// Duplicate n first * border line
st = real_len_c * border;
for (unsigned k = 0; k < border; ++k)
for (unsigned i = 0; i < real_len_c; ++i)
- const_cast<I&>(ima)[k * real_len_c + i] = ima[st + i];
+ ima.element(k * real_len_c + i) = ima.element(st + i);
// Duplicate n last * border line
st = real_len_c * (border + len_r - 1);
for (unsigned k = 1; k <= border; ++k)
for (unsigned i = st; i < st + real_len_c; ++i)
- const_cast<I&>(ima)[k * real_len_c + i] = ima[i];
+ ima.element(k * real_len_c + i) = ima.element(i);
- trace::exiting("border::impl::duplicate_2d_");
+ trace::exiting("border::impl::duplicate_2D");
}
template <typename I>
inline
- void duplicate_3d_(const Image<I>& ima_)
+ void duplicate_3D(I& ima)
{
- trace::entering("border::impl::duplicate_3d_");
+ trace::entering("border::impl::duplicate_3D");
- const I& ima = exact(ima_);
mln_precondition(ima.has_data());
typedef mln_psite(I) P;
- typename I::line_piter pl(ima.domain());
+ mln_box_runstart_piter(I) pl(ima.domain());
unsigned border = ima.border ();
unsigned border_2x = 2 * ima.border ();
- unsigned len_c = exact(ima).bbox().len(P::dim - 1);
- unsigned len_r = exact(ima).bbox().len(1);
- unsigned len_s = exact(ima).bbox().len(0);
+ unsigned len_c = ima.bbox().len(P::dim - 1);
+ unsigned len_r = ima.bbox().len(1);
+ unsigned len_s = ima.bbox().len(0);
unsigned real_len_c = len_c + border_2x;
unsigned real_len_r = len_r + border_2x;
unsigned face = real_len_c * real_len_r;
@@ -155,10 +156,10 @@
{
st = ima.index_of_point (pl);
for (unsigned i = 1; i <= border; ++i)
- const_cast<I&>(ima)[st - i] = ima[st];
+ ima.element(st - i) = ima.element(st);
st = st + len_c - 1;
for (unsigned i = 1; i <= border; ++i)
- const_cast<I&>(ima)[st + i] = ima[st];
+ ima.element(st + i) = ima.element(st);
pl.next ();
}
@@ -166,57 +167,96 @@
st = border * face + k * face + border * real_len_c ;
for (unsigned j = 1; j <= border; ++j)
for (unsigned i = 0; i < real_len_c; ++i)
- const_cast<I&>(ima)[st - j * real_len_c + i] = ima[st + i];
+ ima.element(st - j * real_len_c + i) = ima.element(st + i);
// Duplicate n last * border line
st = border * face + k * face + (len_r + border - 1) * real_len_c ;
for (unsigned j = 1; j <= border; ++j)
for (unsigned i = 0; i < real_len_c; ++i)
- const_cast<I&>(ima)[st + j * real_len_c + i] = ima[st + i];
+ ima.element(st + j * real_len_c + i) = ima.element(st + i);
}
// Duplicate n first * border face
st = border * face;
for (unsigned k = 0; k < border; ++k)
for (unsigned i = 0; i < face; ++i)
- const_cast<I&>(ima)[k * face + i] = ima[st + i];
+ ima.element(k * face + i) = ima.element(st + i);
// Duplicate n last * border face
st = (len_s + border - 1) * face;
for (unsigned k = 1; k <= border; ++k)
for (unsigned i = 0; i < face; ++i)
- const_cast<I&>(ima)[st + k * face + i] = ima[st + i];
+ ima.element(st + k * face + i) = ima.element(st + i);
- trace::exiting("border::impl::duplicate_3d_");
+ trace::exiting("border::impl::duplicate_3D");
}
} // end of namespace mln::border::impl
- // Facade.
+ namespace internal
+ {
template <typename I>
- inline
- void duplicate(const Image<I>& ima_)
+ void duplicate_dispatch_on(metal::int_<1>, I& ima)
{
- trace::entering("border::duplicate");
+ impl::duplicate_1D(ima);
+ }
- const I& ima = exact(ima_);
- mln_precondition(ima.has_data());
+ template <typename I>
+ void duplicate_dispatch_on(metal::int_<2>, I& ima)
+ {
+ impl::duplicate_2D(ima);
+ }
- mlc_is(mln_trait_image_speed(I), trait::image::speed::fastest)::check();
+ template <typename I>
+ void duplicate_dispatch_on(metal::int_<3>, I& ima)
+ {
+ impl::duplicate_3D(ima);
+ }
- typedef mln_psite(I) P;
+ template <typename I>
+ void duplicate_dispatch_on(trait::image::speed::fastest,
+ const Image<I>& ima)
+ {
+ typedef mln_site(I) P;
+ duplicate_dispatch_on(metal::int_<P::dim>(),
+ const_cast<I&>(exact(ima)));
+ }
- if (!ima.border ())
- return;
+ template <typename I>
+ void duplicate_dispatch_on(trait::image::speed::any,
+ const Image<I>& ima)
+ {
+ // No-op.
+ }
+
+ template <typename I>
+ void duplicate_dispatch_on(const Image<I>& ima)
+ {
+ duplicate_dispatch_on(mln_trait_image_speed(I)(),
+ ima);
+ }
+
+ template <typename I>
+ void duplicate_dispatch(const Image<I>& ima)
+ {
+ duplicate_dispatch_on(primary(ima));
+ }
+
+ } // end of namespace mln::border::internal
+
+
+ // Facade.
+
+ template <typename I>
+ void duplicate(const Image<I>& ima)
+ {
+ trace::entering("border::duplicate");
+ mln_precondition(exact(ima).has_data());
- if (P::dim == 1)
- impl::duplicate_1d_(ima);
- if (P::dim == 2)
- impl::duplicate_2d_(ima);
- if (P::dim == 3)
- impl::duplicate_3d_(ima);
+ if (border::get(ima) != 0)
+ internal::duplicate_dispatch(ima);
trace::exiting("border::duplicate");
}
Index: mln/extension/adjust_duplicate.hh
--- mln/extension/adjust_duplicate.hh (revision 2769)
+++ mln/extension/adjust_duplicate.hh (working copy)
@@ -25,18 +25,19 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_CORE_EXTENSION_ADJUST_FILL_HH
-# define MLN_CORE_EXTENSION_ADJUST_FILL_HH
+#ifndef MLN_CORE_EXTENSION_ADJUST_DUPLICATE_HH
+# define MLN_CORE_EXTENSION_ADJUST_DUPLICATE_HH
-/*! \file mln/extension/adjust_fill.hh
+/*! \file mln/extension/adjust_duplicate.hh
*
- * \brief Adjust then fill the domain extension.
+ * \brief Adjust the size of the domain extension then duplicate the
+ * image inner boundary.
*
* \todo Fix doc.
*/
# include <mln/border/adjust.hh>
-# include <mln/extension/fill.hh>
+# include <mln/border/duplicate.hh>
# include <mln/geom/delta.hh>
@@ -46,63 +47,56 @@
namespace extension
{
- /*! Fill the domain extension of image \p ima with the
- * single value \p v.
+ /*! Fill the domain extension of image \p ima by duplicating the
+ * image inner boundary.
*
* \param[in,out] ima The image whose domain extension is to be filled.
- * \param[in] val The value to assign.
*
* \pre \p ima has to be initialized.
- *
- * \todo Optimize with memset if possible.
*/
template <typename I, typename W>
- void adjust_fill(const Image<I>& ima,
- const Window<W>& win,
- const mln_value(I)& val);
+ void adjust_duplicate(const Image<I>& ima,
+ const Window<W>& win);
template <typename I, typename W>
- void adjust_fill(const Image<I>& ima,
- const Weighted_Window<W>& wwin,
- const mln_value(I)& val);
+ void adjust_duplicate(const Image<I>& ima,
+ const Weighted_Window<W>& wwin);
template <typename I, typename N>
- void adjust_fill(const Image<I>& ima,
- const Neighborhood<N>& nbh,
- const mln_value(I)& val);
+ void adjust_duplicate(const Image<I>& ima,
+ const Neighborhood<N>& nbh);
template <typename I>
- void adjust_fill(const Image<I>& ima,
- unsigned delta,
- const mln_value(I)& val);
+ void adjust_duplicate(const Image<I>& ima,
+ unsigned delta);
+
+
# ifndef MLN_INCLUDE_ONLY
namespace impl
{
- template <typename I, typename V>
- void do_adjust_fill(const I& ima,
- unsigned delta,
- const V& val)
+ template <typename I>
+ void do_adjust_duplicate(const I& ima,
+ unsigned delta)
{
mln_precondition(exact(ima).has_data());
// mln_precondition(exact(win_like).is_valid());
border::adjust(ima, delta);
- extension::fill(ima, val);
+ border::duplicate(ima);
}
- template <typename I, typename W, typename V>
- void do_adjust_fill(const I& ima,
- const W& win_like,
- const V& val)
+ template <typename I, typename W>
+ void do_adjust_duplicate(const I& ima,
+ const W& win_like)
{
mln_precondition(exact(ima).has_data());
// mln_precondition(exact(win_like).is_valid());
border::adjust(ima, geom::delta(win_like));
- extension::fill(ima, val);
+ border::duplicate(ima);
}
} // end of namespace mln::extension::impl
@@ -111,43 +105,39 @@
// Facades.
template <typename I, typename W>
- void adjust_fill(const Image<I>& ima,
- const Window<W>& win,
- const mln_value(I)& val)
- {
- trace::entering("extension::adjust_fill");
- impl::do_adjust_fill(ima, win, val);
- trace::exiting("extension::adjust_fill");
+ void adjust_duplicate(const Image<I>& ima,
+ const Window<W>& win)
+ {
+ trace::entering("extension::adjust_duplicate");
+ impl::do_adjust_duplicate(ima, win);
+ trace::exiting("extension::adjust_duplicate");
}
template <typename I, typename W>
- void adjust_fill(const Image<I>& ima,
- const Weighted_Window<W>& wwin,
- const mln_value(I)& val)
- {
- trace::entering("extension::adjust_fill");
- impl::do_adjust_fill(ima, wwin, val);
- trace::exiting("extension::adjust_fill");
+ void adjust_duplicate(const Image<I>& ima,
+ const Weighted_Window<W>& wwin)
+ {
+ trace::entering("extension::adjust_duplicate");
+ impl::do_adjust_duplicate(ima, wwin);
+ trace::exiting("extension::adjust_duplicate");
}
template <typename I, typename N>
- void adjust_fill(const Image<I>& ima,
- const Neighborhood<N>& nbh,
- const mln_value(I)& val)
- {
- trace::entering("extension::adjust_fill");
- impl::do_adjust_fill(ima, nbh, val);
- trace::exiting("extension::adjust_fill");
+ void adjust_duplicate(const Image<I>& ima,
+ const Neighborhood<N>& nbh)
+ {
+ trace::entering("extension::adjust_duplicate");
+ impl::do_adjust_duplicate(ima, nbh);
+ trace::exiting("extension::adjust_duplicate");
}
template <typename I>
- void adjust_fill(const Image<I>& ima,
- unsigned delta,
- const mln_value(I)& val)
- {
- trace::entering("extension::adjust_fill");
- impl::do_adjust_fill(ima, delta, val);
- trace::exiting("extension::adjust_fill");
+ void adjust_duplicate(const Image<I>& ima,
+ unsigned delta)
+ {
+ trace::entering("extension::adjust_duplicate");
+ impl::do_adjust_duplicate(ima, delta);
+ trace::exiting("extension::adjust_duplicate");
}
@@ -158,4 +148,4 @@
} // end of namespace mln
-#endif // ! MLN_CORE_EXTENSION_FILL_HH
+#endif // ! MLN_CORE_EXTENSION_DUPLICATE_HH
Property changes on: mln/extension/adjust_duplicate.hh
___________________________________________________________________
Added: svn:mergeinfo
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
INIM: Add a README file.
* ballas/color/README: New.
README | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
Index: ballas/color/README
--- ballas/color/README (revision 0)
+++ ballas/color/README (revision 0)
@@ -0,0 +1,83 @@
+-*- outline -*-
+
+* Fichiers sources:
+
+Les fichiers sources se trouvent dans milena/sandbox/ballas/color/.
+
+** Les méthodes de références:
+
+*** reference.cc:
+ Utilisation de la seconde dérivée de gaussienne.
+ Les passages par 0 sont mis en rouges.
+
+*** reference2.cc:
+ Utilisation d'un gradient puis d'un filtre de clôture de volumes.
+
+ Variante testée (non retenue):
+ - un filtre de clôture d'aires.
+
+** min_tree:
+
+Les approches développées avec le min tree essayent de prendre en compte
+la couleur de l'image initial.
+
+Ici, on "expand" l'image pour pouvoir stocker les points et les edges directement
+sur l'image. Puis sur chaque edge, on stocke la distance séparant les deux
+pixels voisins cet edge. On construit ensuite un min tree sur ces edges.
+Ce min tree est ensuite filtrer afin d'éviter la sur-segmentation
+
+
+*** min_tree_area.cc:
+ Dans cette version, un filtre d'aire est appliqué aux edges constituant
+le min tree. Si l'aire des edges d'une région du min tree est inférieure à un
+lambda donné, on fusionne la région avec sa région supérieure.
+
+*** min_tree_volume.cc
+ Dans cette version, un filtre de volume est appliqué aux edges constituant
+le min tree.
+
+*** min_tree_color.cc
+ Dans cette version, on filtre en fonction de la couleur moyenne.
+Si la distance entre la couleur moyenne constituant 2 régions est inférieure
+à un lambda donné, on fusionne les régions.
+
+
+* Organisation des répertoires:
+
+Les images de tests se trouve dans le répertoire ~ballas/pub/result/
+
+Chaque sous-répertoire contient des tests sur une image en particulier
+Cette image est stockée dans le répertoire sous le nom input.ppm.
+
+Chaque sous-répertoire contiennent des répertoires avec les résultats
+en fonction des méthodes utilisées:
+- ref1 contient les résultats de la méthode reference.cc
+- ref2 contient les résultats de la méthode reference2.cc
+- area contient les résultats de la méthode min_tree_area.cc
+- volume contient les résultats de la méthode min_tree_volume.cc
+- color contient les résultats de la méthode min_tree_color.cc
+
+Les résultats sont organisés de la manière suivante dans les répertoires
+area, volume et color.
+** edge.pgm:
+ Image affichant les edges calculés avant le passage de min tree.
+ Ces edges contiennent la distance entre les deux pixels voisins.
+ Les pixels sont noir par défaut dans cette image.
+** edge.ppm:
+ Image affichant les edges calcules après l'application du filtre sur le
+ min tree.
+ Ces edges contiennent la distance entre les deux pixels voisins.
+ Les pixels sont noir par défaut dans cette image.
+** full.ppm:
+ Superposition de l'image edge.ppm et de l'image de départ.
+** colorize.ppm:
+ Image contenant les pixels coloriés à partir des edges de l'image.
+ On utilise une dilatation pour colorier les pixels, ce qui altère la
+ forme des lettres.
+
+Les résultats sont organisés de la manière suivante dans les répertoires
+ref1 et ref2.
+** lambda_x.ppm:
+ x est le lambda utilisé pour le filtre.
+ Dans ref1, nous avons une image avec les contours, alors que dans ref2,
+ nous une image découpée en zones.
1
0
cleanup-2008 2772: Inim: Add the code related to edge detection in the sandbox.
by Nicolas Ballas 03 Nov '08
by Nicolas Ballas 03 Nov '08
03 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena/sandbox
Index: ChangeLog
from Nicolas Ballas <ballas(a)lrde.epita.fr>
Inim: Add the code related to edge detection in the sandbox.
* ballas/color: New.
* ballas/color/min_tree_volume_filter.cc: Min tree using volume filter.
* ballas/color/reference.cc: Method using a gradient.
* ballas/color/min_tree_area_filter.cc: Min tree using area filter.
* ballas/color/min_tree_color.cc: Min tree using filter based on color.
* ballas/color/reference2.cc: Method using the laplacien.
* ballas/color/src: New.
* ballas/color/src/graph.hh,
* ballas/color/src/io.hh,
* ballas/color/src/distance.hh,
* ballas/color/src/convert.hh: New, factorize some code.
* ballas/color/laplacien.cc: Laplacien tests.
laplacien.cc | 129 ++++++++++
min_tree_area_filter.cc | 505 +++++++++++++++++++++++++++++++++++++++++
min_tree_color.cc | 525 +++++++++++++++++++++++++++++++++++++++++++
min_tree_volume_filter.cc | 514 ++++++++++++++++++++++++++++++++++++++++++
reference.cc | 556 ++++++++++++++++++++++++++++++++++++++++++++++
reference2.cc | 406 +++++++++++++++++++++++++++++++++
src/convert.hh | 37 +++
src/distance.hh | 52 ++++
src/graph.hh | 61 +++++
src/io.hh | 57 ++++
10 files changed, 2842 insertions(+)
Index: ballas/color/min_tree_volume_filter.cc
--- ballas/color/min_tree_volume_filter.cc (revision 0)
+++ ballas/color/min_tree_volume_filter.cc (revision 0)
@@ -0,0 +1,514 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+# include <mln/literal/origin.hh>
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/morpho/closing_area.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/debug/println.hh>
+
+# include "src/distance.hh"
+
+namespace mln
+{
+ template <typename I, typename N, typename Ic, typename Nc>
+ struct min_tree_
+ {
+ typedef mln_site(I) point;
+ typedef p_array<point> S;
+
+ // in:
+ const I& f;
+ const N& nbh;
+ const Ic& ref;
+ const Nc& nbhc;
+
+ // aux:
+ S s;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+ mln_ch_value(I, bool) resp;
+ mln_ch_value(I, point) zpar;
+
+ // attached data:
+ int lambda;
+ mln_ch_value(I, int) volume;
+ //mln_ch_value(Ic, value::rgb8) values;
+ //initialize(values, ref);
+ //mln_ch_value(I, int) comp;
+
+ min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+ : f(f),
+ nbh(nbh),
+ ref(ref),
+ nbhc(nbhc),
+ lambda(lambda)
+ {
+ run();
+ }
+
+ void run()
+ {
+ // init
+ {
+ initialize(deja_vu, f);
+ initialize(parent, f);
+ initialize(resp, f);
+ initialize(zpar, f);
+ initialize(volume, f);
+ //initialize(comp, f);
+
+ mln::level::fill(deja_vu, false);
+ //mln::level::fill(resp, false);
+ mln::level::fill(volume, 0);
+
+ s = level::sort_psites_increasing(f);
+ }
+
+ // first pass
+ {
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ make_set(p);
+ for_all(n)
+ if (f.has(n) && deja_vu(n))
+ do_union(n, p);
+ deja_vu(p) = true;
+ }
+ }
+
+ // second pass: canonization
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (f(parent(q)) == f(q))
+ {
+ parent(p) = parent(q);
+ resp(q) = false;
+ }
+ }
+ }
+
+ // third pass: Merging region with volume < lambda
+ {
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (resp(p) && (volume(p) < lambda))
+ {
+ resp(p) = false;
+ update_data(parent(p), volume(p));
+ }
+ }
+ }
+
+ } // end of run()
+
+ void make_set(const point& p)
+ {
+ parent(p) = p;
+ zpar(p) = p;
+ init_data(p);
+ }
+
+ void set_parent(const point& r, const point& p)
+ {
+ parent(r) = p;
+ merge_data(r, p);
+ }
+
+ bool is_root(const point& p) const
+ {
+ return parent(p) == p;
+ }
+
+ bool is_node(const point& p) const
+ {
+ //return is_root(p) || f(parent(p)) != f(p);
+ return (is_root(p) || resp(p));
+ }
+
+ point find_root(const point& x)
+ {
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = find_root(zpar(x));
+ }
+
+ point find_representative(const point& x)
+ {
+ if (parent(x) == x || resp(x))
+ return x;
+ else
+ return find_representative(parent(x));
+ }
+
+ void do_union(const point& n, const point& p)
+ {
+ point r = find_root(n);
+ if (r != p)
+ {
+ set_parent(r, p);
+ zpar(r) = p;
+ }
+ }
+
+ void init_data(const point& p)
+ {
+ int red =0, green = 0, blue = 0;
+
+ mln_niter(Nc) n(nbhc, p);
+ for_all(n)
+ {
+ red += ref(n).red();
+ green += ref(n).green();
+ blue += ref(n).blue();
+ }
+
+ red /= 2;
+ green /= 2;
+ blue /= 2;
+
+ volume(p) = distance(value::rgb8(red, green, blue),
+ value::rgb8(0, 0, 0));
+ resp(p) = true;
+ }
+
+ void merge_data(const point& r, const point& p)
+ {
+ if (f(p) == f(r))
+ {
+ resp(p) = false;
+ volume(r) += volume(p);
+ }
+ }
+
+ void update_data(const point& p, int val)
+ {
+ volume(p) += val;
+ if (parent(p) != p && !resp(p))
+ update_data(parent(p), val);
+ }
+
+ };
+}
+
+namespace mln
+{
+ image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u16> output(data.domain());
+ mln_piter_(image2d<value::int_u16>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // end of mln
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+
+ mln_VAR(edge, ima | is_edge);
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (unsigned row = 0; row < input.nrows(); ++row)
+ for (unsigned col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (unsigned row = 0; row < input.nrows(); row += 2)
+ for (unsigned col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+template <typename I, typename N, typename Ic, typename Nc>
+unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+{
+ using namespace mln;
+
+ min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
+ mln_piter(I) p(f.domain());
+ unsigned nnodes = 0;
+ for_all(p)
+ {
+ if (run.is_node(p))
+ {
+ ++nnodes;
+ }
+ }
+
+ colorize colors(nnodes);
+ image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, ref);
+
+ mln_piter(I) q(f.domain());
+ unsigned int i = 0;
+ for_all(q)
+ {
+ if (run.is_node(q))
+ {
+ tmp(q) = colors(i);
+ i++;
+ }
+ }
+ mln_piter(I) r(f.domain());
+ for_all(r)
+ {
+ if (!run.is_node(r))
+ {
+ tmp(r) = tmp(run.find_representative(r));
+ }
+ }
+
+ image2d<value::rgb8> to_display(tmp.domain());
+
+ level::fill(to_display, value::rgb8(255, 255, 255));
+ level::paste((tmp | is_edge), to_display);
+ level::paste(morpho::dilation(to_display, c4()), to_display);
+
+ io::ppm::save(display_edge(tmp, literal::black, 3),
+ "edge.ppm");
+ io::ppm::save(tmp, "full.ppm");
+ io::ppm::save(cells2image(to_display), "colorize.ppm");
+
+
+ return nnodes;
+}
+
+
+template <typename I>
+I
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /// Graph creation
+ I graph;
+ create_graph(input, graph, value::rgb8(0, 0, 0));
+
+ // Initialization
+ image2d<value::int_u16> ima = convert_to_grey(graph);
+
+ // Neigbhorhood
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+
+ mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v));
+
+ // Algorithm
+ distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima);
+
+ io::pgm::save(ima, "edge.pgm");
+
+ nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda);
+
+ return graph;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ //io::ppm::save(output, argv[3]);
+}
Index: ballas/color/reference.cc
--- ballas/color/reference.cc (revision 0)
+++ ballas/color/reference.cc (revision 0)
@@ -0,0 +1,556 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+# include <mln/literal/origin.hh>
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+# include <mln/accu/mean.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+# include <mln/convert/to.hh>
+
+# include <mln/linear/gaussian.hh>
+
+# include <mln/morpho/meyer_wst.hh>
+# include <mln/morpho/closing_volume.hh>
+
+# include <mln/make/w_window2d.hh>
+
+# include <mln/debug/println.hh>
+
+// Laplacian method
+namespace mln
+{
+ namespace linear
+ {
+ // required to deal with a input image that differ from the output since I
+ //don't succeed in using a float image in entry.
+ template <class I, class O>
+ inline
+ void
+ gaussian_2nd_derivative(const Image<I>& input, float sigma, Image<O>& output)
+ {
+ mln_precondition(exact(input).has_data());
+
+ impl::recursivefilter_coef_
+ coef(-1.331f, 3.661f,
+ 1.24f, 1.314f,
+ 0.3225f, -1.738f,
+ 0.748f, 2.166f,
+ sigma, impl::gaussian_2nd_deriv_coef_norm_);
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output);
+ }
+
+ template <class I, class O>
+ inline
+ void
+ gaussian_1st_derivative(const Image<I>& input, float sigma, Image<O>& output)
+ {
+ mln_precondition(exact(input).has_data());
+
+ impl::recursivefilter_coef_
+ coef(-0.6472f, -4.531f,
+ 1.527f, 1.516f,
+ 0.6494f, 0.9557f,
+ 0.6719f, 2.072f,
+ sigma, impl::gaussian_1st_deriv_coef_norm_);
+ impl::generic_filter_common_(mln_trait_value_nature(mln_value(I))(),
+ input, coef, sigma, output);
+ }
+ }
+}
+
+// Gradient + watershed method
+namespace mln
+{
+ namespace morpho
+ {
+ template <typename I, typename N>
+ mln_concrete(I)
+ closing_volume(const I& input, const Neighborhood<N>& nbh, std::size_t lambda)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+ closing_volume(input, nbh, lambda, output);
+ return output;
+ }
+ }
+} // !mln
+
+namespace mln
+{
+ image2d<value::int_u8> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u8> output(data.domain());
+ mln_piter_(image2d<value::int_u8>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // !mln
+
+// Functions
+
+inline
+bool is_row_odd(const mln::point2d& p)
+{
+ return p.row() % 2;
+}
+
+inline
+bool is_cell(const mln::point2d& p)
+{
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+}
+
+inline
+bool is_edge(const mln::point2d& p)
+{
+ return p.row() % 2 + p.col() % 2 == 1;
+}
+
+inline
+bool is_point(const mln::point2d& p)
+{
+ return p.row() % 2 && p.col() % 2;
+}
+
+inline
+bool is_not_edge(const mln::point2d& p)
+{
+ return ! is_edge(p);
+}
+
+
+
+namespace mln
+{
+
+ namespace border
+ {
+
+ template <typename I>
+ void
+ fill(I& ima, const mln_value(I)& v)
+ {
+ const int nrows = ima.nrows();
+ const int ncols = ima.ncols();
+ for (int r = -1; r <= nrows; ++r)
+ {
+ ima.at(r, -1) = v;
+ ima.at(r, ncols) = v;
+ }
+ for (int c = -1; c <= ncols; ++c)
+ {
+ ima.at(-1, c) = v;
+ ima.at(nrows, c) = v;
+ }
+ }
+
+ } // mln::border
+
+ namespace accu
+ {
+
+ template <typename I, typename L, typename A, typename V>
+ inline
+ void
+ compute(const Image<I>& input_,
+ const Image<L>& label_,
+ const Accumulator<A>&,
+ V& v)
+ {
+ trace::entering("accu::compute");
+
+ const I& input = exact(input_);
+ const L& label = exact(label_);
+
+ const unsigned n = v.size();
+ std::vector<A> a(n);
+
+ mln_piter(I) p(input.domain());
+ for_all(p)
+ a[label(p)].take(input(p));
+
+ for (unsigned l = 1; l < n; ++l)
+ v(l) = a[l].to_result();
+
+ trace::exiting("accu::compute");
+ }
+
+ } // mln::accu
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ gradient(const I& input, const N& nbh)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+ accu::min_max<mln_value(I)> mm;
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ mm.init();
+ for_all(n) if (input.has(n))
+ mm.take(input(n));
+ output(p) = mm.second() - mm.first();
+ }
+ return output;
+ }
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+
+ template <typename I>
+ I display_edge_with_bg(const I& ima, unsigned zoom, mln_value(I) bg)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (int row = 0; row < input.nrows(); ++row)
+ for (int col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+namespace mln {
+
+ template <typename I, typename N, typename M>
+ mln_concrete(I)
+ mean(const I& input, const N& nbh, const M& nbh2)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ mln_niter(M) m(nbh2, p);
+ for_all(p)
+ {
+ if (is_edge(p))
+ {
+ int nb = 0;
+ int r = 0, g = 0, b = 0;
+ for_all(n)
+ {
+ if (input.has(n))
+ {
+ r += input(n).red();
+ g += input(n).green();
+ b += input(n).blue();
+ ++nb;
+ }
+ }
+ output(p) = value::rgb8(r / nb, g / nb, b / nb);
+ }
+ if (is_point(p))
+ {
+ int nb = 0;
+ int r = 0, g = 0, b = 0;
+ for_all(m)
+ {
+ if (input.has(m))
+ {
+ r += input(m).red();
+ g += input(m).green();
+ b += input(m).blue();
+ ++nb;
+ }
+ }
+ output(p) = value::rgb8(r / nb, g / nb, b / nb);
+ }
+ if (is_cell(p))
+ output(p) = input(p);
+ }
+ return output;
+ }
+
+}
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (int row = 0; row < input.nrows(); row += 2)
+ for (int col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+
+
+template <typename I>
+mln_concrete(I)
+do_it(I& input, float lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /**************************/
+ /* Neighborhood defintion */
+ /**************************/
+
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) );
+
+ // e2e
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) );
+
+ // e2p
+ bool e2p_h[] = { 1, 0, 1,
+ 0, 0, 0,
+ 1, 0, 1 };
+ bool e2p_v[] = { 1, 0, 1,
+ 0, 0, 0,
+ 1, 0, 1 };
+ mln_VAR( e2p, make::double_neighb2d(is_row_odd, e2p_h, e2p_v) );
+
+ /******************/
+ /* Initialisation */
+ /******************/
+
+ I output = mean(image2cells(input), e2c, e2p);
+ io::ppm::save(output, "tmp_input.ppm");
+ //image2d<value::int_u8> ima = convert_to_grey(output);
+ image2d<value::int_u8> imau = convert_to_grey(output);
+ io::pgm::save(imau, "tmp_grey_input.pgm");
+
+ image2d<float> ima(exact(imau).domain());
+
+ // cell
+ mln_VAR(cell, imau | is_cell);
+
+ // edge
+ mln_VAR(edge, extend((imau | is_edge).rw(), pw::value(imau)));
+
+ // FIXME until laplacian is working use gradient / closing_area / wst
+
+ linear::gaussian_2nd_derivative(imau, lambda, ima);
+
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ {
+ if (is_row_odd(p))
+ {
+ mln_value(image2d<float>) t = ima.at(p.row() - 1, p.col());
+ mln_value(image2d<float>) b = ima.at(p.row() + 1, p.col());
+ if ((t > 0 && b < 0) || (t < 0 && b > 0))
+ output(p) = value::rgb8(255,0,0);
+ }
+ else
+ {
+ mln_value(image2d<float>) r = ima.at(p.row(), p.col() - 1);
+ mln_value(image2d<float>) d = ima.at(p.row(), p.col() + 1);
+ if ((r > 0 && d < 0) || (r < 0 && d > 0))
+ output(p) = value::rgb8(255,0,0);
+ }
+ }
+
+#if 0
+ level::paste(morpho::gradient(edge, e2c), edge);
+ level::paste(morpho::closing_volume(edge, e2e, lambda), edge);
+ level::fill(edge, morpho::meyer_wst(edge, e2e, nbasins));
+
+ // Fill regions (with colorize) (won't work with laplacian...)
+
+ colorize colors(nbasins);
+
+ image2d<value::rgb8> cells(ima.domain());
+ level::fill(cells, literal::white);
+ level::paste(level::transform(edge, colors), cells);
+ io::ppm::save(display_edge_with_bg(cells, 3, literal::white), "tmp_edge.ppm");
+
+ // Move the color of an edge which is non black in the cell
+ level::paste(morpho::dilation(cells, c4()), cells);
+#endif
+
+ //cells = convert_to_rgb8(ima);
+
+ return output;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 4)
+ usage(argv);
+
+ float lambda = atof(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ io::ppm::save(display_edge(output, 3), argv[3]);
+}
Index: ballas/color/min_tree_area_filter.cc
--- ballas/color/min_tree_area_filter.cc (revision 0)
+++ ballas/color/min_tree_area_filter.cc (revision 0)
@@ -0,0 +1,505 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+# include <mln/literal/origin.hh>
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/morpho/meyer_wst.hh>
+# include <mln/morpho/closing_area.hh>
+
+# include <mln/debug/println.hh>
+
+# include "src/distance.hh"
+
+namespace mln
+{
+ template <typename I, typename N, typename Ic, typename Nc>
+ struct min_tree_
+ {
+ typedef mln_site(I) point;
+ typedef p_array<point> S;
+
+ // in:
+ const I& f;
+ const N& nbh;
+ const Ic& ref;
+ const Nc& nbhc;
+
+ // aux:
+ S s;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+ mln_ch_value(I, bool) resp;
+ mln_ch_value(I, point) zpar;
+
+ // attached data:
+ int lambda;
+ mln_ch_value(I, int) area;
+ //mln_ch_value(Ic, value::rgb8) values;
+ //initialize(values, ref);
+ //mln_ch_value(I, int) comp;
+
+ min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+ : f(f),
+ nbh(nbh),
+ ref(ref),
+ nbhc(nbhc),
+ lambda(lambda)
+ {
+ run();
+ }
+
+ void run()
+ {
+ // init
+ {
+ initialize(deja_vu, f);
+ initialize(parent, f);
+ initialize(resp, f);
+ initialize(zpar, f);
+ initialize(area, f);
+ //initialize(comp, f);
+
+ mln::level::fill(deja_vu, false);
+ //mln::level::fill(resp, false);
+ mln::level::fill(area, 0);
+
+ s = level::sort_psites_increasing(f);
+ }
+
+ // first pass
+ {
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ make_set(p);
+ for_all(n)
+ if (f.has(n) && deja_vu(n))
+ do_union(n, p);
+ deja_vu(p) = true;
+ }
+ }
+
+ // second pass: canonization
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (f(parent(q)) == f(q))
+ {
+ parent(p) = parent(q);
+ resp(q) = false;
+ }
+ }
+ }
+
+ // third pass: Merging region with area < lambda
+ {
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (resp(p) && area(p) < lambda)
+ {
+ resp(p) = false;
+ update_data(parent(p), area(p));
+ }
+ }
+ }
+ } // end of run()
+
+ void make_set(const point& p)
+ {
+ parent(p) = p;
+ zpar(p) = p;
+ init_data(p);
+ }
+
+ void set_parent(const point& r, const point& p)
+ {
+ parent(r) = p;
+ merge_data(r, p);
+ }
+
+ bool is_root(const point& p) const
+ {
+ return parent(p) == p;
+ }
+
+ bool is_node(const point& p) const
+ {
+ //return is_root(p) || f(parent(p)) != f(p);
+ return (is_root(p) || resp(p));
+ }
+
+ point find_root(const point& x)
+ {
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = find_root(zpar(x));
+ }
+
+ point find_representative(const point& x)
+ {
+ if (parent(x) == x || resp(x))
+ return x;
+ else
+ return find_representative(parent(x));
+ }
+
+ void do_union(const point& n, const point& p)
+ {
+ point r = find_root(n);
+ if (r != p)
+ {
+ set_parent(r, p);
+ zpar(r) = p;
+ }
+ }
+
+ void init_data(const point& p)
+ {
+ area(p) = 1;
+ resp(p) = true;
+ }
+
+ void merge_data(const point& r, const point& p)
+ {
+ if (f(p) == f(r))
+ {
+ resp(p) = false;
+ area(p) += area(r);
+ }
+ }
+
+ void update_data(const point& p, int val)
+ {
+ area(p) += val;
+ if (parent(p) != p && !resp(p))
+ update_data(parent(p), val);
+ }
+
+ };
+}
+
+namespace mln
+{
+ image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u16> output(data.domain());
+ mln_piter_(image2d<value::int_u16>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // end of mln
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+
+ mln_VAR(edge, ima | is_edge);
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (unsigned row = 0; row < input.nrows(); ++row)
+ for (unsigned col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (unsigned row = 0; row < input.nrows(); row += 2)
+ for (unsigned col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+template <typename I, typename N, typename Ic, typename Nc>
+unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+{
+ using namespace mln;
+
+ min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
+
+ mln_piter(I) p(f.domain());
+ unsigned nnodes = 0;
+ for_all(p)
+ {
+ if (run.is_node(p))
+ {
+ std::cout << "nodes: " << p << std::endl;
+ ++nnodes;
+ }
+ }
+
+ colorize colors(nnodes);
+ image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, ref);
+
+ mln_piter(I) q(f.domain());
+ unsigned int i = 0;
+ for_all(q)
+ {
+ if (run.is_node(q))
+ {
+ tmp(q) = colors(i);
+ i++;
+ }
+ }
+ mln_piter(I) r(f.domain());
+ for_all(r)
+ {
+ if (!run.is_node(r))
+ {
+ tmp(r) = tmp(run.find_representative(r));
+ }
+ }
+
+
+ image2d<value::rgb8> to_display(tmp.domain());
+
+ level::fill(to_display, value::rgb8(255, 255, 255));
+ level::paste((tmp | is_edge), to_display);
+ level::paste(morpho::dilation(to_display, c4()), to_display);
+
+ io::ppm::save(display_edge(tmp, literal::white, 3),
+ "edge.ppm");
+ io::ppm::save(tmp, "full.ppm");
+ io::ppm::save(cells2image(to_display), "colorize.ppm");
+
+ return nnodes;
+}
+
+
+template <typename I>
+I
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /// Graph creation
+ I graph;
+ create_graph(input, graph, value::rgb8(0, 0, 0));
+
+ // Initialization
+ image2d<value::int_u16> ima = convert_to_grey(graph);
+
+ // Neigbhorhood
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+
+ mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v));
+
+ // Algorithm
+ distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima);
+ io::pgm::save(ima, "edge.pgm");
+
+ nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda);
+
+ return graph;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ //io::ppm::save(output, argv[3]);
+}
Index: ballas/color/min_tree_color.cc
--- ballas/color/min_tree_color.cc (revision 0)
+++ ballas/color/min_tree_color.cc (revision 0)
@@ -0,0 +1,525 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+# include <mln/literal/origin.hh>
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/morpho/closing_area.hh>
+
+
+# include <mln/debug/println.hh>
+
+# include "src/distance.hh"
+
+namespace mln
+{
+ template <typename I, typename N, typename Ic, typename Nc>
+ struct min_tree_
+ {
+ typedef mln_site(I) point;
+ typedef p_array<point> S;
+
+ // in:
+ const I& f;
+ const N& nbh;
+ const Ic& ref;
+ const Nc& nbhc;
+
+ // aux:
+ S s;
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, point) parent;
+ mln_ch_value(I, bool) resp;
+ mln_ch_value(I, point) zpar;
+
+ // attached data:
+ unsigned lambda;
+ mln_ch_value(I, value::rgb8) color;
+ //mln_ch_value(Ic, value::rgb8) values;
+ //initialize(values, ref);
+ //mln_ch_value(I, int) comp;
+
+ min_tree_(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+ : f(f),
+ nbh(nbh),
+ ref(ref),
+ nbhc(nbhc),
+ lambda(lambda)
+ {
+ run();
+ }
+
+ void run()
+ {
+ // init
+ {
+ initialize(deja_vu, f);
+ initialize(parent, f);
+ initialize(resp, f);
+ initialize(zpar, f);
+ initialize(color, f);
+ //initialize(comp, f);
+
+ mln::level::fill(deja_vu, false);
+ //mln::level::fill(resp, false);
+ mln::level::fill(color, value::rgb8(0, 0, 0));
+
+ s = level::sort_psites_increasing(f);
+ }
+
+ // first pass
+ {
+ mln_fwd_piter(S) p(s);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ make_set(p);
+ for_all(n)
+ if (f.has(n) && deja_vu(n))
+ do_union(n, p);
+ deja_vu(p) = true;
+ }
+ }
+
+ // second pass: canonization
+ {
+ mln_bkd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (f(parent(q)) == f(q))
+ {
+ parent(p) = parent(q);
+ resp(q) = false;
+ }
+ }
+ }
+
+ // third pass: Merging region with distance(color) < lambda
+ {
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ point q = parent(p);
+ if (resp(p) && distance(color(p), color(q)) < lambda)
+ {
+ resp(p) = false;
+ update_data(q, color(p));
+ }
+ }
+ }
+
+ } // end of run()
+
+ void make_set(const point& p)
+ {
+ parent(p) = p;
+ zpar(p) = p;
+ init_data(p);
+ }
+
+ void set_parent(const point& r, const point& p)
+ {
+ parent(r) = p;
+ merge_data(r, p);
+ }
+
+ bool is_root(const point& p) const
+ {
+ return parent(p) == p;
+ }
+
+ bool is_node(const point& p) const
+ {
+ //return is_root(p) || f(parent(p)) != f(p);
+ return (is_root(p) || resp(p));
+ }
+
+ point find_root(const point& x)
+ {
+ if (zpar(x) == x)
+ return x;
+ else
+ return zpar(x) = find_root(zpar(x));
+ }
+
+ point find_representative(const point& x)
+ {
+ if (parent(x) == x || resp(x))
+ return x;
+ else
+ return find_representative(parent(x));
+ }
+
+ void do_union(const point& n, const point& p)
+ {
+ point r = find_root(n);
+ if (r != p)
+ {
+ set_parent(r, p);
+ zpar(r) = p;
+ }
+ }
+
+ void init_data(const point& p)
+ {
+ int red =0, green = 0, blue = 0;
+
+ mln_niter(Nc) n(nbhc, p);
+ for_all(n)
+ {
+ red += ref(n).red();
+ green += ref(n).green();
+ blue += ref(n).blue();
+ }
+
+ red /= 2;
+ green /= 2;
+ blue /= 2;
+
+ color(p).red() = red;
+ color(p).green() = green;
+ color(p).blue() = blue;
+
+ resp(p) = true;
+ }
+
+ void merge_data(const point& r, const point& p)
+ {
+ if (f(p) == f(r))
+ {
+ resp(p) = false;
+ color(r) = (color(r) + color(p)) / 2;
+ }
+ }
+
+ void update_data(const point& p, value::rgb8 val)
+ {
+ color(p) = (color(p) + val) / 2;
+ if (parent(p) != p && !resp(p))
+ update_data(parent(p), color(p));
+ }
+
+ };
+}
+
+namespace mln
+{
+ image2d<value::int_u16> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u16> output(data.domain());
+ mln_piter_(image2d<value::int_u16>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // end of mln
+
+namespace mln
+{
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+
+ mln_VAR(edge, ima | is_edge);
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+ template <typename I>
+ I display_edge(const I& ima, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+
+ mln_VAR( cell, ima | is_cell );
+ mln_piter(cell_t) q(cell.domain());
+ for_all(q)
+ {
+ unsigned row = (q.row() / 2) * (zoom + 1);
+ unsigned col = (q.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ for (unsigned j = 0; j < zoom; ++j)
+ output.at(row + i, col + j) = ima(q);
+ }
+
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (unsigned row = 0; row < input.nrows(); ++row)
+ for (unsigned col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (unsigned row = 0; row < input.nrows(); row += 2)
+ for (unsigned col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+template <typename I, typename N, typename Ic, typename Nc>
+unsigned min_tree(const I& f, const N& nbh, const Ic& ref, const Nc& nbhc,
+ int lambda)
+{
+ using namespace mln;
+
+ min_tree_<I,N,Ic,Nc> run(f, nbh, ref, nbhc, lambda);
+
+
+ mln_piter(I) p(f.domain());
+ unsigned nnodes = 0;
+ for_all(p)
+ {
+ if (run.is_node(p))
+ ++nnodes;
+ }
+
+#if 1
+ colorize colors(nnodes);
+ image2d<value::rgb8> tmp(ref.domain());
+ level::fill(tmp, ref);
+
+
+ mln_piter(I) q(f.domain());
+ unsigned int i = 0;
+ for_all(q)
+ {
+ if (run.is_node(q))
+ {
+ tmp(q) = colors(i);
+ i++;
+ }
+ }
+ mln_piter(I) r(f.domain());
+ for_all(r)
+ {
+ if (!run.is_node(r))
+ tmp(r) = tmp(run.find_representative(r));
+ }
+
+ image2d<value::rgb8> to_display(tmp.domain());
+
+ level::fill(to_display, value::rgb8(255, 255, 255));
+ level::paste((tmp | is_edge), to_display);
+ level::paste(morpho::dilation(to_display, c4()), to_display);
+
+ io::ppm::save(display_edge(tmp, literal::white, 3),
+ "edge.ppm");
+ io::ppm::save(tmp, "full.ppm");
+ io::ppm::save(cells2image(to_display), "colorize.ppm");
+#endif
+
+#if 1
+ // io::ppm::save(display_edge(run.values, literal::white, 3), "tmp_tree_colored.pgm");
+#endif
+
+ return nnodes;
+}
+
+
+template <typename I>
+I
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /// Graph creation
+ I graph;
+ create_graph(input, graph, value::rgb8(0, 0, 0));
+
+ // Initialization
+ image2d<value::int_u16> ima = convert_to_grey(graph);
+
+ // Neigbhorhood
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+
+ mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR(e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v));
+
+ // Algorithm
+ distance(extend((graph | is_edge).rw(), pw::value(graph)), e2c, ima);
+
+ io::pgm::save(ima, "edge.pgm");
+
+ nbasins = min_tree((ima | is_edge), e2e, graph, e2c, lambda);
+
+ return graph;
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 3)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ //io::ppm::save(output, argv[3]);
+}
Index: ballas/color/reference2.cc
--- ballas/color/reference2.cc (revision 0)
+++ ballas/color/reference2.cc (revision 0)
@@ -0,0 +1,406 @@
+# include <mln/core/var.hh>
+
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image_if.hh>
+# include <mln/core/image/extended.hh>
+# include <mln/core/routine/extend.hh>
+
+# include <mln/core/alias/window2d.hh>
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+# include <mln/core/site_set/p_centered.hh>
+
+# include <mln/literal/origin.hh>
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+
+# include <mln/value/int_u8.hh>
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+
+# include <mln/value/rgb8.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+# include <mln/accu/min_max.hh>
+# include <mln/accu/mean.hh>
+
+# include <mln/fun/i2v/array.hh>
+# include <mln/fun/p2v/iota.hh>
+
+# include <mln/level/paste.hh>
+# include <mln/level/fill.hh>
+# include <mln/level/transform.hh>
+# include <mln/extension/fill.hh>
+
+# include <mln/morpho/meyer_wst.hh>
+# include <mln/morpho/closing_volume.hh>
+
+# include <mln/linear/convolve.hh>
+# include <mln/make/w_window2d.hh>
+
+# include <mln/debug/println.hh>
+
+namespace mln
+{
+ namespace morpho
+ {
+ template <typename I, typename N>
+ mln_concrete(I)
+ closing_volume(const I& input, const Neighborhood<N>& nbh, std::size_t lambda)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+ closing_volume(input, nbh, lambda, output);
+ return output;
+ }
+ }
+}
+
+namespace mln
+{
+ template <typename I, typename O>
+ void
+ LoG_17x17(const I& input, const O& output)
+ {
+ mln_precondition(exact(output).domain() == exact(input).domain());
+ int ws[] = { +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0,
+ +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0,
+ +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0,
+ +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0,
+ +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0,
+ +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0,
+ -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1,
+ -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1,
+ -1,-1,-3,-3,-3, 4,12,21,24,21,12, 4,-3,-3,-3,-1,-1,
+ -1,-1,-3,-3,-2, 2,10,18,21,18,10, 2,-2,-3,-3,-1,-1,
+ -1,-1,-3,-3,-3, 0, 4,10,12,10, 4, 0,-3,-3,-3,-1,-1,
+ +0,-1,-2,-3,-3,-3, 0, 2, 4, 2, 0,-3,-3,-3,-2,-1, 0,
+ +0,-1,-1,-2,-3,-3,-3,-2,-3,-2,-3,-3,-3,-2,-1,-1, 0,
+ +0, 0,-1,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1,-1, 0, 0,
+ +0, 0,-1,-1,-1,-2,-3,-3,-3,-3,-3,-2,-1,-1,-1, 0, 0,
+ +0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0,
+ +0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0 };
+ linear::convolve(input, make::w_window2d(ws), output);
+ }
+} // !mln
+
+namespace mln
+{
+ image2d<value::int_u8> convert_to_grey(const image2d<value::rgb8>& data)
+ {
+ image2d<value::int_u8> output(data.domain());
+ mln_piter_(image2d<value::int_u8>) p(output.domain());
+ for_all(p)
+ output(p) = (int) (data(p).red() * 0.3 + data(p).green() * 0.58 + data(p).blue()) * 0.12;
+ return output;
+ }
+} // !mln
+
+// Functions
+
+inline
+bool is_row_odd(const mln::point2d& p)
+{
+ return p.row() % 2;
+}
+
+inline
+bool is_cell(const mln::point2d& p)
+{
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+}
+
+inline
+bool is_edge(const mln::point2d& p)
+{
+ return p.row() % 2 + p.col() % 2 == 1;
+}
+
+inline
+bool is_point(const mln::point2d& p)
+{
+ return p.row() % 2 && p.col() % 2;
+}
+
+inline
+bool is_not_edge(const mln::point2d& p)
+{
+ return ! is_edge(p);
+}
+
+
+
+namespace mln
+{
+
+ namespace border
+ {
+
+ template <typename I>
+ void
+ fill(I& ima, const mln_value(I)& v)
+ {
+ const int nrows = ima.nrows();
+ const int ncols = ima.ncols();
+ for (int r = -1; r <= nrows; ++r)
+ {
+ ima.at(r, -1) = v;
+ ima.at(r, ncols) = v;
+ }
+ for (int c = -1; c <= ncols; ++c)
+ {
+ ima.at(-1, c) = v;
+ ima.at(nrows, c) = v;
+ }
+ }
+
+ } // mln::border
+
+ namespace accu
+ {
+
+ template <typename I, typename L, typename A, typename V>
+ inline
+ void
+ compute(const Image<I>& input_,
+ const Image<L>& label_,
+ const Accumulator<A>&,
+ V& v)
+ {
+ trace::entering("accu::compute");
+
+ const I& input = exact(input_);
+ const L& label = exact(label_);
+
+ const unsigned n = v.size();
+ std::vector<A> a(n);
+
+ mln_piter(I) p(input.domain());
+ for_all(p)
+ a[label(p)].take(input(p));
+
+ for (unsigned l = 1; l < n; ++l)
+ v(l) = a[l].to_result();
+
+ trace::exiting("accu::compute");
+ }
+
+ } // mln::accu
+
+ namespace morpho
+ {
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ gradient(const I& input, const N& nbh)
+ {
+ mln_concrete(I) output;
+ initialize(output, input);
+ accu::min_max<mln_value(I)> mm;
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ mm.init();
+ for_all(n) if (input.has(n))
+ mm.take(input(n));
+ output(p) = mm.second() - mm.first();
+ }
+ return output;
+ }
+
+ template <typename I, typename N>
+ mln_concrete(I)
+ dilation(const I& input, const N& nbh)
+ {
+ typedef mln_value(I) V;
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ mln_piter(I) p(input.domain());
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ for_all(n)
+ if (input.has(n) && input(n) != value::rgb8(0,0,0))
+ output(p) = input(n);
+ }
+ return output;
+ }
+ } // mln::morpho
+
+
+ struct colorize : Function_v2v< colorize >
+ {
+ typedef value::rgb8 result;
+ colorize(unsigned max)
+ : lut(max + 1)
+ {
+ lut[0] = literal::black;
+ for (unsigned i = 1; i <= max; ++i)
+ lut[i] = result(100 + std::rand() % 150,
+ 100 + std::rand() % 150,
+ 100 + std::rand() % 150);
+ }
+ result operator()(unsigned i) const
+ {
+ return lut[i];
+ }
+ std::vector<result> lut;
+ };
+
+
+ template <typename I>
+ I display_edge(const I& ima, mln_value(I) bg, unsigned zoom)
+ {
+ unsigned nrows = ima.nrows() / 2 + 1;
+ unsigned ncols = ima.ncols() / 2 + 1;
+ I output(nrows * (zoom + 1) - 1,
+ ncols * (zoom + 1) - 1);
+ level::fill(output, bg);
+ mln_VAR( edge, ima | is_edge );
+ mln_piter(edge_t) p(edge.domain());
+ for_all(p)
+ if (p.row() % 2) // horizontal edge
+ {
+ unsigned row = (p.row() / 2 + 1) * (zoom + 1) - 1;
+ unsigned col = (p.col() / 2) * (zoom + 1);
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row, col + i) = ima(p);
+ }
+ else // vertical edge
+ {
+ unsigned row = (p.row() / 2) * (zoom + 1);
+ unsigned col = (p.col() / 2 + 1) * (zoom + 1) - 1;
+ for (unsigned i = 0; i < zoom; ++i)
+ output.at(row + i, col) = ima(p);
+ }
+ return output;
+ }
+
+} // mln
+
+
+
+template <typename T>
+mln::image2d<T>
+image2cells(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output(2 * input.nrows() - 1,
+ 2 * input.ncols() - 1);
+ for (int row = 0; row < input.nrows(); ++row)
+ for (int col = 0; col < input.ncols(); ++col)
+ output.at(2 * row, 2 * col) = input.at(row, col);
+ return output;
+}
+
+
+template <typename T>
+mln::image2d<T>
+cells2image(const mln::image2d<T>& input)
+{
+ mln::image2d<T> output((input.nrows() + 1) / 2,
+ (input.ncols() + 1) / 2);
+ for (int row = 0; row < input.nrows(); row += 2)
+ for (int col = 0; col < input.ncols(); col += 2)
+ output.at(row / 2, col / 2) = input.at(row, col);
+ return output;
+}
+
+
+
+
+template <typename I>
+mln_concrete(I)
+do_it(I& input, int lambda, unsigned& nbasins)
+{
+ using namespace mln;
+
+ /******************/
+ /* Initialisation */
+ /******************/
+
+ image2d<value::int_u8> ima = image2cells(convert_to_grey(input));
+
+ /**************************/
+ /* Neighborhood defintion */
+ /**************************/
+
+ // e2c
+ bool e2c_h[] = { 0, 1, 0,
+ 0, 0, 0,
+ 0, 1, 0 };
+ bool e2c_v[] = { 0, 0, 0,
+ 1, 0, 1,
+ 0, 0, 0 };
+ mln_VAR( e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v) );
+
+ // e2e
+ bool e2e_h[] = { 0, 0, 1, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 0, 0, 1, 0, 0 };
+ bool e2e_v[] = { 0, 0, 0, 0, 0,
+ 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 1,
+ 0, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0 };
+ mln_VAR( e2e, make::double_neighb2d(is_row_odd, e2e_h, e2e_v) );
+
+ // cell
+ mln_VAR(cell, ima | is_cell);
+
+ // edge
+ mln_VAR(edge, extend((ima | is_edge).rw(), pw::value(ima)));
+
+ // FIXME until laplacian is working use gradient / closing_area / wst
+
+ level::paste(morpho::gradient(edge, e2c), edge);
+ level::paste(morpho::closing_volume(edge, e2e, lambda), edge);
+ level::fill(edge, morpho::meyer_wst(edge, e2e, nbasins));
+
+ // Fill regions (with colorize) (won't work with laplacian...)
+
+ colorize colors(nbasins);
+
+ image2d<value::rgb8> cells(ima.domain());
+ level::fill(cells, literal::white);
+ level::paste(level::transform(edge, colors), cells);
+ io::ppm::save(display_edge(cells, literal::white, 3), "tmp_edge.ppm");
+
+ // Move the color of an edge which is non black in the cell
+ level::paste(morpho::dilation(cells, c4()), cells);
+
+ return cells2image(cells);
+}
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm lambda output.ppm" << std::endl;
+ std::cerr << " lambda >= 0" << std::endl;
+ abort();
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ if (argc != 4)
+ usage(argv);
+
+ int lambda = atoi(argv[2]);
+ if (lambda < 0)
+ usage(argv);
+
+ image2d<value::rgb8> ima;
+ io::ppm::load(ima, argv[1]);
+
+ unsigned nbasins;
+ image2d<value::rgb8> output = do_it(ima, lambda, nbasins);
+
+ io::ppm::save(output, argv[3]);
+}
Index: ballas/color/src/graph.hh
--- ballas/color/src/graph.hh (revision 0)
+++ ballas/color/src/graph.hh (revision 0)
@@ -0,0 +1,61 @@
+/*! \file src/graph.hh
+ *
+ */
+
+#ifndef SRC_GRAPH_HH
+# define SRC_GRAPH_HH
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/value/rgb8.hh>
+
+# include <mln/level/fill.hh>
+
+# include <mln/core/image/image2d.hh>
+
+
+// Neighborhood functions
+inline
+bool is_row_odd(const mln::point2d& p)
+{
+ return p.row() % 2;
+}
+inline
+bool is_cell(const mln::point2d& p)
+{
+ return p.row() % 2 == 0 && p.col() % 2 == 0;
+}
+inline
+bool is_edge(const mln::point2d& p)
+{
+ return (p.row() % 2 + p.col() % 2) == 1;
+}
+inline
+bool is_point(const mln::point2d& p)
+{
+ return p.row() % 2 && p.col() % 2;
+}
+inline
+bool is_not_edge(const mln::point2d& p)
+{
+ return ! is_edge(p);
+}
+
+// Graph image creation function
+// FIXME: add exact conversion....
+// FIXME: check that the input image is in 2 dimension
+template <typename I>
+void
+create_graph(const I& ima, I& graph, mln_value(I) val)
+{
+ graph = I(ima.nrows() * 2 -1, ima.ncols() * 2 - 1);
+
+ mln::level::fill(graph, val);
+
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ graph.at(p.row() * 2, p.col() * 2) = ima(p);
+}
+
+
+#endif // !SRC_GRAPH_HH
Index: ballas/color/src/io.hh
--- ballas/color/src/io.hh (revision 0)
+++ ballas/color/src/io.hh (revision 0)
@@ -0,0 +1,57 @@
+/*! \file src/io.hh
+ *
+ * Contains various method to load/save an image
+ */
+
+#ifndef SRC_IO_HH
+# define SRC_IO_HH
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/value/int_u16.hh>
+#include <mln/value/int_s16.hh>
+
+# include <mln/io/pgm/load.hh>
+# include <mln/io/pgm/save.hh>
+# include <mln/io/ppm/load.hh>
+# include <mln/io/ppm/save.hh>
+
+namespace IO
+{
+
+ template <typename I>
+ void load(I& ima, const std::string& file)
+ {
+ mln::io::ppm::load(ima, file);
+ }
+
+ template <>
+ void load(mln::image2d<mln::value::int_u16>& ima,
+ const std::string& file)
+ {
+ mln::io::pgm::load(ima, file);
+ }
+
+ template <typename I>
+ void save(I& ima, const std::string& file)
+ {
+ mln::io::ppm::save(ima, file);
+ }
+
+ template <>
+ void save(mln::image2d<mln::value::int_u16>& ima,
+ const std::string& file)
+ {
+ mln::io::pgm::save(ima, file);
+ }
+
+ template <>
+ void save(mln::image2d<mln::value::int_s16>& ima,
+ const std::string& file)
+ {
+ mln::io::pgm::save(ima, file);
+ }
+
+} // !IO
+
+#endif // !SRC_IO_HH
Index: ballas/color/src/distance.hh
--- ballas/color/src/distance.hh (revision 0)
+++ ballas/color/src/distance.hh (revision 0)
@@ -0,0 +1,52 @@
+/*! \file src/distance.hh
+ *
+ */
+
+#ifndef SRC_DISTANCE_HH
+# define SRC_DISTANCE_HH
+
+# include "graph.hh"
+
+# include <cmath>
+
+
+/// Manhatan distance
+inline
+unsigned distance(const mln::value::rgb8& lhs,
+ const mln::value::rgb8& rhs)
+{
+ return abs(lhs.red() - rhs.red()) +
+ abs(lhs.green() - rhs.green()) +
+ abs(lhs.blue() - rhs.blue());
+}
+
+
+/// Store the distance between two points on edge
+/// FIXME documentation
+template <typename I, typename N, typename O>
+void distance(const I& rgb_graph,
+ const N& nbh,
+ O& gl_graph)
+{
+ mln_piter(I) p(rgb_graph.domain());
+ mln_niter(N) n(nbh, p);
+
+ for_all(p)
+ {
+ mln::value::rgb8 v1;
+ mln::value::rgb8 v2;
+
+ n.start();
+ assert(n.is_valid() && rgb_graph.has(n));
+ v1 = rgb_graph(n);
+ n.next();
+ assert(n.is_valid() && rgb_graph.has(n));
+ v2 = rgb_graph(n);
+
+ gl_graph(p) = distance(v1, v2);
+ }
+}
+
+
+
+#endif // !SRC_DISTANCE_HH
Index: ballas/color/src/convert.hh
--- ballas/color/src/convert.hh (revision 0)
+++ ballas/color/src/convert.hh (revision 0)
@@ -0,0 +1,37 @@
+/*! \file src/convert.hh
+ *
+ * Method that convert an rgb image 2d into gray level
+ */
+
+#ifndef SRC_CONVERT_HH
+# define SRC_CONVERT_HH
+
+# include <mln/value/int_u8.hh>
+# include <mln/value/int_u16.hh>
+# include <mln/value/int_s16.hh>
+# include <mln/value/rgb8.hh>
+
+# include <mln/core/image/image2d.hh>
+
+// Convert function
+void convert_to_gl(mln::image2d<mln::value::int_u16>& ima,
+ const mln::image2d<mln::value::rgb8>& data)
+{
+ mln_piter_(mln::image2d<mln::value::int_u16>) p(ima.domain());
+ for_all(p)
+ ima(p) = (int) (data(p).red() * 0.3 +
+ data(p).green() * 0.58 +
+ data(p).blue() * 0.12);
+}
+
+void convert_to_gl(mln::image2d<mln::value::int_s16>& ima,
+ const mln::image2d<mln::value::rgb8>& data)
+{
+ mln_piter_(mln::image2d<mln::value::int_s16>) p(ima.domain());
+ for_all(p)
+ ima(p) = (int) (data(p).red() * 0.3 +
+ data(p).green() * 0.58 +
+ data(p).blue() * 0.12);
+}
+
+#endif // !SRC_CONVERT_HH
Index: ballas/color/laplacien.cc
--- ballas/color/laplacien.cc (revision 0)
+++ ballas/color/laplacien.cc (revision 0)
@@ -0,0 +1,129 @@
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image_if.hh>
+
+# include <mln/core/alias/neighb2d.hh>
+# include <mln/make/double_neighb2d.hh>
+
+#include <mln/value/rgb8.hh>
+#include <mln/value/int_u16.hh>
+#include <mln/value/int_s16.hh>
+
+#include <mln/linear/gaussian.hh>
+#include <mln/morpho/erosion.hh>
+
+#include <mln/core/var.hh>
+#include <mln/debug/println.hh>
+
+#include "src/io.hh"
+#include "src/graph.hh"
+#include "src/convert.hh"
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.ppm output.pgm" << std::endl;
+ abort();
+}
+
+/// FIXME Put these elsewhere
+typedef mln::image2d<mln::value::rgb8> Icolor;
+typedef mln::image2d<mln::value::int_u16> Igray;
+
+void process(Icolor& graph, const Icolor& input)
+{
+ using namespace mln;
+
+ // Neighborhood definition
+
+// bool e2c_h[] = { 0, 1, 0,
+// 0, 0, 0,
+// 0, 1, 0 };
+// bool e2c_v[] = { 0, 0, 0,
+// 1, 0, 1,
+// 0, 0, 0 };
+
+// bool e2e_h[] = { 0, 0, 1, 0, 0,
+// 0, 1, 0, 1, 0,
+// 0, 0, 0, 0, 0,
+// 0, 1, 0, 1, 0,
+// 0, 0, 1, 0, 0 };
+// bool e2e_v[] = { 0, 0, 0, 0, 0,
+// 0, 1, 0, 1, 0,
+// 1, 0, 0, 0, 1,
+// 0, 1, 0, 1, 0,
+// 0, 0, 0, 0, 0 };
+
+// bool e2p_h[] = { 0, 0, 1,
+// 0, 0, 0,
+// 1, 0, 0 };
+// bool e2p_v[] = { 1, 0, 0,
+// 0, 0, 0,
+// 0, 0, 1 };
+ //mln_VAR(e2c, make::double_neighb2d(is_row_odd, e2c_h, e2c_v));
+
+
+ // convert the image into grey level
+ Igray gray_graph(graph.bbox());
+ convert_to_gl(gray_graph, graph);
+
+ Igray gray_input(input.bbox());
+ convert_to_gl(gray_input, input);
+
+
+ //level::paste(morpho::dilation((gray_graph | is_cell), e2c.win()), gray_graph);
+// Igray save(gray_graph.bbox());
+// level::paste(gray_graph | is_cell, save);
+// IO::save(save, "tmp3.ppm");
+
+ // Create the laplacian image
+ //Igray laplacian(gray_input.bbox());
+ image2d<int> laplacian(gray_input.bbox());
+ linear::gaussian(gray_input, 2.0f, laplacian);
+ //IO::save(laplacian, "tmp1.ppm");
+ linear::laplacian(gray_input, 2.0f, laplacian);
+ debug::println(laplacian);
+ //IO::save(laplacian, "tmp2.ppm");
+
+ // Display edge on the output images
+// debug::println(laplacian);
+
+// mln_piter_(Igray) p(laplacian.domain());
+// for_all(p)
+// if (laplacian(p) == 0u)
+// {
+// std::cout << "I'm here" << std::endl;
+// graph.at(p.row() * 2, p.col() * 2) = value::rgb<8>(255, 0, 0);
+// }
+
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ // Initialisation
+ if (argc != 3)
+ usage(argv);
+
+ std::string input_file(argv[1]);
+ std::string output_file(argv[2]);
+
+
+ Icolor input;
+
+ // Load the image
+ IO::load(input, input_file);
+
+ // create a graph image from the input
+ Icolor graph;
+ create_graph(input, graph);
+
+ // Process
+ process(graph, input);
+
+
+ // Save
+ IO::save(graph, output_file);
+}
1
0
From: Maxime van Noppen <yabo(a)lrde.epita.fr>
To: olena-patches(a)lrde.epita.fr
Subject: milena r2770: Fix an include problem in mln/morpho
URL: https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
ChangeLog:
2008-11-03 Maxime van Noppen <yabo(a)lrde.epita.fr>
Fix an include problem in mln/morpho.
* includes.hh: As erosion is used in dilation it must be included
* before. Same for complementation.
---
includes.hh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
Index: branches/cleanup-2008/milena/mln/morpho/includes.hh
===================================================================
--- branches/cleanup-2008/milena/mln/morpho/includes.hh (revision 2769)
+++ branches/cleanup-2008/milena/mln/morpho/includes.hh (revision 2770)
@@ -66,11 +66,11 @@
# include <mln/win/diff.hh>
# include <mln/win/inter.hh>
-# include <mln/morpho/dilation.hh>
# include <mln/morpho/erosion.hh>
+# include <mln/morpho/complementation.hh>
+# include <mln/morpho/dilation.hh>
# include <mln/morpho/min.hh>
-# include <mln/morpho/complementation.hh>
# include <mln/morpho/minus.hh>
# include <mln/morpho/plus.hh>
1
0
03 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Hack morphological dilation so it is practicable.
* tests/morpho/dilation.cc: Fix copyright.
(neighb/image.hh): Fix missing guards for this include.
* mln/morpho/dilation.hh (todo): New.
Fix copyright.
(impl): Remove all implementations; they were obsolete.
(dilation_as_erosion_dual): New implementation.
(dilation_tests, dilation_dispatch): New.
mln/morpho/dilation.hh | 251 ++++++-----------------------------------------
tests/morpho/dilation.cc | 9 +
2 files changed, 45 insertions(+), 215 deletions(-)
Index: tests/morpho/dilation.cc
--- tests/morpho/dilation.cc (revision 2768)
+++ tests/morpho/dilation.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// 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
@@ -49,7 +50,13 @@
#include <mln/fun/ops.hh>
#include <mln/core/alias/neighb2d.hh>
+
+ /* FIXME: Re-enable these tests for Olena 1.1, when associated
+ neighborhoods (i.e., the neighb::image morpher) are supported and
+ shipped. */
+#if 0
#include <mln/neighb/image.hh>
+#endif
#include "tests/data.hh"
Index: mln/morpho/dilation.hh
--- mln/morpho/dilation.hh (revision 2768)
+++ mln/morpho/dilation.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// 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
@@ -29,9 +30,10 @@
# define MLN_MORPHO_DILATION_HH
/// \file mln/morpho/dilation.hh
-/// \brief Morphological dilation.
///
-/// \todo Activate the FIXMEs (border::adjust).
+/// Morphological dilation.
+///
+/// \todo Revamp.
# include <mln/morpho/includes.hh>
@@ -42,28 +44,9 @@
namespace morpho
{
- /// Morphological dilation using the neighborhood bound to an image.
- ///
- /// \{
- /* FIXME: Re-enable this routine for Olena 1.1, when associated
- neighborhoods (i.e., the neighb::image morpher) are supported
- and shipped. */
-#if 0
- /// Perform a morphological dilation of \a input using its
- /// neighborhood and return the result.
- ///
- /// \pre \a input must be an image with a neighborhood.
- template <typename I>
- mln_concrete(I)
- dilation(const Image<I>& input);
- /// \}
-#endif
/// Morphological dilation using windows.
///
- /// \todo Overload dilation_wrt_win for hline and vline and for fast
- /// images.
- ///
/// \{
/// Perform a morphological dilation of \a input using \a win and
/// return the result.
@@ -74,223 +57,68 @@
-# ifndef MLN_INCLUDE_ONLY
-
- namespace impl
- {
-
- /*---------------.
- | Window-based. |
- `---------------*/
-
- // On function.
-
- template <typename I, typename W, typename O>
- inline
- void dilation_on_function(const Image<I>& input_, const Window<W>& win_,
- Image<O>& output_)
- {
- const I& input = exact(input_);
- const W& win = exact(win_);
- O& output = exact(output_);
- // FIXME: border::adjust(input, win.delta());
- extension::fill(input, mln_min(mln_value(I)));
+# ifndef MLN_INCLUDE_ONLY
- accu::max<mln_value(I)> max;
+ // Tests.
- mln_piter(I) p(input.domain());
- mln_qiter(W) q(win, p);
- for_all(p)
+ namespace internal
{
- max.init();
- for_all(q) if (input.has(q))
- max.take(input(q));
- output(p) = max.to_result();
- }
- }
- // On set.
-
- template <typename I, typename W, typename O>
- inline
- void dilation_on_set(const Image<I>& input_, const Window<W>& win_,
- Image<O>& output_)
+ template <typename I, typename W>
+ void
+ dilation_tests(const Image<I>& input_, const Window<W>& win_)
{
const I& input = exact(input_);
const W& win = exact(win_);
- O& output = exact(output_);
-
- // FIXME: border::adjust(input, win.delta());
- extension::fill(input, false);
-
- level::fill(output, input);
-
- mln_piter(I) p(input.domain());
- mln_qiter(W) q(win, p);
- for_all(p)
- if (!input(p))
- for_all(q) if (input.has(q))
- if (input(q))
- {
- output(p) = true;
- break;
+ mln_precondition(input.has_data());
+ // mln_precondition(win.is_valid());
+ (void) input;
+ (void) win;
}
- }
-
- // ------------- //
- // Dispatchers. //
- // ------------- //
+ } // end of namespace mln::morpho::internal
- // FIXME: Stage 3: dispatch w.r.t. speed property.
- // ...
+ // Implementations.
- /// Stage 2: dispatch w.r.t. the value kind.
- /// \{
-
- /// Binary => morphology on sets.
- template <typename I, typename W, typename O>
- inline
- void dilation_wrt_value(trait::image::kind::logic,
- const Image<I>& input, const Window<W>& win,
- Image<O>& output)
+ namespace impl
{
- return impl::dilation_on_set(exact(input), exact(win), output);
- }
- /// Otherwise => morphology on functions.
- template <typename I, typename W, typename O>
- inline
- void dilation_wrt_value(trait::image::kind::any,
- const Image<I>& input, const Window<W>& win,
- Image<O>& output)
+ template <typename I, typename W>
+ mln_concrete(I)
+ dilation_as_erosion_dual(const Image<I>& input, const Window<W>& win)
{
- return impl::dilation_on_function(exact(input), exact(win), output);
- }
-
- // End of stage 2.
-
- /// \}
+ trace::entering("morpho::impl::dilation_as_erosion_dual");
+ mln_concrete(I) output = morpho::erosion(morpho::complementation(input),
+ win);
+ morpho::complementation_inplace(output);
-
- /// 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);
+ trace::exiting("morpho::impl::dilation_as_erosion_dual");
+ return output;
}
-# ifdef MLN_CORE_WIN_RECTANGLE2D_HH
-
- /// Rectangle window.
- template <typename I, typename O>
- inline
- void dilation_wrt_win(const Image<I>& input, const win::rectangle2d& win,
- Image<O>& output)
- {
- O temp(exact(output).domain());
- morpho::dilation(input, win::hline2d(win.width()), temp);
- morpho::dilation(temp, win::vline2d(win.height()), output);
- }
+ } // end of namespace mln::morpho::impl
-# endif // MLN_CORE_WIN_RECTANGLE2D_HH
-# ifdef MLN_CORE_WIN_OCTAGON2D_HH
-# ifdef MLN_CORE_WIN_DIAG2D_HH
-# ifdef MLN_CORE_WIN_BACKDIAG2D_HH
+ // Dispatch.
- /// Octagon window.
- template <typename I, typename O>
- void dilation_wrt_win(const Image<I>& input, const win::octagon2d& win,
- Image<O>& output)
+ namespace internal
{
- const unsigned len = win.length() / 3 + 1;
-
- O temp1(exact(output).domain());
- O temp2(exact(output).domain());
- morpho::dilation(input, win::hline2d(len), temp1);
- morpho::dilation(temp1, win::vline2d(len), temp2);
- morpho::dilation(temp2, win::diag2d(len), temp1);
- morpho::dilation(temp1, win::backdiag2d(len), output);
- }
-
-# endif // MLN_CORE_WIN_BACKDIAG2D_HH
-# endif // MLN_CORE_WIN_DIAG2D_HH
-# endif // MLN_CORE_WIN_OCTAGON2D_HH
- // End of stage 1.
-
- /// \}
-
-
- /*---------------------.
- | Neighborhood-based. |
- `---------------------*/
-
- // FIXME: Disabled (see above).
-#if 0
- /* 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)
+ template <typename I, typename W>
+ mln_concrete(I)
+ dilation_dispatch(const Image<I>& input, const Window<W>& win)
{
- /* 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, nbh.win(), output);
+ return impl::dilation_as_erosion_dual(input, win);
}
-#endif
- } // end of namespace mln::morpho::impl
+ } // end of namespace mln::morpho::internal
- /*----------.
- | Facades. |
- `----------*/
-
- // ----------------------------------------------- //
- // Facade for neighborhood-based implementations. //
- // ----------------------------------------------- //
-
- // FIXME: Disabled (see above).
-#if 0
- template <typename I>
- mln_concrete(I)
- dilation(const Image<I>& input)
- {
- trace::entering("morpho::dilation");
-
- metal::has_neighborhood<I>::check();
- typedef mln_neighb(I) neighb;
-
- mln_concrete(I) output;
- initialize(output, input);
- impl::dilation_wrt_nbh(input, exact(input).neighborhood(), output);
- trace::exiting("morpho::dilation");
- return output;
- }
-#endif
// ----------------------------------------- //
// Facade for window-based implementations. //
@@ -301,15 +129,10 @@
dilation(const Image<I>& input, const Window<W>& win)
{
trace::entering("morpho::dilation");
- mln_precondition(exact(input).has_data());
- mln_precondition(! exact(win).is_empty());
- mln_concrete(I) output;
- initialize(output, input);
- impl::dilation_wrt_win(input, exact(win), output);
+ internal::dilation_tests(input, win);
+ mln_concrete(I) output = internal::dilation_dispatch(input, win);
- if (exact(win).is_centered())
- mln_postcondition(output >= input);
trace::exiting("morpho::dilation");
return output;
}
1
0
cleanup-2008 2768: Fix many little things in weighted window related stuff.
by Thierry Geraud 03 Nov '08
by Thierry Geraud 03 Nov '08
03 Nov '08
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Fix many little things in weighted window related stuff.
* tests/core/alias/w_window1d_int.cc: Fix doc.
* tests/core/alias/window1d.cc: Likewise.
Remove echo on std::cout.
* tests/core/alias/w_window3d_int.cc: Likewise.
* tests/core/alias/window3d.cc: Likewise.
* tests/core/alias/w_window2d_int.cc: Fix doc.
* tests/core/alias/window2d.cc: Remove useless include.
* mln/trait/image_from_grid.hh: Update doc style.
* mln/core/concept/weighted_window.hh: Likewise.
(sym): Fix sig in doc.
(W): Rename this parameter as...
(E): ...this to remain consistent with othe concept files.
(is_empty, is_centered, delta): Move to...
* mln/core/internal/weighted_window_base.hh: ...this new file.
* mln/core/concept/object.hh: Include some more metal stuff.
* mln/core/concept/window.hh
(level::fill): Replace by plain code to supress dep.
(internal::bbox_): Move this hack into...
* mln/core/internal/geom_bbox.hh: ...this new file.
Update include.
* mln/core/w_window.hh (w_window): Update inheritance.
* mln/core/internal/window_base.hh: Fix copyright.
* mln/make/w_window2d.hh: Fix missing include.
* mln/convert/to_image.hh: Likewise.
(to_image): Fix sig in the Weighted_Window overload.
mln/convert/to_image.hh | 11 +
mln/core/concept/object.hh | 2
mln/core/concept/weighted_window.hh | 63 ++++------
mln/core/concept/window.hh | 39 +-----
mln/core/internal/geom_bbox.hh | 75 ++++++++++++
mln/core/internal/weighted_window_base.hh | 178 ++++++++++++++++++++++++++++++
mln/core/internal/window_base.hh | 2
mln/core/w_window.hh | 57 ++-------
mln/make/w_window2d.hh | 1
mln/trait/image_from_grid.hh | 12 +-
tests/core/alias/w_window1d_int.cc | 5
tests/core/alias/w_window2d_int.cc | 8 -
tests/core/alias/w_window3d_int.cc | 15 --
tests/core/alias/window1d.cc | 9 -
tests/core/alias/window2d.cc | 1
tests/core/alias/window3d.cc | 14 --
16 files changed, 339 insertions(+), 153 deletions(-)
Index: tests/core/alias/w_window1d_int.cc
--- tests/core/alias/w_window1d_int.cc (revision 2767)
+++ tests/core/alias/w_window1d_int.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// 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
@@ -26,7 +27,7 @@
// Public License.
/// \file tests/core/alias/w_window1d_int.cc
-/// \brief Tests on mln::w_window1d_int.
+/// Tests on mln::w_window1d_int.
#include <mln/core/alias/w_window1d_int.hh>
#include <mln/win/segment1d.hh>
Index: tests/core/alias/window1d.cc
--- tests/core/alias/window1d.cc (revision 2767)
+++ tests/core/alias/window1d.cc (working copy)
@@ -1,4 +1,5 @@
-// 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
@@ -31,9 +32,7 @@
*/
#include <mln/core/alias/window1d.hh>
-#include <mln/core/image/image1d.hh>
#include <mln/convert/to_image.hh>
-#include <mln/debug/println.hh>
@@ -46,14 +45,12 @@
mln_assertion(w.is_centered() == false);
mln_assertion(w.is_symmetric() == true);
- // FIXME: Does not compile as expected.
+ // As expected, the code below does not compile:
// w.insert(-1,0);
w.insert(-1);
w.insert( 1);
image1d<bool> ima = convert::to_image(w);
- debug::println(ima);
-
mln_assertion(w.delta() == 1);
}
Index: tests/core/alias/w_window2d_int.cc
--- tests/core/alias/w_window2d_int.cc (revision 2767)
+++ tests/core/alias/w_window2d_int.cc (working copy)
@@ -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
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/core/alias/w_window2d_int.cc
- *
- * \brief Tests on mln::w_window2d_int.
- */
+/// \file tests/core/alias/w_window2d_int.cc
+///
+/// Tests on mln::w_window2d_int.
#include <mln/core/alias/w_window2d_int.hh>
#include <mln/win/rectangle2d.hh>
Index: tests/core/alias/window2d.cc
--- tests/core/alias/window2d.cc (revision 2767)
+++ tests/core/alias/window2d.cc (working copy)
@@ -31,7 +31,6 @@
/// Tests on mln::window2d.
#include <mln/core/alias/window2d.hh>
-#include <mln/core/image/image2d.hh>
#include <mln/convert/to_image.hh>
Index: tests/core/alias/w_window3d_int.cc
--- tests/core/alias/w_window3d_int.cc (revision 2767)
+++ tests/core/alias/w_window3d_int.cc (working copy)
@@ -1,4 +1,5 @@
-// 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
@@ -25,10 +26,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/core/alias/w_window3d_int.cc
- *
- * \brief Tests on mln::w_window3d_int.
- */
+/// tests/core/alias/w_window3d_int.cc
+///
+/// Tests on mln::w_window3d_int.
#include <mln/core/alias/w_window3d_int.hh>
#include <mln/win/cube3d.hh>
@@ -38,8 +38,6 @@
#include <mln/convert/to_fun.hh>
#include <mln/estim/sum.hh>
-#include <mln/debug/println.hh>
-
int f(mln::point3d p)
{
@@ -64,8 +62,6 @@
w_window3d_int w_win = make::w_window3d(ws);
image3d<int> ima = convert::to_image(w_win);
- debug::println(ima);
- std::cout << std::endl;
w_window3d_int w_win_2 = convert::to<w_window3d_int>(ima);
mln_assertion(w_win_2 == w_win);
}
@@ -77,7 +73,6 @@
// -2 -1 0 +1 +2
// -1 0 +1 +2 +3
image3d<int> ima = convert::to_image(w_win);
- debug::println(ima);
mln_assertion(estim::sum(ima) == 0);
}
Index: tests/core/alias/window3d.cc
--- tests/core/alias/window3d.cc (revision 2767)
+++ tests/core/alias/window3d.cc (working copy)
@@ -1,4 +1,5 @@
-// 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
@@ -31,10 +32,7 @@
*/
#include <mln/core/alias/window3d.hh>
-#include <mln/core/image/image3d.hh>
#include <mln/convert/to_image.hh>
-#include <mln/debug/println.hh>
-
int main()
@@ -46,12 +44,10 @@
mln_assertion(w.is_centered() == false);
mln_assertion(w.is_symmetric() == true);
- w.insert(dpoint3d(-1, -1, -1));
- w.insert(dpoint3d( 1, 1, 1));
- w.insert(dpoint3d( 0, 0, 2));
+ w.insert(-1, -1, -1);
+ w.insert( 1, 1, 1);
+ w.insert( 0, 0, 2);
image3d<bool> ima = convert::to_image(w);
- debug::println(ima);
-
mln_assertion(w.delta() == 2);
}
Index: mln/trait/image_from_grid.hh
--- mln/trait/image_from_grid.hh (revision 2767)
+++ mln/trait/image_from_grid.hh (working copy)
@@ -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,13 @@
#ifndef MLN_TRAIT_IMAGE_FROM_MESH_HH
# define MLN_TRAIT_IMAGE_FROM_MESH_HH
-/*! \file mln/trait/image_from_grid.hh
- *
- * \brief Definition of the "image from mesh" trait.
- */
+/// \file mln/trait/image_from_grid.hh
+///
+/// Definition of the "image from mesh" trait.
+///
+/// This file shall not include the concrete image types it returns;
+/// otherwise we get circular dependencies. As a consequence the user
+/// shall include the appropriate image type she deals with.
# include <mln/core/grids.hh>
Index: mln/core/w_window.hh
--- mln/core/w_window.hh (revision 2767)
+++ mln/core/w_window.hh (working copy)
@@ -37,7 +37,7 @@
# include <map>
-# include <mln/core/concept/weighted_window.hh>
+# include <mln/core/internal/weighted_window_base.hh>
# include <mln/core/concept/image.hh>
# include <mln/core/site_set/box.hh>
# include <mln/core/window.hh>
@@ -45,7 +45,6 @@
# include <mln/value/ops.hh>
# include <mln/util/ord.hh>
-# include <mln/level/fill.hh>
# include <mln/geom/bbox.hh> // FIXME: We may have some dep trouble with this include.
# include <mln/literal/zero.hh>
# include <mln/convert/to.hh>
@@ -63,7 +62,7 @@
{
template <typename D, typename W>
- struct window_< mln::w_window<D,W> > : window_<W>
+ struct window_< mln::w_window<D,W> > : window_< mln::window<D> >
{
// Same traits as its corresponding window.
};
@@ -78,23 +77,15 @@
* the type of weights.
*/
template <typename D, typename W>
- struct w_window : public Weighted_Window< w_window<D,W> >
+ struct w_window : public internal::weighted_window_base< mln::window<D>,
+ w_window<D,W> >
{
/// Dpsite associated type.
typedef D dpsite;
- /// Psite associated type.
- typedef mln_psite(D) psite;
-
- /// Site associated type.
- typedef mln_site(D) site;
-
/// Weight associated type.
typedef W weight;
- /// Window associated type.
- typedef mln::window<D> window;
-
/// Site_Iterator type to browse (forward) the points of a generic w_window.
typedef with_w_< dpsites_fwd_piter< w_window<D, W> >, W > fwd_qiter;
@@ -118,12 +109,6 @@
const std::vector<W>& weights() const;
- // Give the \p i-th delta-point.
- const D& dp(unsigned i) const;
-
- /// Give the number of delta-points.
- unsigned size() const;
-
/// Give access to the vector of delta-points.
const std::vector<D>& std_vector() const;
@@ -237,25 +222,6 @@
template <typename D, typename W>
inline
- const D&
- w_window<D,W>::dp(unsigned i) const
- {
- mln_precondition(i < win_.size());
- mln_invariant(wei_.size() == win_.size());
- return win_.dp(i);
- }
-
- template <typename D, typename W>
- inline
- unsigned
- w_window<D,W>::size() const
- {
- mln_invariant(wei_.size() == win_.size());
- return win_.size();
- }
-
- template <typename D, typename W>
- inline
const std::vector<D>&
w_window<D,W>::std_vector() const
{
@@ -344,9 +310,10 @@
mlc_converts_to(mln_value(I), W)::check();
const I& ima = exact(from_);
to.clear();
+ mln_value(I) zero = literal::zero;
mln_piter(I) p(ima.domain());
for_all(p)
- if (ima(p) != literal::zero)
+ if (ima(p) != zero)
to.insert(ima(p), convert::to<D>(p));
}
@@ -363,8 +330,13 @@
// mln_precondition(w_win.is_valid());
ima.init_(geom::bbox(w_win));
- level::fill(ima, literal::zero);
-
+ {
+ // level::fill(ima, literal::zero) is:
+ mln_value(I) zero = literal::zero;
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = zero;
+ }
unsigned n = w_win.size();
for (unsigned i = 0; i < n; ++i)
ima(convert::to<P>(w_win.dp(i))) = w_win.w(i);
@@ -407,9 +379,10 @@
box<P> b(all_to(-s), all_to(+s));
mln_fwd_piter(box<P>) p(b);
unsigned i = 0;
+ V zero = literal::zero;
for_all(p)
{
- if (weight[i] != literal::zero)
+ if (weight[i] != zero)
to.insert(weight[i], convert::to<D>(p));
++i;
}
Index: mln/core/concept/weighted_window.hh
--- mln/core/concept/weighted_window.hh (revision 2767)
+++ mln/core/concept/weighted_window.hh (working copy)
@@ -29,10 +29,11 @@
#ifndef MLN_CORE_CONCEPT_WEIGHTED_WINDOW_HH
# define MLN_CORE_CONCEPT_WEIGHTED_WINDOW_HH
-/*! \file mln/core/concept/weighted_window.hh
- *
- * \brief Definition of the concept of mln::Weighted_Window.
- */
+/// \file mln/core/concept/weighted_window.hh
+///
+/// Definition of the concept of mln::Weighted_Window.
+///
+/// \todo Make ::sym() be optional.
# include <mln/core/concept/object.hh>
# include <mln/core/concept/iterator.hh>
@@ -42,8 +43,9 @@
namespace mln
{
- // Fwd decl.
- template <typename W> struct Weighted_Window;
+ // Forward declaration.
+ template <typename E> struct Weighted_Window;
+
// Weighted_Window category flag type.
template <>
@@ -59,8 +61,8 @@
* \see mln::doc::Weighted_Window for a complete documentation of
* this class contents.
*/
- template <typename W>
- struct Weighted_Window : public Object<W>
+ template <typename E>
+ struct Weighted_Window : public Object<E>
{
typedef Weighted_Window<void> category;
@@ -74,29 +76,9 @@
typedef weight;
typedef window;
- E& sym();
+ void sym();
*/
- /// Test if the weighted window is empty; final method.
- bool is_empty() const
- {
- return exact(this)->win().is_empty();
- }
-
- /// Test if the weighted window is centered; final method.
- bool is_centered() const
- {
- return exact(this)->win().is_centered();
- }
-
- // FIXME: Remove because too ambiguous: bool is_symmetric() const
-
- /// Give the maximum coordinate gap.
- unsigned delta() const
- {
- return exact(this)->win().delta();
- }
-
protected:
Weighted_Window();
};
@@ -110,24 +92,27 @@
W operator-(const Weighted_Window<W>& rhs);
+
# ifndef MLN_INCLUDE_ONLY
- template <typename W>
+ template <typename E>
inline
- Weighted_Window<W>::Weighted_Window()
+ Weighted_Window<E>::Weighted_Window()
{
- //typedef mln_psite(E) point;
- //typedef mln_dpsite(E) dpoint;
- typedef mln_weight(W) weight;
- typedef mln_window(W) window;
+ typedef mln_site(E) site;
+ typedef mln_psite(E) psite;
+ typedef mln_dpsite(E) dpsite;
+
+ typedef mln_weight(E) weight;
+ typedef mln_window(E) window;
- typedef mln_fwd_qiter(W) fwd_qiter;
- typedef mln_bkd_qiter(W) bkd_qiter;
+ typedef mln_fwd_qiter(E) fwd_qiter;
+ typedef mln_bkd_qiter(E) bkd_qiter;
- void (W::*m1)() = & W::sym;
+ void (E::*m1)() = & E::sym;
m1 = 0;
- const window& (W::*m2)() const = & W::win;
+ const window& (E::*m2)() const = & E::win;
m2 = 0;
}
Index: mln/core/concept/object.hh
--- mln/core/concept/object.hh (revision 2767)
+++ mln/core/concept/object.hh (working copy)
@@ -47,6 +47,8 @@
# include <mln/metal/is_a.hh>
# include <mln/metal/is.hh>
# include <mln/metal/is_not.hh>
+# include <mln/metal/equal.hh>
+# include <mln/metal/not_equal.hh>
# include <mln/metal/converts_to.hh>
# include <mln/metal/ret.hh>
# include <mln/metal/unqualif.hh>
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 2767)
+++ mln/core/concept/window.hh (working copy)
@@ -38,8 +38,6 @@
*
* \todo The is_centered() method could also exist when the window is
* not regular...
- *
- * \todo Remove hack.
*/
# include <mln/core/concept/object.hh>
@@ -47,10 +45,7 @@
# include <mln/trait/windows.hh>
# include <mln/core/site_set/p_array.hh>
-
-# include <mln/accu/bbox.hh>
-# include <mln/literal/origin.hh>
-# include <mln/level/fill.hh>
+# include <mln/core/internal/geom_bbox.hh> // For use in convert::from_to.
# include <mln/convert/from_to.hxx>
@@ -307,27 +302,6 @@
namespace convert
{
- namespace internal
- {
-
-
- // FIXME: Hack to avoid including geom::bbox (circular
- // dependency).
-
- template <typename W>
- box<mln_psite(W)> bbox_(const Window<W>& win)
- {
- typedef mln_psite(W) P;
- accu::bbox<P> b;
- P O = literal::origin;
- mln_qiter(W) q(exact(win), O);
- for_all(q)
- b.take(q);
- return b;
- }
-
- }
-
template <typename W, typename I>
void
from_to(const Window<W>& win_, Image<I>& ima_)
@@ -343,9 +317,14 @@
// mln_precondition(win.is_valid());
mln_precondition(! ima.has_data());
- ima.init_(internal::bbox_(win)); // geom::bbox(win));
- level::fill(ima, false);
-
+ // Hack (below) to avoid circular dependency.
+ ima.init_(mln::internal::geom_bbox(win));
+ {
+ // level::fill(ima, false) is:
+ mln_piter(I) p(ima.domain());
+ for_all(p)
+ ima(p) = false;
+ }
unsigned n = win.size();
for (unsigned i = 0; i < n; ++i)
ima(convert::to<P>(win.dp(i))) = true;
Index: mln/core/internal/geom_bbox.hh
--- mln/core/internal/geom_bbox.hh (revision 0)
+++ mln/core/internal/geom_bbox.hh (revision 0)
@@ -0,0 +1,75 @@
+// 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_CORE_INTERNAL_GEOM_BBOX_HH
+# define MLN_CORE_INTERNAL_GEOM_BBOX_HH
+
+/// \file mln/core/internal/geom_bbox.hh
+///
+/// \internal Routine that computes a bounding box from a window.
+/// This file is included in mln/core/concept/window.hh and avoid
+/// circular dependency since mln/geom/bbox.hh cannot be included in
+/// concept files.
+
+# include <mln/accu/bbox.hh>
+# include <mln/literal/origin.hh>
+
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ template <typename W>
+ box<mln_psite(W)>
+ geom_bbox(const W& win);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename W>
+ box<mln_psite(W)>
+ geom_bbox(const W& win)
+ {
+ typedef mln_psite(W) P;
+ accu::bbox<P> b;
+ P O = literal::origin;
+ mln_qiter(W) q(exact(win), O);
+ for_all(q)
+ b.take(q);
+ return b;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::internal
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_INTERNAL_GEOM_BBOX_HH
Index: mln/core/internal/weighted_window_base.hh
--- mln/core/internal/weighted_window_base.hh (revision 0)
+++ mln/core/internal/weighted_window_base.hh (revision 0)
@@ -0,0 +1,178 @@
+// 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_CORE_INTERNAL_WEIGHTED_WINDOW_BASE_HH
+# define MLN_CORE_INTERNAL_WEIGHTED_WINDOW_BASE_HH
+
+/// \file mln/core/internal/weighted_window_base.hh
+///
+/// Definition of a base class for weighted window classes.
+
+# include <mln/core/concept/weighted_window.hh>
+
+
+namespace mln
+{
+
+ namespace internal
+ {
+
+ /// Base class for weighted window classes.
+ ///
+ /// \p W is the corresponding window type.
+
+ template <typename W, typename E>
+ struct weighted_window_base : public Weighted_Window<E>
+ {
+
+ /// Window associated type.
+ typedef W window;
+
+ /// Dpsite associated type.
+ typedef mln_dpsite(W) dpsite;
+
+ /// Psite associated type.
+ typedef mln_psite(W) psite;
+
+ /// Site associated type.
+ typedef mln_site(W) site;
+
+ /// Test if the weighted window is empty; final method.
+ bool is_empty() const;
+
+ /// Give the window size; final method. This method is valid
+ /// iff the underlying window has a fixed size.
+ unsigned size() const;
+
+ /// Test if the weighted window is centered; final method. This
+ /// method is valid iff the support is regular and the
+ /// definition is not varying.
+ bool is_centered() const;
+
+ /// Give the maximum coordinate gap; final method. This method
+ /// is valid iff the support is regular and the definition is
+ /// not varying.
+ unsigned delta() const;
+
+ /// Give the \p i-th delta-point; final method. This method is
+ /// valid iff the support is regular and the definition is
+ /// unique.
+ const mln_dpsite(W)& dp(unsigned i) const;
+
+ /// Test if the \p dp delta-point is in this window; final
+ /// method. This method is valid iff the support is regular and
+ /// the definition is unique.
+ bool has(const mln_dpsite(W)& dp) const;
+
+ protected:
+ weighted_window_base();
+ };
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename W, typename E>
+ inline
+ weighted_window_base<W,E>::weighted_window_base()
+ {
+ }
+
+ template <typename W, typename E>
+ inline
+ bool
+ weighted_window_base<W,E>::is_empty() const
+ {
+ return exact(this)->win().is_empty();
+ }
+
+ template <typename W, typename E>
+ inline
+ unsigned
+ weighted_window_base<W,E>::size() const
+ {
+ mlc_equal(mln_trait_window_size(W),
+ trait::window::size::fixed)::check();
+ return exact(this)->win().size();
+ }
+
+ template <typename W, typename E>
+ inline
+ bool
+ weighted_window_base<W,E>::is_centered() const
+ {
+ mlc_equal(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_not_equal(mln_trait_window_definition(W),
+ trait::window::definition::varying)::check();
+ return exact(this)->win().is_centered();
+ }
+
+ template <typename W, typename E>
+ inline
+ unsigned
+ weighted_window_base<W,E>::delta() const
+ {
+ mlc_equal(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_not_equal(mln_trait_window_definition(W),
+ trait::window::definition::varying)::check();
+ return exact(this)->win().delta();
+ }
+
+ template <typename W, typename E>
+ inline
+ const mln_dpsite(W)&
+ weighted_window_base<W,E>::dp(unsigned i) const
+ {
+ mlc_equal(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_equal(mln_trait_window_definition(W),
+ trait::window::definition::unique)::check();
+ mln_precondition(i < this->size());
+ return exact(this)->win().dp(i);
+ }
+
+ template <typename W, typename E>
+ inline
+ bool
+ weighted_window_base<W,E>::has(const mln_dpsite(W)& dp) const
+ {
+ mlc_equal(mln_trait_window_support(W),
+ trait::window::support::regular)::check();
+ mlc_equal(mln_trait_window_definition(W),
+ trait::window::definition::unique)::check();
+ return exact(this)->win().has(dp);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::internal
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CORE_INTERNAL_WEIGHTED_WINDOW_BASE_HH
Index: mln/core/internal/window_base.hh
--- mln/core/internal/window_base.hh (revision 2767)
+++ mln/core/internal/window_base.hh (working copy)
@@ -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
Index: mln/make/w_window2d.hh
--- mln/make/w_window2d.hh (revision 2767)
+++ mln/make/w_window2d.hh (working copy)
@@ -36,6 +36,7 @@
# include <mln/core/w_window.hh>
# include <mln/core/alias/dpoint2d.hh>
+# include <mln/convert/from_to.hxx>
namespace mln
Index: mln/convert/to_image.hh
--- mln/convert/to_image.hh (revision 2767)
+++ mln/convert/to_image.hh (working copy)
@@ -40,12 +40,13 @@
# include <mln/core/concept/weighted_window.hh>
# include <mln/core/concept/neighborhood.hh>
-# include <mln/literal/zero.hh>
# include <mln/geom/bbox.hh>
# include <mln/level/fill.hh>
# include <mln/histo/data.hh>
-
+# include <mln/core/image/image1d.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/image3d.hh>
namespace mln
@@ -68,7 +69,7 @@
/// Convert a weighted window \p w_win into an image.
template <typename W>
- mln_image_from_grid(mln_site(W)::grid, bool)
+ mln_image_from_grid(mln_site(W)::grid, mln_weight(W))
to_image(const Weighted_Window<W>& w_win);
/// Convert a neighborhood \p nbh into a binary image.
@@ -114,12 +115,12 @@
template <typename W>
inline
- mln_image_from_grid(mln_site(W)::grid, bool)
+ mln_image_from_grid(mln_site(W)::grid, mln_weight(W))
to_image(const Weighted_Window<W>& w_win)
{
mln_is_simple_window(W)::check();
// mln_precondition(exact(w_win).is_valid());
- mln_image_from_grid(mln_site(W)::grid, bool) tmp;
+ mln_image_from_grid(mln_site(W)::grid, mln_weight(W)) tmp;
convert::from_to(exact(w_win), tmp);
return tmp;
}
1
0
https://svn.lrde.epita.fr/svn/oln/branches/cleanup-2008
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Remove a std::size_t.
In my opinion nelements must not return size_t.
* milena/mln/core/site_set/p_image.hh,
* milena/mln/core/image/image3d.hh: Here.
image/image3d.hh | 4 ++--
site_set/p_image.hh | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
Index: milena/mln/core/site_set/p_image.hh
--- milena/mln/core/site_set/p_image.hh (revision 2766)
+++ milena/mln/core/site_set/p_image.hh (working copy)
@@ -115,7 +115,7 @@
bool is_valid() const;
/// Give the number of sites.
- std::size_t nsites() const;
+ unsigned nsites() const;
/// Insertion element associated type.
@@ -149,7 +149,7 @@
private:
I ima_;
- std::size_t nsites_;
+ unsigned nsites_;
};
@@ -198,7 +198,7 @@
template <typename I>
inline
- std::size_t
+ unsigned
p_image<I>::nsites() const
{
return nsites_;
Index: milena/mln/core/image/image3d.hh
--- milena/mln/core/image/image3d.hh (revision 2766)
+++ milena/mln/core/image/image3d.hh (working copy)
@@ -184,7 +184,7 @@
unsigned border() const;
/// Give the number of cells (points including border ones).
- std::size_t nelements() const;
+ unsigned nelements() const;
/// Read-only access to the image value located at point \p p.
const T& operator()(const point3d& p) const;
@@ -426,7 +426,7 @@
template <typename T>
inline
- std::size_t
+ unsigned
image3d<T>::nelements() const
{
mln_precondition(this->has_data());
1
0