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
February 2009
- 12 participants
- 266 discussions
3333: Fix missing specialization for bkd_pixter in image1d and image3d.
by Thierry Geraud 10 Feb '09
by Thierry Geraud 10 Feb '09
10 Feb '09
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Fix missing specialization for bkd_pixter in image1d and image3d.
* mln/core/image/image1d.hh
(bkd_pixter): Fix missing specialization.
* mln/core/image/image3d.hh
(bkd_pixter): Fix missing specialization.
* mln/morpho/attribute/card.hh: Fix missing using.
* mln/canvas/morpho/algebraic_filter.hh: Layout.
* tests/morpho/closing_algebraic.cc: Remove dead code.
mln/core/image/image1d.hh | 10 ++++++++--
mln/core/image/image3d.hh | 10 ++++++++--
mln/morpho/attribute/card.hh | 9 ++++++---
tests/morpho/closing_algebraic.cc | 2 +-
4 files changed, 23 insertions(+), 8 deletions(-)
Index: mln/core/image/image1d.hh
--- mln/core/image/image1d.hh (revision 3332)
+++ mln/core/image/image1d.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -543,6 +543,12 @@
template <typename T>
struct bkd_pixter< image1d<T> >
{
+ typedef bkd_pixter1d< image1d<T> > ret;
+ };
+
+ template <typename T>
+ struct bkd_pixter< const image1d<T> >
+ {
typedef bkd_pixter1d< const image1d<T> > ret;
};
Index: mln/core/image/image3d.hh
--- mln/core/image/image3d.hh (revision 3332)
+++ mln/core/image/image3d.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -623,6 +623,12 @@
template <typename T>
struct bkd_pixter< image3d<T> >
{
+ typedef bkd_pixter3d< image3d<T> > ret;
+ };
+
+ template <typename T>
+ struct bkd_pixter< const image3d<T> >
+ {
typedef bkd_pixter3d< const image3d<T> > ret;
};
Index: mln/morpho/attribute/card.hh
--- mln/morpho/attribute/card.hh (revision 3332)
+++ mln/morpho/attribute/card.hh (working copy)
@@ -44,7 +44,7 @@
namespace morpho {
namespace attribute {
- template <typename I> struct card;
+ template <typename I> class card;
}
}
@@ -61,7 +61,6 @@
typedef accumulator::has_set_value::no has_set_value;
typedef accumulator::has_stop::no has_stop;
typedef accumulator::when_pix::use_none when_pix;
-
};
} // end of namespace mln::trait
@@ -76,8 +75,11 @@
/// Cardinality accumulator class.
template <typename I>
- struct card : public mln::accu::internal::base< unsigned, card<I> >
+ class card : public mln::accu::internal::base< unsigned, card<I> >
{
+ typedef mln::accu::internal::base< unsigned, card<I> > super_;
+ public:
+
typedef mln_psite(I) argument;
card();
@@ -93,6 +95,7 @@
void take();
void take_as_init();
+ using super_::take_as_init;
/// \}
/// Get the value of the accumulator.
Index: mln/canvas/morpho/algebraic_filter.hh
Index: tests/morpho/closing_algebraic.cc
--- tests/morpho/closing_algebraic.cc (revision 3332)
+++ tests/morpho/closing_algebraic.cc (working copy)
@@ -53,7 +53,7 @@
typedef image2d<int_u8> I;
I lena;
- io::pgm::load(lena, MLN_IMG_DIR "/tiny.pgm");//lena.pgm");
+ io::pgm::load(lena, MLN_IMG_DIR "/tiny.pgm");
{
accu::count<point2d> a;
io::pgm::save(morpho::closing_algebraic(lena, c4(), a, 10),
1
0
10 Feb '09
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Fetch card and algebraic_union_find.hh from Edwin's sandbox.
* mln/trait/accumulator/props.hh (use_none): New.
* mln/trait/accumulators.hh
(mln_trait_accumulator_has_setvalue): Rename as...
(mln_trait_accumulator_has_set_value): ...this.
* mln/morpho/attribute: New directory.
* mln/morpho/attribute/all.hh: New.
* sandbox/edwin/card.hh: Copy to...
* mln/morpho/attribute/card.hh: ...this new file.
Update.
* mln/morpho/all.hh: Update.
* sandbox/edwin/algebraic_union_find.hh: Copy to...
* mln/canvas/morpho/algebraic_filter.hh: ...this new file.
(algebraic_union_find): Rename as...
(algebraic_filter): ...this.
Fix.
* mln/morpho/closing_algebraic.hh: New.
* mln/canvas/morpho/all.hh: Update.
* tests/morpho/attribute: New directory.
* tests/morpho/attribute/Makefile.am: New.
* tests/morpho/attribute/card.cc: New.
* tests/morpho/Makefile.am: Update.
* tests/morpho/closing_algebraic.cc: New.
mln/canvas/morpho/algebraic_filter.hh | 174 ++++++++++++------------
mln/canvas/morpho/all.hh | 5
mln/morpho/all.hh | 5
mln/morpho/attribute/all.hh | 51 +++++++
mln/morpho/attribute/card.hh | 146 +++++++++++++++-----
mln/morpho/closing_algebraic.hh | 240 ++--------------------------------
mln/trait/accumulator/props.hh | 1
mln/trait/accumulators.hh | 2
tests/morpho/Makefile.am | 3
tests/morpho/attribute/Makefile.am | 10 +
tests/morpho/attribute/card.cc | 50 +++++++
tests/morpho/closing_algebraic.cc | 29 ++--
12 files changed, 360 insertions(+), 356 deletions(-)
Index: mln/trait/accumulator/props.hh
--- mln/trait/accumulator/props.hh (revision 3331)
+++ mln/trait/accumulator/props.hh (working copy)
@@ -74,6 +74,7 @@
struct use_v : any { std::string name() const { return "when_pix::use_v"; } };
struct use_p : any { std::string name() const { return "when_pix::use_p"; } };
struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
+ struct use_none : any { std::string name() const { return "when_pix::use_none"; } };
struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
};
Index: mln/trait/accumulators.hh
--- mln/trait/accumulators.hh (revision 3331)
+++ mln/trait/accumulators.hh (working copy)
@@ -40,7 +40,7 @@
# define mln_trait_accumulator_has_untake(A) typename mln::trait::accumulator_< A >::has_untake
/// Shortcut to the accumulator property about setvalue method disponibility
-# define mln_trait_accumulator_has_setvalue(A) typename mln::trait::accumulator_< A >::has_setvalue
+# define mln_trait_accumulator_has_set_value(A) typename mln::trait::accumulator_< A >::has_set_value
/// Shortcut to the accumulator property about stop method disponibility
# define mln_trait_accumulator_has_stop(A) typename mln::trait::accumulator_< A >::has_stop
Index: mln/morpho/attribute/all.hh
--- mln/morpho/attribute/all.hh (revision 0)
+++ mln/morpho/attribute/all.hh (revision 0)
@@ -0,0 +1,51 @@
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_ATTRIBUTE_ALL_HH
+# define MLN_MORPHO_ATTRIBUTE_ALL_HH
+
+/// \file mln/morpho/attribute/all.hh
+///
+/// File that includes all attributes used in mathematical morphology.
+
+
+namespace mln
+{
+ namespace morpho
+ {
+
+ /// Namespace of attributes used in mathematical morphology.
+ namespace attribute {}
+
+ }
+}
+
+
+# include <mln/morpho/attribute/card.hh>
+
+
+#endif // ! MLN_MORPHO_ATTRIBUTE_ALL_HH
Index: mln/morpho/attribute/card.hh
--- mln/morpho/attribute/card.hh (revision 0)
+++ mln/morpho/attribute/card.hh (working copy)
@@ -1,44 +1,121 @@
-#ifndef CARD_HH_
-# define CARD_HH_
+// Copyright (C) 2009 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MORPHO_ATTRIBUTE_CARD_HH
+# define MLN_MORPHO_ATTRIBUTE_CARD_HH
+
+/// \file mln/morpho/attribute/card.hh
+///
+/// Define an accumulator that computes the cardinality of a
+/// component.
+
+# include <mln/accu/internal/base.hh>
-# include <mln/accu/all.hh>
-# include <mln/util/pix.hh>
namespace mln
{
+
+
+ // Forward declaration.
+
+ namespace morpho {
+ namespace attribute {
+ template <typename I> struct card;
+ }
+ }
+
+
+ // Traits.
+
+ namespace trait
+ {
+
+ template <typename I>
+ struct accumulator_< morpho::attribute::card<I> >
+ {
+ typedef accumulator::has_untake::no has_untake;
+ typedef accumulator::has_set_value::no has_set_value;
+ typedef accumulator::has_stop::no has_stop;
+ typedef accumulator::when_pix::use_none when_pix;
+
+ };
+
+ } // end of namespace mln::trait
+
+
namespace morpho
{
- namespace accu
+
+ namespace attribute
{
+
+ /// Cardinality accumulator class.
+
template <typename I>
struct card : public mln::accu::internal::base< unsigned, card<I> >
{
typedef mln_psite(I) argument;
card ();
+
+ /// Manipulators.
+ /// \{
void init ();
- void take (const card<I>& accu);
+ void take(const argument& s);
+ void take(const card<I>& other);
+
+ void take(const util::pix<I>& px);
void take ();
- void take (const mln_psite(I)& elt);
- void take (const mln_value(I)& elt);
- void take (const util::pix<I>& pix);
+ void take_as_init();
+ /// \}
+ /// Get the value of the accumulator.
unsigned to_result() const;
+ /// Check whether this accu is able to return a result.
+ /// Always true here.
bool is_valid () const;
- private:
+ protected:
+ /// The value.
unsigned c_;
};
+
+
# ifndef MLN_INCLUDE_ONLY
+
template <typename I>
inline
- card<I>::card () :
- c_ (0)
+ card<I>::card()
{
+ init();
}
template <typename I>
@@ -52,45 +129,43 @@
template <typename I>
inline
void
- card<I>::take (const card<I>& accu)
+ card<I>::take(const argument&)
{
- c_ += accu.c_;
+ take();
}
-
template <typename I>
inline
void
- card<I>::take ()
+ card<I>::take(const card<I>& other)
{
- ++c_;
- };
+ c_ += other.c_;
+ }
template <typename I>
inline
void
- card<I>::take (const mln_psite(I)& elt)
+ card<I>::take(const util::pix<I>&)
{
- ++c_;
- };
-
+ take();
+ }
template <typename I>
inline
void
- card<I>::take (const mln_value(I)& elt)
+ card<I>::take()
{
++c_;
- };
-
+ }
template <typename I>
inline
void
- card<I>::take (const util::pix<I>& pix)
+ card<I>::take_as_init()
{
- ++c_;
- };
+ init();
+ take();
+ }
template <typename I>
inline
@@ -98,7 +173,7 @@
card<I>::to_result() const
{
return c_;
- };
+ }
template <typename I>
inline
@@ -106,14 +181,15 @@
card<I>::is_valid () const
{
return true;
- };
-# endif
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+ } // end of namespace mln::morpho::attribute
- } // mln::morpho::accu
- } // mln::morpho
-} // mln
+ } // end of namespace mln::morpho
-#endif /* !CARD_HH_ */
+} // end of namespace mln
+#endif // ! MLN_MORPHO_ATTRIBUTE_CARD_HH
Property changes on: mln/morpho/attribute/card.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/morpho/all.hh
--- mln/morpho/all.hh (revision 3331)
+++ mln/morpho/all.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -84,6 +84,7 @@
// Sub-directories.
+# include <mln/morpho/attribute/all.hh>
# include <mln/morpho/elementary/all.hh>
# include <mln/morpho/tree/all.hh>
# include <mln/morpho/watershed/all.hh>
Index: mln/morpho/closing_algebraic.hh
--- mln/morpho/closing_algebraic.hh (revision 3330)
+++ mln/morpho/closing_algebraic.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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,25 +26,15 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_MORPHO_CLOSING_ATTRIBUTE_HH
-# define MLN_MORPHO_CLOSING_ATTRIBUTE_HH
+#ifndef MLN_MORPHO_CLOSING_ALGEBRAIC_HH
+# define MLN_MORPHO_CLOSING_ALGEBRAIC_HH
-/// \file mln/morpho/closing_attribute.hh
+/// \file mln/morpho/closing_algebraic.hh
///
-/// Morphological attribute closing.
-///
-/// \todo How to pass dynamic data (e.g., k of accu::rank) to the routine?
-///
-/// \todo Add extension::adjust_fill.
-///
-/// \todo Re-activate the fastest version when accumulators are
-/// cleaned-up.
+/// Morphological algebraic closing.
# include <mln/morpho/includes.hh>
-# include <mln/canvas/morpho/algebraic_union_find.hh>
-# include <mln/level/sort_psites.hh>
-# include <mln/level/sort_offsets.hh>
-# include <mln/util/pix.hh>
+# include <mln/canvas/morpho/algebraic_filter.hh>
namespace mln
@@ -53,227 +43,39 @@
namespace morpho
{
- /// Morphological attribute closing.
- template <typename A, typename I, typename N>
- mln_concrete(I)
- closing_attribute(const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda);
-
-
-
-# ifndef MLN_INCLUDE_ONLY
-
-
- // Implementations.
-
- namespace impl
- {
-
-
- // Generic version.
-
- namespace generic
- {
-
- template <typename I, typename A_>
- struct closing_attribute_functor_t
- {
- // requirements from mln::canvas::morpho::algebraic_union_find
-
- typedef A_ A;
- typedef mln_psite(I) P;
- typedef p_array<P> S;
-
- mln_result(A) lambda;
- const S s;
-
- void init()
- {
- // FIXME: border::fill(input, mln_max(mln_value(I)));
- }
-
- bool is_active(const A& attr) const
- {
- return attr.to_result() < lambda;
- }
-
- void inactivate(A& attr)
- {
- attr.set_value(lambda);
- }
-
- // end of requirements
-
- closing_attribute_functor_t(const Image<I>& input, mln_result(A) lambda)
- : lambda(lambda),
- s(level::sort_psites_increasing(exact(input)))
- {
- }
-
- };
-
-
- template <typename A, typename I, typename N>
- inline
+ /// Morphological algebraic closing.
+ template <typename I, typename N, typename A>
mln_concrete(I)
- closing_attribute(const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
- {
- trace::entering("morpho::impl::generic::closing_attribute");
+ closing_algebraic(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu, const mln_result(A)& lambda);
- mln_precondition(exact(input).is_valid());
- typedef closing_attribute_functor_t<I, A> F;
- F f(input, lambda);
- mln_concrete(I) output = canvas::morpho::impl::generic::algebraic_union_find(input, nbh, f);
-
- mln_postcondition(output >= input);
-
- trace::exiting("morpho::impl::generic::closing_attribute");
- return output;
- }
-
-
- } // end of namespace mln::morpho::impl::generic
-
-
-
- // "Fastest" version.
-
-
- template <typename I, typename A_>
- struct closing_attribute_fastest_functor_t
- {
- // requirements from mln::canvas::morpho::algebraic_union_find
-
- typedef A_ A;
- typedef mln_psite(I) P;
- typedef util::array<unsigned> S;
-
- mln_result(A) lambda;
- const S s;
-
- void init()
- {
- // FIXME: border::fill(input, mln_max(mln_value(I)));
- }
-
- bool is_active(const A& attr) const
- {
- return attr.to_result() < lambda;
- }
-
- void inactivate(A& attr)
- {
- attr.set_value(lambda);
- }
-
- // end of requirements
-
- closing_attribute_fastest_functor_t(const Image<I>& input, mln_result(A) lambda)
- : lambda(lambda),
- s(level::sort_offsets_increasing(exact(input)))
- {
- }
-
- };
-
-
- template <typename A, typename I, typename N>
- inline
- mln_concrete(I)
- closing_attribute_fastest(const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
- {
- trace::entering("morpho::impl::closing_attribute_fastest");
-
- mln_precondition(exact(input).is_valid());
-
- typedef impl::closing_attribute_fastest_functor_t<I, A> F;
- F f(input, lambda);
- mln_concrete(I) output = canvas::morpho::impl::algebraic_union_find_fastest(input, nbh, f);
-
- mln_postcondition(output >= input);
-
- trace::exiting("morpho::impl::closing_attribute_fastest");
- return output;
- }
-
-
- } // end of namespace mln::morpho::impl
-
-
-
- // Dispatch.
-
- namespace internal
- {
-
- template <typename A, typename I, typename N>
- inline
- mln_concrete(I)
- closing_attribute_dispatch(metal::false_,
- const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
- {
- return impl::generic::closing_attribute<A>(input, nbh, lambda);
- }
-
- template <typename A, typename I, typename N>
- inline
- mln_concrete(I)
- closing_attribute_dispatch(metal::true_,
- const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
- {
- return impl::generic::closing_attribute<A>(input, nbh, lambda);
-// return impl::closing_attribute_fastest<A>(input, nbh, lambda);
- }
-
- template <typename A, typename I, typename N>
- inline
- mln_concrete(I)
- closing_attribute_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
- {
- enum {
- test = mlc_equal(mln_trait_image_speed(I),
- trait::image::speed::fastest)::value
- &&
- mln_is_simple_neighborhood(N)::value
- };
- return closing_attribute_dispatch<A>(metal::bool_<test>(),
- input, nbh, lambda);
- }
-
- } // end of namespace internal
+# ifndef MLN_INCLUDE_ONLY
- // Facade.
- template <typename A, typename I, typename N>
+ template <typename I, typename N, typename A>
inline
mln_concrete(I)
- closing_attribute(const Image<I>& input, const Neighborhood<N>& nbh,
- mln_result(A) lambda)
+ closing_algebraic(const Image<I>& input, const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu, const mln_result(A)& lambda)
{
- trace::entering("morpho::closing_attribute");
+ trace::entering("morpho::closing_algebraic");
mln_precondition(exact(input).is_valid());
- mln_concrete(I) output = internal::closing_attribute_dispatch<A>(input, nbh, lambda);
+ mln_concrete(I) output;
+ output = canvas::morpho::algebraic_filter(input, nbh, accu, lambda,
+ /* increasing = */ true);
mln_postcondition(output >= input);
- trace::exiting("morpho::closing_attribute");
+ trace::exiting("morpho::closing_algebraic");
return output;
}
- // Facade.
-
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::morpho
@@ -281,4 +83,4 @@
} // end of namespace mln
-#endif // ! MLN_MORPHO_CLOSING_ATTRIBUTE_HH
+#endif // ! MLN_MORPHO_CLOSING_ALGEBRAIC_HH
Property changes on: mln/morpho/closing_algebraic.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/canvas/morpho/all.hh
--- mln/canvas/morpho/all.hh (revision 3331)
+++ mln/canvas/morpho/all.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -46,6 +46,7 @@
}
+# include <mln/canvas/morpho/algebraic_filter.hh>
# include <mln/canvas/morpho/algebraic_union_find.hh>
Index: mln/canvas/morpho/algebraic_filter.hh
--- mln/canvas/morpho/algebraic_filter.hh (revision 3330)
+++ mln/canvas/morpho/algebraic_filter.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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,27 +26,24 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-#ifndef MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
-# define MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
+#ifndef MLN_CANVAS_MORPHO_ALGEBRAIC_FILTER_HH
+# define MLN_CANVAS_MORPHO_ALGEBRAIC_FILTER_HH
+/// \file mln/canvas/morpho/algebraic_filter.hh
///
-///
-/// \todo: Doc!
-///
-/// \todo Re-activate the fastest version when accumulators are
-/// cleaned-up.
+/// Canvas for morphological algebraic filters.
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
# include <mln/core/concept/accumulator.hh>
-# include <mln/data/fill.hh>
-# include <mln/util/pix.hh>
+# include <mln/data/fill.hh>
+# include <mln/extension/adjust_fill.hh>
# include <mln/level/sort_psites.hh>
# include <mln/level/sort_offsets.hh>
-# include "accu_trait.hh"
+
namespace mln
{
@@ -57,6 +54,23 @@
namespace morpho
{
+
+ template <typename I, typename N, typename A>
+ mln_concrete(I)
+ algebraic_filter(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ const mln_result(A)& lambda,
+ bool increasing);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+ // Implementations.
+
+
namespace impl
{
@@ -79,18 +93,19 @@
template <typename I, typename N, typename S, typename A>
inline
mln_concrete(I)
- algebraic_union_find(const Image<I>& input_,
+ algebraic_filter(const Image<I>& input_,
const Neighborhood<N>& nbh_,
- const Site_Set<S>& s_,
const Accumulator<A>& accu_,
- mln_result(A) lambda)
+ const mln_result(A)& lambda,
+ const Site_Set<S>& s_)
{
- trace::entering("canvas::morpho::impl::generic::algebraic_union_find");
+ trace::entering("canvas::morpho::impl::generic::algebraic_filter");
// FIXME: Tests?
const I& input = exact(input_);
const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
mln_concrete(I) output;
initialize(output, input);
@@ -117,42 +132,18 @@
// First pass.
{
- mln_fwd_piter(S) p(s_);
+ mln_fwd_piter(S) p(s);
mln_niter(N) n(nbh, p);
for_all(p)
{
- // Make set.
- {
+ // Make-Set.
parent(p) = p;
- /* FIXME: What if the value_type of DATA (i.e., A) were not
- based on a accu::count<mln::pix>? Currently, nothing
- enforces this, but the code below expects this line to be
- valid:
-
- data(p).take_as_init(make::pix(f.input, p))
-
- which probably restricts the kind of input images.
-
- If we want to be more generic, the initialization should
- read something like:
-
- init_data(p);
-
- i.e., the functor for the initialization of data should
- be passed as an argument to the canvas' ctor.
-
- Of course, we might want to restrict attributes to the
- accumulator accu::count<mln::pix> (which is perfectly
- acceptable), but then this class should statically check
- the conformance of the template parameter A to this
- constraint. */
- data(p).take_as_init(p); // FIXME: algebraic so p!
- }
+ data(p).take_as_init(p);
for_all(n)
if (input.domain().has(n) && deja_vu(n))
{
- //do_union(n, p);
+ // Do-Union.
P r = find_root(parent, n);
if (r != p)
{
@@ -177,18 +168,16 @@
activity(p) = false;
}
else
- {
activity(p) = false;
}
}
- }
deja_vu(p) = true;
}
}
// Second pass.
{
- mln_bkd_piter(S) p(s_);
+ mln_bkd_piter(S) p(s);
for_all(p)
if (parent(p) == p) // p is root.
output(p) = input(p);
@@ -202,7 +191,7 @@
and add in init:
mln::data::fill(output, input);
*/
- trace::exiting("canvas::morpho::impl::generic::algebraic_union_find");
+ trace::exiting("canvas::morpho::impl::generic::algebraic_filter");
return output;
}
@@ -213,34 +202,36 @@
// Fastest version.
+
template <typename I>
inline
unsigned
find_root_fastest(I& parent, unsigned x)
{
- if (parent.element(x) == x)
+ if (parent.element(x) == 0)
return x;
else
return parent.element(x) = find_root_fastest(parent, parent.element(x));
}
-
- template <typename I, typename N, typename S, typename A>
+ template <typename I, typename N, typename A>
inline
mln_concrete(I)
- algebraic_union_find_fastest(const Image<I>& input_,
+ algebraic_filter_fastest(const Image<I>& input_,
const Neighborhood<N>& nbh_,
- const Site_Set<S>& s_,
const Accumulator<A>& accu_,
- mln_result(A) lambda)
+ const mln_result(A)& lambda,
+ const util::array<unsigned>& s)
{
- trace::entering("canvas::morpho::impl::algebraic_union_find_fastest");
+ trace::entering("canvas::morpho::impl::algebraic_filter_fastest");
// FIXME: Tests?
const I& input = exact(input_);
const N& nbh = exact(nbh_);
+ extension::adjust(input, nbh);
+
mln_concrete(I) output;
initialize(output, input);
@@ -257,6 +248,7 @@
{
initialize(deja_vu, input);
mln::data::fill(deja_vu, false);
+ extension::fill(deja_vu, false); // So that the extension is ignored.
initialize(activity, input);
mln::data::fill(activity, true);
initialize(parent, input);
@@ -267,18 +259,17 @@
util::array<int> dp = offsets_wrt(input, nbh);
const unsigned n_nbhs = dp.nelements();
- const unsigned n_points = s_.nelements();
+ const unsigned n = s.nelements();
// First pass.
{
- for (unsigned i = 0; i < n_points; ++i)
+ for (unsigned i = 0; i < n; ++i)
{
- unsigned p = s_[i]; // An offset.
+ unsigned p = s[i]; // An offset.
// Make set.
- parent.element(p) = p;
- data.element(p).take_as_init(); // FIXME: Very bad et SEULEMENT POUR CARD !!! C CON!!!
+ data.element(p).take_as_init(); // FIXME: Very bad!
for (unsigned j = 0; j < n_nbhs; ++j)
{
@@ -290,20 +281,17 @@
if (r != p)
{
if (input.element(r) == input.element(p)
- || (activity.element(r)
- && data.element(r) < lambda))
+ || (activity.element(r) && data.element(r) < lambda))
{
- data.element(p).take();
+ data.element(p).take(data.element(r));
parent.element(r) = p;
if (activity.element(r) == false)
activity.element(p) = false;
}
else
- {
activity.element(p) = false;
}
}
- }
deja_vu.element(p) = true;
}
@@ -312,16 +300,16 @@
// Second pass.
{
- for (int i = n_points - 1; i >= 0 ; --i)
+ for (int i = n - 1; i >= 0 ; --i)
{
- unsigned p = s_[i];
- if (parent.element(p) == p) // p is root.
+ unsigned p = s[i];
+ if (parent.element(p) == 0) // p is root.
output.element(p) = input.element(p);
else
output.element(p) = output.element(parent.element(p));
}
}
- trace::exiting("canvas::morpho::impl::algebraic_union_find_fastest");
+ trace::exiting("canvas::morpho::impl::algebraic_filter_fastest");
return output;
}
@@ -332,59 +320,64 @@
// Dispatch.
+
namespace internal
{
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- algebraic_union_find_dispatch(metal::false_,
+ algebraic_filter_dispatch(metal::false_,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& accu,
- mln_result(A) lambda,
+ const mln_result(A)& lambda,
bool increasing)
{
p_array<mln_psite(I)> s = increasing ?
level::sort_psites_increasing(input) :
level::sort_psites_decreasing(input);
- return impl::generic::algebraic_union_find(input, nbh, s, accu,
- lambda);
+ return impl::generic::algebraic_filter(input, nbh, accu, lambda,
+ s);
}
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- algebraic_union_find_dispatch(metal::true_,
+ algebraic_filter_dispatch(metal::true_,
const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& accu,
- mln_result(A) lambda,
+ const mln_result(A)& lambda,
bool increasing)
{
util::array<unsigned> s = increasing ?
level::sort_offsets_increasing(input) :
level::sort_offsets_decreasing(input);
- return impl::algebraic_union_find_fastest(input, nbh, s, accu, lambda);
+ return impl::algebraic_filter_fastest(input, nbh, accu, lambda,
+ s);
}
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- algebraic_union_find_dispatch(const Image<I>& input,
+ algebraic_filter_dispatch(const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& accu,
- mln_result(A) lambda,
+ const mln_result(A)& lambda,
bool increasing)
{
enum {
test = (mlc_equal(mln_trait_image_speed(I),
- trait::image::speed::fastest)::value &&
- mln_is_simple_neighborhood(N)::value &&
- mlc_equal(mln_trait_accu_when_pix(A),
- trait::accu::when_pix::use_whatever)::value)
+ trait::image::speed::fastest)::value
+ &&
+ mln_is_simple_neighborhood(N)::value
+ &&
+ mlc_equal(mln_trait_accumulator_when_pix(A),
+ trait::accumulator::when_pix::use_none)::value)
};
- return algebraic_union_find_dispatch(metal::bool_<test>(), input, nbh,
- accu, lambda, increasing);
+ return algebraic_filter_dispatch(metal::bool_<test>(),
+ input, nbh, accu, lambda,
+ increasing);
}
} // end of namespace mln::canvas::morpho::internal
@@ -393,20 +386,23 @@
// Facade.
+
template <typename I, typename N, typename A>
inline
mln_concrete(I)
- algebraic_union_find(const Image<I>& input,
+ algebraic_filter(const Image<I>& input,
const Neighborhood<N>& nbh,
const Accumulator<A>& accu,
- mln_result(A) lambda,
+ const mln_result(A)& lambda,
bool increasing)
{
- return internal::algebraic_union_find_dispatch(input, nbh, accu,
- lambda, increasing);
+ return internal::algebraic_filter_dispatch(input, nbh, accu, lambda,
+ increasing);
}
+# endif // ! MLN_INCLUDE_ONLY
+
} // end of namespace mln::canvas::morpho
} // end of namespace mln::canvas
@@ -414,4 +410,4 @@
} // end of namespace mln
-#endif // ! MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
+#endif // ! MLN_CANVAS_MORPHO_ALGEBRAIC_FILTER_HH
Property changes on: mln/canvas/morpho/algebraic_filter.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: tests/morpho/attribute/Makefile.am
--- tests/morpho/attribute/Makefile.am (revision 0)
+++ tests/morpho/attribute/Makefile.am (revision 0)
@@ -0,0 +1,10 @@
+## Process this file through Automake to create Makefile.in -*- Makefile -*-
+
+include $(top_srcdir)/milena/tests/tests.mk
+
+check_PROGRAMS = \
+ card
+
+card_SOURCES = card.cc
+
+TESTS = $(check_PROGRAMS)
Index: tests/morpho/attribute/card.cc
--- tests/morpho/attribute/card.cc (revision 0)
+++ tests/morpho/attribute/card.cc (revision 0)
@@ -0,0 +1,50 @@
+// Copyright (C) 2009 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/attribute/card.cc
+///
+/// Test on mln::morpho::attribute::card.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/morpho/attribute/card.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ typedef image2d<int> I;
+ I ima(3, 3);
+ point2d p(0, 0);
+ util::pix<I> px(ima, p);
+
+ morpho::attribute::card<I> c;
+ c.take();
+ c.take(p);
+ c.take(px);
+ mln_assertion(c == 3);
+}
Index: tests/morpho/Makefile.am
--- tests/morpho/Makefile.am (revision 3331)
+++ tests/morpho/Makefile.am (working copy)
@@ -3,12 +3,14 @@
include $(top_srcdir)/milena/tests/tests.mk
SUBDIRS = \
+ attribute \
elementary \
tree \
watershed
check_PROGRAMS = \
artificial_line_graph_image_wst \
+ closing_algebraic \
closing_area \
closing_height \
closing_volume \
@@ -45,6 +47,7 @@
erosion_SOURCES = erosion.cc
opening_area_SOURCES = opening_area.cc
+closing_algebraic_SOURCES = closing_algebraic.cc
closing_area_SOURCES = closing_area.cc
closing_height_SOURCES = closing_height.cc
opening_height_SOURCES = opening_height.cc
Index: tests/morpho/closing_algebraic.cc
--- tests/morpho/closing_algebraic.cc (revision 3330)
+++ tests/morpho/closing_algebraic.cc (working copy)
@@ -1,5 +1,4 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2009 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,9 +25,9 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/// \file tests/morpho/closing_area.cc
+/// \file tests/morpho/closing_algebraic.cc
///
-/// Test on mln::morpho::closing_area.
+/// Test on mln::morpho::closing_algebraic.
#include <mln/core/image/image2d.hh>
#include <mln/value/int_u8.hh>
@@ -37,7 +36,9 @@
#include <mln/io/pgm/load.hh>
#include <mln/io/pgm/save.hh>
-#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/closing_algebraic.hh>
+#include <mln/morpho/attribute/card.hh>
+#include <mln/accu/count.hh>
#include "tests/data.hh"
@@ -48,7 +49,19 @@
using namespace mln;
using value::int_u8;
- image2d<int_u8> lena;
- io::pgm::load(lena, MLN_IMG_DIR "/lena.pgm");
- io::pgm::save(morpho::closing_area(lena, c4(), 510), "out.pgm");
+ trace::quiet = false;
+
+ typedef image2d<int_u8> I;
+ I lena;
+ io::pgm::load(lena, MLN_IMG_DIR "/tiny.pgm");//lena.pgm");
+ {
+ accu::count<point2d> a;
+ io::pgm::save(morpho::closing_algebraic(lena, c4(), a, 10),
+ "ref.pgm");
+ }
+ {
+ morpho::attribute::card<I> a;
+ io::pgm::save(morpho::closing_algebraic(lena, c4(), a, 10),
+ "out.pgm");
+ }
}
Property changes on: tests/morpho/closing_algebraic.cc
___________________________________________________________________
Added: svn:mergeinfo
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Fetch accumulator properties from Fred's sandbox.
* mln/trait/accumulator: New directory.
* sandbox/fred/accuprops.cc: Copy to...
* mln/trait/accumulator/props.hh,
* mln/trait/accumulators.hh: ...these new files.
Rename entities to enforce consistency.
Remove leveling related code.
* mln/trait/accumulator/print.hh: New.
* mln/core/concept/accumulator.hh: Include props.
* tests/accu/max.cc: Upgrade file doc style.
mln/core/concept/accumulator.hh | 5
mln/trait/accumulator/print.hh | 92 ++++++++++
mln/trait/accumulator/props.hh | 338 +++++----------------------------------
mln/trait/accumulators.hh | 340 +++++-----------------------------------
tests/accu/max.cc | 12 -
5 files changed, 195 insertions(+), 592 deletions(-)
Index: mln/trait/accumulator/props.hh
--- mln/trait/accumulator/props.hh (revision 0)
+++ mln/trait/accumulator/props.hh (working copy)
@@ -1,331 +1,87 @@
-# include <iostream>
-# include <string>
-
-# include <mln/trait/undef.hh>
-# include <mln/trait/image/props.hh>
-# include <mln/trait/value_.hh>
-
-# include <mln/metal/bexpr.hh>
-# include <mln/metal/equal.hh>
-# include <mln/metal/if.hh>
-# include <mln/metal/is_const.hh>
-
-# include <mln/core/concept/image.hh>
-# include <mln/accu/all.hh>
-# include <mln/util/pix.hh>
-# include <mln/make/pix.hh>
-
-/// Shortcut to the accumulator property about untake method disponibility
-# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake
-
-/// Shortcut to the accumulator property about setvalue method disponibility
-# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue
+// Copyright (C) 2009 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_TRAIT_ACCUMULATOR_PROPS_HH
+# define MLN_TRAIT_ACCUMULATOR_PROPS_HH
+
+/// \file mln/trait/accumulator/props.hh
+///
+/// Properties of accumulator classes.
-/// Shortcut to the accumulator property about stop method disponibility
-# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop
+# include <string>
-/// Shortcut to the accumulator property about behavior when pixel is given as take() value
-/// Used for instance in mln::canvas::morpho::leveling
-# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix
-namespace mln {
+namespace mln
+{
- namespace trait {
+ namespace trait
+ {
- namespace accu {
+ namespace accumulator
+ {
- // Basic accumulators properties
+ // Basic accumulators properties.
struct has_untake
{
struct any { protected: any() {}; };
-
struct no : any { std::string name() const { return "has_untake::no"; } };
-
struct yes : any { std::string name() const { return "has_untake::yes"; } };
};
struct has_stop
{
struct any { protected: any() {}; };
-
- struct no : any { std::string name() const { return "has_setvalue::no"; } };
-
+ struct no : any { std::string name() const { return "has_stop::no"; } };
struct yes : any { std::string name() const { return "has_stop::yes"; } };
};
- struct has_setvalue
+ struct has_set_value
{
struct any { protected: any() {}; };
-
- struct no : any { std::string name() const { return "has_setvalue::no"; } };
-
- struct yes : any { std::string name() const { return "has_setvalue::yes"; } };
+ struct no : any { std::string name() const { return "has_set_value::no"; } };
+ struct yes : any { std::string name() const { return "has_set_value::yes"; } };
};
// Morphological accumulators properties
struct when_pix
{
struct any { protected: any() {}; };
-
struct use_v : any { std::string name() const { return "when_pix::use_v"; } };
-
struct use_p : any { std::string name() const { return "when_pix::use_p"; } };
-
struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
-
struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
};
- } // end of namespace mln::trait::accu
-
- template <typename A>
- struct undefined_accu_
- {
- // general
- typedef undef has_untake;
- typedef undef has_stop;
- typedef undef has_setvalue;
-
- // morpho
- typedef accu::when_pix::not_ok when_pix;
- // FIXME: should default be undef ?
- };
-
- template <typename A>
- struct accu_ : undefined_accu_<A>
- {
- };
-
- } // end of namespace mln::trait
-
- namespace canvas {
-
- namespace morpho {
-
- namespace impl {
-
- namespace generic {
-
- template <typename I, template <typename P> class A>
- inline
- void
- leveling(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- const I& ima = exact(input);
- A< util::pix<I> >& a = exact(acc);
-
- mln_piter(I) p(ima.domain());
-
- for_all(p)
- a.take(mln::make::pix(ima, p));
- }
-
- } // end of namespace mln::canvas::morpho::impl::generic
-
- // fast implementation (only on values from pixter)
- template <typename I, template <typename P> class A>
- inline
- void
- leveling_fastest(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- const I& ima = exact(input);
- A< util::pix<I> >& a = exact(acc);
-
- mln_pixter(const I) px(ima);
-
- for_all(px)
- a.take(px.val());
- }
-
- } // end of namespace mln::canvas::morpho::impl
-
- namespace internal {
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(metal::false_,
- const Image<I>& input,
- Accumulator<A>& acc)
- {
- impl::generic::leveling(input, acc);
- }
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(metal::true_,
- const Image<I>& input,
- Accumulator<A>& acc)
- {
- impl::leveling_fastest(input, acc);
- }
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(const Image<I>& input,
- Accumulator<A>& acc)
- {
- enum {
- test = mlc_equal(mln_trait_image_speed(I),
- trait::image::speed::fastest)::value
- &&
- mlc_equal(mln_trait_accu_when_pix(A),
- trait::accu::when_pix::use_v)::value
- };
- internal::leveling_dispatch(metal::bool_<test>(),
- input, acc);
- }
-
- } // end of namespace mln::canvas::morpho::internal
-
- // Facade.
- template <typename I, template <typename P> class A>
- inline
- void
- leveling(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- internal::leveling_dispatch(input, acc);
- }
-
- } // end of namespace mln::canvas::morpho
-
- } // end of namespace mln::canvas
-
- namespace morpho {
-
- namespace accu {
-
- namespace internal {
-
- template <typename V>
- struct sum_handling_pixels
- { typedef mln_sum(V) ret; };
-
- template <typename I>
- struct sum_handling_pixels< util::pix<I> >
- { typedef mln_sum(mln_value(I)) ret; };
-
- } // end of namespace mln::morpho::accu::internal
-
- template <typename T>
- /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean.
- /// FIXME: is inclusion polyphormism really appliable ?
- struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>,
- public Accumulator< mean<T> >
- {
- typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super;
- typedef typename super::result result;
-
- using super::operator result;
- using super::take;
-
- void take(const mean<T>& m);
- };
-
- template <typename I>
- struct mean< util::pix<I> > : public mean< mln_value(I) >,
- public Accumulator< mean< util::pix<I> > >
- {
- typedef mean< mln_value(I) > super;
- typedef util::pix<I> argument;
- typedef typename super::result result;
-
- using super::operator result;
- using super::take;
-
- void take(const argument& t);
- void take(const mean< util::pix<I> >& m);
- };
-
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename T>
- inline
- void mean<T>::take(const mean<T>& m)
- {
- this->super::take(m);
- }
-
- template <typename I>
- inline
- void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t)
- {
- this->mean< mln_value(I) >::take(t.v());
- }
-
- template <typename I>
- inline
- void mean< util::pix<I> >::take(const mean< util::pix<I> >& m)
- {
- this->super::take(m);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::morpho::accu
-
- } // end of namespace mln::morpho
-
- namespace trait {
-
- template <typename I>
- struct accu_< morpho::accu::mean< util::pix<I> > > :
- public undefined_accu_ < morpho::accu::mean< util::pix<I> > >
- {
- typedef accu::when_pix::use_v when_pix;
- };
+ } // end of namespace mln::trait::accumulator
} // end of namespace mln::trait
} // end of namespace mln
-# include <mln/accu/all.hh>
-# include <mln/core/image/image2d.hh>
-
-# include <mln/debug/iota.hh>
-# include <mln/debug/println.hh>
-# include <mln/core/var.hh>
-# include <mln/util/timer.hh>
-int main()
-{
- typedef mln::image2d<int> I;
-
- I ima(1000, 1000);
- mln::morpho::accu::mean< mln::util::pix<I> > acc;
-
- float elapsed;
- mln::util::timer chrono;
-
- mln::debug::iota(ima);
- std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl;
-
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::leveling(ima, acc);
- elapsed = chrono.stop();
-
- std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl;
-
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::impl::generic::leveling(ima, acc);
- elapsed = chrono.stop();
-
- std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl;
-
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::impl::leveling_fastest(ima, acc);
- elapsed = chrono.stop();
- std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl;
-}
+#endif // ! MLN_TRAIT_ACCUMULATOR_PROPS_HH
Property changes on: mln/trait/accumulator/props.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/trait/accumulator/print.hh
--- mln/trait/accumulator/print.hh (revision 0)
+++ mln/trait/accumulator/print.hh (revision 0)
@@ -0,0 +1,92 @@
+// Copyright (C) 2009 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_TRAIT_ACCUMULATOR_PRINT_HH
+# define MLN_TRAIT_ACCUMULATOR_PRINT_HH
+
+/// \file mln/trait/accumulator/print.hh
+///
+/// Print the collection of traits for an accumulator type.
+
+# include <iostream>
+# include <mln/trait/accumulators.hh>
+# include <mln/metal/is_a.hh>
+
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename E> struct Accumulator;
+
+
+ namespace trait
+ {
+
+ namespace accumulator
+ {
+
+ template <typename A>
+ void print(std::ostream& ostr = std::cout);
+
+ template <typename A>
+ void print(const Accumulator<A>& ima, std::ostream& ostr = std::cout);
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename A>
+ inline
+ void print(std::ostream& ostr)
+ {
+ mlc_is_a(A, Accumulator)::check();
+ typedef mln::trait::accumulator_<A> the;
+ ostr << "{ "
+ << typename the::has_untake().name() << ", "
+ << typename the::has_stop().name() << ", "
+ << typename the::has_set_value().name() << ", "
+ << typename the::when_pix().name() << " }" << std::endl;
+ }
+
+ template <typename A>
+ inline
+ void print(const Accumulator<A>&, std::ostream& ostr)
+ {
+ print<A>(ostr);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::trait::accumulator
+
+ } // end of namespace mln::trait
+
+} // end of namespace mln
+
+
+#endif // ! MLN_TRAIT_ACCUMULATOR_PRINT_HH
Index: mln/trait/accumulators.hh
--- mln/trait/accumulators.hh (revision 3329)
+++ mln/trait/accumulators.hh (working copy)
@@ -1,331 +1,83 @@
-# include <iostream>
-# include <string>
+// Copyright (C) 2009 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_TRAIT_ACCUMULATORS_HH
+# define MLN_TRAIT_ACCUMULATORS_HH
+
+/// \file mln/trait/accumulators.hh
+///
+/// Some base trait types for accumulators.
+# include <mln/trait/accumulator/props.hh>
# include <mln/trait/undef.hh>
-# include <mln/trait/image/props.hh>
-# include <mln/trait/value_.hh>
-# include <mln/metal/bexpr.hh>
-# include <mln/metal/equal.hh>
-# include <mln/metal/if.hh>
-# include <mln/metal/is_const.hh>
-
-# include <mln/core/concept/image.hh>
-# include <mln/accu/all.hh>
-# include <mln/util/pix.hh>
-# include <mln/make/pix.hh>
/// Shortcut to the accumulator property about untake method disponibility
-# define mln_trait_accu_has_untake(A) typename mln::trait::accu_< A >::has_untake
+# define mln_trait_accumulator_has_untake(A) typename mln::trait::accumulator_< A >::has_untake
/// Shortcut to the accumulator property about setvalue method disponibility
-# define mln_trait_accu_has_setvalue(A) typename mln::trait::accu_< A >::has_setvalue
+# define mln_trait_accumulator_has_setvalue(A) typename mln::trait::accumulator_< A >::has_setvalue
/// Shortcut to the accumulator property about stop method disponibility
-# define mln_trait_accu_has_stop(A) typename mln::trait::accu_< A >::has_stop
+# define mln_trait_accumulator_has_stop(A) typename mln::trait::accumulator_< A >::has_stop
/// Shortcut to the accumulator property about behavior when pixel is given as take() value
/// Used for instance in mln::canvas::morpho::leveling
-# define mln_trait_accu_when_pix(A) typename mln::trait::accu_< A >::when_pix
+# define mln_trait_accumulator_when_pix(A) typename mln::trait::accumulator_< A >::when_pix
-namespace mln {
- namespace trait {
- namespace accu {
-
- // Basic accumulators properties
-
- struct has_untake
+namespace mln
{
- struct any { protected: any() {}; };
-
- struct no : any { std::string name() const { return "has_untake::no"; } };
- struct yes : any { std::string name() const { return "has_untake::yes"; } };
- };
-
- struct has_stop
+ namespace trait
{
- struct any { protected: any() {}; };
-
- struct no : any { std::string name() const { return "has_setvalue::no"; } };
-
- struct yes : any { std::string name() const { return "has_stop::yes"; } };
- };
-
- struct has_setvalue
- {
- struct any { protected: any() {}; };
-
- struct no : any { std::string name() const { return "has_setvalue::no"; } };
-
- struct yes : any { std::string name() const { return "has_setvalue::yes"; } };
- };
-
- // Morphological accumulators properties
- struct when_pix
- {
- struct any { protected: any() {}; };
-
- struct use_v : any { std::string name() const { return "when_pix::use_v"; } };
-
- struct use_p : any { std::string name() const { return "when_pix::use_p"; } };
-
- struct use_pix : any { std::string name() const { return "when_pix::use_pix"; } };
-
- struct not_ok : any { std::string name() const { return "when_pix::not_ok"; } };
- };
-
- } // end of namespace mln::trait::accu
template <typename A>
- struct undefined_accu_
+ struct undefined_accumulator_
{
- // general
typedef undef has_untake;
typedef undef has_stop;
- typedef undef has_setvalue;
-
- // morpho
- typedef accu::when_pix::not_ok when_pix;
- // FIXME: should default be undef ?
+ typedef undef has_set_value;
+ typedef accumulator::when_pix::not_ok when_pix;
};
template <typename A>
- struct accu_ : undefined_accu_<A>
- {
- };
-
- } // end of namespace mln::trait
-
- namespace canvas {
-
- namespace morpho {
-
- namespace impl {
-
- namespace generic {
-
- template <typename I, template <typename P> class A>
- inline
- void
- leveling(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- const I& ima = exact(input);
- A< util::pix<I> >& a = exact(acc);
-
- mln_piter(I) p(ima.domain());
-
- for_all(p)
- a.take(mln::make::pix(ima, p));
- }
-
- } // end of namespace mln::canvas::morpho::impl::generic
-
- // fast implementation (only on values from pixter)
- template <typename I, template <typename P> class A>
- inline
- void
- leveling_fastest(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- const I& ima = exact(input);
- A< util::pix<I> >& a = exact(acc);
-
- mln_pixter(const I) px(ima);
-
- for_all(px)
- a.take(px.val());
- }
-
- } // end of namespace mln::canvas::morpho::impl
-
- namespace internal {
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(metal::false_,
- const Image<I>& input,
- Accumulator<A>& acc)
- {
- impl::generic::leveling(input, acc);
- }
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(metal::true_,
- const Image<I>& input,
- Accumulator<A>& acc)
+ struct accumulator_ : undefined_accumulator_<A>
{
- impl::leveling_fastest(input, acc);
- }
-
- template <typename I, typename A>
- inline
- void
- leveling_dispatch(const Image<I>& input,
- Accumulator<A>& acc)
- {
- enum {
- test = mlc_equal(mln_trait_image_speed(I),
- trait::image::speed::fastest)::value
- &&
- mlc_equal(mln_trait_accu_when_pix(A),
- trait::accu::when_pix::use_v)::value
- };
- internal::leveling_dispatch(metal::bool_<test>(),
- input, acc);
- }
-
- } // end of namespace mln::canvas::morpho::internal
-
- // Facade.
- template <typename I, template <typename P> class A>
- inline
- void
- leveling(const Image<I>& input,
- Accumulator< A< util::pix<I> > >& acc)
- {
- internal::leveling_dispatch(input, acc);
- }
-
- } // end of namespace mln::canvas::morpho
-
- } // end of namespace mln::canvas
-
- namespace morpho {
-
- namespace accu {
-
- namespace internal {
-
- template <typename V>
- struct sum_handling_pixels
- { typedef mln_sum(V) ret; };
-
- template <typename I>
- struct sum_handling_pixels< util::pix<I> >
- { typedef mln_sum(mln_value(I)) ret; };
-
- } // end of namespace mln::morpho::accu::internal
-
- template <typename T>
- /// Morphological (i.e. for pixel and pixel values) accumulator calculating mean.
- /// FIXME: is inclusion polyphormism really appliable ?
- struct mean : public mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret>,
- public Accumulator< mean<T> >
- {
- typedef mln::accu::mean<T, typename internal::sum_handling_pixels<T>::ret> super;
- typedef typename super::result result;
-
- using super::operator result;
- using super::take;
-
- void take(const mean<T>& m);
- };
-
- template <typename I>
- struct mean< util::pix<I> > : public mean< mln_value(I) >,
- public Accumulator< mean< util::pix<I> > >
- {
- typedef mean< mln_value(I) > super;
- typedef util::pix<I> argument;
- typedef typename super::result result;
-
- using super::operator result;
- using super::take;
-
- void take(const argument& t);
- void take(const mean< util::pix<I> >& m);
};
-# ifndef MLN_INCLUDE_ONLY
-
- template <typename T>
- inline
- void mean<T>::take(const mean<T>& m)
- {
- this->super::take(m);
- }
-
- template <typename I>
- inline
- void mean< util::pix<I> >::take(const mean< util::pix<I> >::argument& t)
- {
- this->mean< mln_value(I) >::take(t.v());
- }
-
- template <typename I>
- inline
- void mean< util::pix<I> >::take(const mean< util::pix<I> >& m)
- {
- this->super::take(m);
- }
-
-# endif // ! MLN_INCLUDE_ONLY
-
- } // end of namespace mln::morpho::accu
-
- } // end of namespace mln::morpho
-
- namespace trait {
-
- template <typename I>
- struct accu_< morpho::accu::mean< util::pix<I> > > :
- public undefined_accu_ < morpho::accu::mean< util::pix<I> > >
- {
- typedef accu::when_pix::use_v when_pix;
- };
} // end of namespace mln::trait
} // end of namespace mln
-# include <mln/accu/all.hh>
-# include <mln/core/image/image2d.hh>
-
-# include <mln/debug/iota.hh>
-# include <mln/debug/println.hh>
-# include <mln/core/var.hh>
-# include <mln/util/timer.hh>
-int main()
-{
- typedef mln::image2d<int> I;
-
- I ima(1000, 1000);
- mln::morpho::accu::mean< mln::util::pix<I> > acc;
-
- float elapsed;
- mln::util::timer chrono;
-
- mln::debug::iota(ima);
- std::cout << "50 mean of a 1000x1000 image2d<int>" << std::endl;
-
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::leveling(ima, acc);
- elapsed = chrono.stop();
-
- std::cout << "(auto) " << elapsed << "s : " << acc.to_result() << std::endl;
-
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::impl::generic::leveling(ima, acc);
- elapsed = chrono.stop();
- std::cout << "(generic) " << elapsed << "s : " << acc.to_result() << std::endl;
+# include <mln/trait/accumulator/print.hh>
- acc.init();
- chrono.start();
- for (int i = 0; i < 50; i++)
- mln::canvas::morpho::impl::leveling_fastest(ima, acc);
- elapsed = chrono.stop();
- std::cout << "(fast) " << elapsed << "s : " << acc.to_result() << std::endl;
-}
+#endif // ! MLN_TRAIT_ACCUMULATORS_HH
Property changes on: mln/trait/accumulators.hh
___________________________________________________________________
Added: svn:mergeinfo
Index: mln/core/concept/accumulator.hh
--- mln/core/concept/accumulator.hh (revision 3329)
+++ mln/core/concept/accumulator.hh (working copy)
@@ -1,5 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
-// (LRDE)
+// Copyright (C) 2007, 2008, 2009 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
@@ -36,6 +36,7 @@
# include <mln/core/concept/proxy.hh>
# include <mln/metal/fix_return.hh>
# include <mln/metal/const.hh>
+# include <mln/trait/accumulators.hh>
namespace mln
Index: tests/accu/max.cc
--- tests/accu/max.cc (revision 3329)
+++ tests/accu/max.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008, 2009 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/accu/max.cc
- *
- * \brief Tests on mln::accu::max.
- */
+/// \file tests/accu/max.cc
+///
+/// Tests on mln::accu::max.
#include <mln/core/image/image2d.hh>
#include <mln/debug/iota.hh>
@@ -50,4 +50,6 @@
mln_assertion(level::compute(accu::meta::max(), ima) == 9);
accu::max<int> M;
mln_assertion(level::compute(M, ima) == 9);
+
+ // mln::trait::accumulator::print(M);
}
1
0
* mln/accu/center.hh: use a vector of type mln_sum(P::coord) instead
of P::vec. Avoid an overflow.
---
milena/ChangeLog | 7 +++++++
milena/mln/accu/center.hh | 4 ++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3d3cca5..933a495 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,10 @@
+2009-02-10 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Fix accu::center.
+
+ * mln/accu/center.hh: use a vector of type mln_sum(P::coord) instead
+ of P::vec. Avoid an overflow.
+
2009-02-09 Guillaume Lazzara <z(a)lrde.epita.fr>
Update ICP.
diff --git a/milena/mln/accu/center.hh b/milena/mln/accu/center.hh
index aba9a80..f7caff3 100644
--- a/milena/mln/accu/center.hh
+++ b/milena/mln/accu/center.hh
@@ -73,7 +73,7 @@ namespace mln
bool is_valid() const;
protected:
- V center_;
+ algebra::vec<P::dim, mln_sum(mln_coord(P))> center_;
unsigned nsites_;
};
@@ -87,7 +87,7 @@ namespace mln
template <typename P, typename V>
struct with
{
- typedef accu::center<P,V> ret;
+ typedef accu::center<P, V> ret;
};
};
--
1.5.6.5
1
0
09 Feb '09
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-09 Edwin Carlinet <carlinet(a)lrde.epita.fr>
Try to make algebraic_union_find filter work with new accus.
* edwin/algebraic_union_find.hh: First version of algebraic
filter according to new accus.
* edwin/card.hh: Make card cleaner with MLN_INCLUDE_ONLY.
---
algebraic_union_find.hh | 417 ++++++++++++++++++++++++++++++++++++++++++++++++
card.hh | 96 ++++++++++-
2 files changed, 504 insertions(+), 9 deletions(-)
Index: trunk/milena/sandbox/edwin/algebraic_union_find.hh
===================================================================
--- trunk/milena/sandbox/edwin/algebraic_union_find.hh (revision 0)
+++ trunk/milena/sandbox/edwin/algebraic_union_find.hh (revision 3328)
@@ -0,0 +1,417 @@
+// 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.
+
+#ifndef MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
+# define MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
+
+///
+///
+/// \todo: Doc!
+///
+/// \todo Re-activate the fastest version when accumulators are
+/// cleaned-up.
+
+# include <mln/core/concept/image.hh>
+# include <mln/core/concept/neighborhood.hh>
+# include <mln/core/concept/accumulator.hh>
+# include <mln/data/fill.hh>
+# include <mln/util/pix.hh>
+
+
+# include <mln/level/sort_psites.hh>
+# include <mln/level/sort_offsets.hh>
+
+# include "accu_trait.hh"
+
+namespace mln
+{
+
+ namespace canvas
+ {
+
+ namespace morpho
+ {
+
+ namespace impl
+ {
+
+ // Generic version.
+
+ namespace generic
+ {
+
+ template <typename I>
+ inline
+ mln_psite(I)
+ find_root(I& parent, const mln_psite(I)& x)
+ {
+ if (parent(x) == x)
+ return x;
+ else
+ return parent(x) = find_root(parent, parent(x));
+ }
+
+ template <typename I, typename N, typename S, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_,
+ const Accumulator<A>& accu_,
+ mln_result(A) lambda)
+ {
+ trace::entering("canvas::morpho::impl::generic::algebraic_union_find");
+
+ // FIXME: Tests?
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, P) parent;
+ mln_ch_value(I, A) data;
+
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ initialize(data, input);
+ }
+
+ // First pass.
+ {
+ mln_fwd_piter(S) p(s_);
+ mln_niter(N) n(nbh, p);
+ for_all(p)
+ {
+ // Make set.
+ {
+ parent(p) = p;
+ /* FIXME: What if the value_type of DATA (i.e., A) were not
+ based on a accu::count<mln::pix>? Currently, nothing
+ enforces this, but the code below expects this line to be
+ valid:
+
+ data(p).take_as_init(make::pix(f.input, p))
+
+ which probably restricts the kind of input images.
+
+ If we want to be more generic, the initialization should
+ read something like:
+
+ init_data(p);
+
+ i.e., the functor for the initialization of data should
+ be passed as an argument to the canvas' ctor.
+
+ Of course, we might want to restrict attributes to the
+ accumulator accu::count<mln::pix> (which is perfectly
+ acceptable), but then this class should statically check
+ the conformance of the template parameter A to this
+ constraint. */
+ data(p).take_as_init(p); // FIXME: algebraic so p!
+ }
+
+ for_all(n)
+ if (input.domain().has(n) && deja_vu(n))
+ {
+ //do_union(n, p);
+ P r = find_root(parent, n);
+ if (r != p)
+ {
+ if (input(r) == input(p) || (activity(r) && data(r) < lambda)) // Equiv(r, p)
+ // Either a flat zone or the component of r is still growing.
+ {
+ /* FIXME: Same remark as above concerning the
+ initialization of data(p); instead of
+
+ data(p).take(data(r));
+
+ we should (or could) have
+
+ unite_data(p, r);
+
+ so as to keep the generic aspect of this canvas
+ (as long as the set of acceptable types for the
+ template parameter A is not bound). */
+ data(p).take(data(r));
+ parent(r) = p;
+ if (activity(r) == false)
+ activity(p) = false;
+ }
+ else
+ {
+ activity(p) = false;
+ }
+ }
+ }
+ deja_vu(p) = true;
+ }
+ }
+
+ // Second pass.
+ {
+ mln_bkd_piter(S) p(s_);
+ for_all(p)
+ if (parent(p) == p) // p is root.
+ output(p) = input(p);
+ else
+ output(p) = output(parent(p));
+ }
+
+ /*
+ Change 2nd pass into:
+ for_all(p) if (not is_root(p)) output(p) = output(parent(p));
+ and add in init:
+ mln::data::fill(output, input);
+ */
+ trace::exiting("canvas::morpho::impl::generic::algebraic_union_find");
+
+ return output;
+ }
+
+ } // end of namespace mln::canvas::morpho::impl::generic
+
+
+
+ // Fastest version.
+
+ template <typename I>
+ inline
+ unsigned
+ find_root_fastest(I& parent, unsigned x)
+ {
+ if (parent.element(x) == x)
+ return x;
+ else
+ return parent.element(x) = find_root_fastest(parent, parent.element(x));
+ }
+
+
+ template <typename I, typename N, typename S, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find_fastest(const Image<I>& input_,
+ const Neighborhood<N>& nbh_,
+ const Site_Set<S>& s_,
+ const Accumulator<A>& accu_,
+ mln_result(A) lambda)
+ {
+ trace::entering("canvas::morpho::impl::algebraic_union_find_fastest");
+
+ // FIXME: Tests?
+
+ const I& input = exact(input_);
+ const N& nbh = exact(nbh_);
+
+ mln_concrete(I) output;
+ initialize(output, input);
+
+ // Local type.
+ typedef mln_psite(I) P;
+
+ // Auxiliary data.
+ mln_ch_value(I, bool) deja_vu;
+ mln_ch_value(I, bool) activity;
+ mln_ch_value(I, unsigned) parent;
+ mln_ch_value(I, A) data;
+
+ // Initialization.
+ {
+ initialize(deja_vu, input);
+ mln::data::fill(deja_vu, false);
+ initialize(activity, input);
+ mln::data::fill(activity, true);
+ initialize(parent, input);
+ mln::data::fill(parent, 0);
+ initialize(data, input);
+ }
+
+ util::array<int> dp = offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
+ const unsigned n_points = s_.nelements();
+
+ // First pass.
+ {
+
+ for (unsigned i = 0; i < n_points; ++i)
+ {
+ unsigned p = s_[i]; // An offset.
+
+ // Make set.
+ parent.element(p) = p;
+ data.element(p).take_as_init(); // FIXME: Very bad et SEULEMENT POUR CARD !!! C CON!!!
+
+ for (unsigned j = 0; j < n_nbhs; ++j)
+ {
+ unsigned n = p + dp[j];
+ if (! deja_vu.element(n))
+ continue;
+
+ unsigned r = find_root_fastest(parent, n);
+ if (r != p)
+ {
+ if (input.element(r) == input.element(p)
+ || (activity.element(r)
+ && data.element(r) < lambda))
+ {
+ data.element(p).take();
+ parent.element(r) = p;
+ if (activity.element(r) == false)
+ activity.element(p) = false;
+ }
+ else
+ {
+ activity.element(p) = false;
+ }
+ }
+ }
+
+ deja_vu.element(p) = true;
+ }
+
+ }
+
+ // Second pass.
+ {
+ for (int i = n_points - 1; i >= 0 ; --i)
+ {
+ unsigned p = s_[i];
+ if (parent.element(p) == p) // p is root.
+ output.element(p) = input.element(p);
+ else
+ output.element(p) = output.element(parent.element(p));
+ }
+ }
+ trace::exiting("canvas::morpho::impl::algebraic_union_find_fastest");
+ return output;
+ }
+
+
+ } // end of namespace mln::canvas::morpho::impl
+
+
+
+ // Dispatch.
+
+ namespace internal
+ {
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find_dispatch(metal::false_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ mln_result(A) lambda,
+ bool increasing)
+ {
+ p_array<mln_psite(I)> s = increasing ?
+ level::sort_psites_increasing(input) :
+ level::sort_psites_decreasing(input);
+ return impl::generic::algebraic_union_find(input, nbh, s, accu,
+ lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find_dispatch(metal::true_,
+ const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ mln_result(A) lambda,
+ bool increasing)
+ {
+ util::array<unsigned> s = increasing ?
+ level::sort_offsets_increasing(input) :
+ level::sort_offsets_decreasing(input);
+ return impl::algebraic_union_find_fastest(input, nbh, s, accu, lambda);
+ }
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find_dispatch(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ mln_result(A) lambda,
+ bool increasing)
+ {
+ enum {
+ test = (mlc_equal(mln_trait_image_speed(I),
+ trait::image::speed::fastest)::value &&
+ mln_is_simple_neighborhood(N)::value &&
+ mlc_equal(mln_trait_accu_when_pix(A),
+ trait::accu::when_pix::use_whatever)::value)
+ };
+ return algebraic_union_find_dispatch(metal::bool_<test>(), input, nbh,
+ accu, lambda, increasing);
+ }
+
+ } // end of namespace mln::canvas::morpho::internal
+
+
+
+ // Facade.
+
+ template <typename I, typename N, typename A>
+ inline
+ mln_concrete(I)
+ algebraic_union_find(const Image<I>& input,
+ const Neighborhood<N>& nbh,
+ const Accumulator<A>& accu,
+ mln_result(A) lambda,
+ bool increasing)
+ {
+ return internal::algebraic_union_find_dispatch(input, nbh, accu,
+ lambda, increasing);
+ }
+
+
+ } // end of namespace mln::canvas::morpho
+
+ } // end of namespace mln::canvas
+
+} // end of namespace mln
+
+
+#endif // ! MLN_CANVAS_MORPHO_ALGEBRAIC_UNION_FIND_HH
Index: trunk/milena/sandbox/edwin/card.hh
===================================================================
--- trunk/milena/sandbox/edwin/card.hh (revision 3327)
+++ trunk/milena/sandbox/edwin/card.hh (revision 3328)
@@ -15,23 +15,101 @@
{
typedef mln_psite(I) argument;
- card () { init(); };
- void init () { c_ = 0; };
+ card ();
+ void init ();
- void take (const card<I>& accu) { c_ += accu.c_; };
+ void take (const card<I>& accu);
- void take () { ++c_; };
- void take (const mln_psite(I)& elt) { ++c_; };
- void take (const mln_value(I)& elt) { ++c_; };
- void take (const util::pix<I>& pix) { ++c_; };
+ void take ();
+ void take (const mln_psite(I)& elt);
+ void take (const mln_value(I)& elt);
+ void take (const util::pix<I>& pix);
- unsigned to_result() const { return c_; };
+ unsigned to_result() const;
- bool is_valid () const { return true; };
+ bool is_valid () const;
private:
unsigned c_;
};
+
+# ifndef MLN_INCLUDE_ONLY
+ template <typename I>
+ inline
+ card<I>::card () :
+ c_ (0)
+ {
+ }
+
+ template <typename I>
+ inline
+ void
+ card<I>::init ()
+ {
+ c_ = 0;
+ }
+
+ template <typename I>
+ inline
+ void
+ card<I>::take (const card<I>& accu)
+ {
+ c_ += accu.c_;
+ }
+
+
+ template <typename I>
+ inline
+ void
+ card<I>::take ()
+ {
+ ++c_;
+ };
+
+ template <typename I>
+ inline
+ void
+ card<I>::take (const mln_psite(I)& elt)
+ {
+ ++c_;
+ };
+
+
+ template <typename I>
+ inline
+ void
+ card<I>::take (const mln_value(I)& elt)
+ {
+ ++c_;
+ };
+
+
+ template <typename I>
+ inline
+ void
+ card<I>::take (const util::pix<I>& pix)
+ {
+ ++c_;
+ };
+
+ template <typename I>
+ inline
+ unsigned
+ card<I>::to_result() const
+ {
+ return c_;
+ };
+
+ template <typename I>
+ inline
+ bool
+ card<I>::is_valid () const
+ {
+ return true;
+ };
+# endif
+
+
} // mln::morpho::accu
} // mln::morpho
} // mln
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
ChangeLog:
2009-02-09 Fabien Freling <freling(a)lrde.epita.fr>
New IGR test files.
* fabien/igr/igr.cc: New test file.
* fabien/igr/img/slice_7.pgm: New test picture.
---
igr.cc | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 102 insertions(+)
Index: trunk/milena/sandbox/fabien/igr/igr.cc
===================================================================
--- trunk/milena/sandbox/fabien/igr/igr.cc (revision 0)
+++ trunk/milena/sandbox/fabien/igr/igr.cc (revision 3326)
@@ -0,0 +1,102 @@
+// Copyright (C) 2007, 2008, 2009 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.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/value/int_u8.hh>
+#include <mln/io/pgm/all.hh>
+#include <mln/io/pbm/all.hh>
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/labeling/flat_zones.hh>
+
+#include <mln/labeling/blobs.hh>
+#include <mln/labeling/compute.hh>
+#include <mln/level/compare.hh>
+#include <mln/fun/v2b/threshold.hh>
+#include <mln/level/transform.hh>
+#include <mln/accu/count.hh>
+#include <mln/value/label_8.hh>
+#include <mln/data/fill.hh>
+#include <mln/pw/all.hh>
+
+//FIXME: remove
+#include <mln/essential/2d.hh>
+
+//struct threshold : Function_v2v<threshold>
+//{
+// typedef bool result;
+// bool operator() (int_u8 val) const {if (val < 25) return false; return true;}
+//};
+
+int main()
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label_8;
+
+ trace::quiet = false;
+
+ image2d<int_u8> src;
+ io::pgm::load(src, "img/slice_7.pgm");
+
+ image2d<bool> threshold = level::transform(src, fun::v2b::threshold<int_u8>(25));
+
+ label_8 n;
+ image2d<label_8> labels = labeling::flat_zones(threshold, c4(), n);
+ accu::count<int_u8> a_;
+ util::array<unsigned> a = labeling::compute(a_, src, labels, n);
+
+ mln_ch_value_(image2d<int_u8>, bool) biggest;
+ initialize(biggest, src);
+ data::fill(biggest, false);
+ unsigned x = 0;
+ unsigned y = 0;
+ unsigned z = 0;
+ for (int i = 0; i < a.nelements(); ++i)
+ {
+ if (a[i] > x)
+ x = a[i];
+ if (x > y)
+ {
+ int swap = y;
+ y = x;
+ x = swap;
+ }
+ if (y > z)
+ {
+ int swap = z;
+ z = y;
+ y = swap;
+ }
+ }
+ data::fill((biggest | pw::value(labels) == x).rw(), true);
+ data::fill((biggest | pw::value(labels) == y).rw(), true);
+
+ // gradient_internal, center
+
+ io::pbm::save(biggest, "out.pgm");
+}
Index: trunk/milena/sandbox/fabien/igr/img/slice_7.pgm
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/milena/sandbox/fabien/igr/img/slice_7.pgm
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
1
0
* mln/registration/icp2.hh: add a better debug. Revamp and remove
useless overloads.
---
milena/ChangeLog | 7 +
milena/mln/registration/icp2.hh | 269 +++++++++++++++++++--------------------
2 files changed, 138 insertions(+), 138 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 9d32600..3d3cca5 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,10 @@
+2009-02-09 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update ICP.
+
+ * mln/registration/icp2.hh: add a better debug. Revamp and remove
+ useless overloads.
+
2009-02-09 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Optimize the video labeling canvas.
diff --git a/milena/mln/registration/icp2.hh b/milena/mln/registration/icp2.hh
index 1c83c25..1a6f331 100644
--- a/milena/mln/registration/icp2.hh
+++ b/milena/mln/registration/icp2.hh
@@ -31,6 +31,8 @@
/// \file mln/registration/icp.hh
///
/// Register an image over an another using the ICP algorithm.
+///
+/// \todo encode distances on 12 bits.
# include <cmath>
# include <algorithm>
@@ -61,7 +63,6 @@
# include <mln/literal/colors.hh>
# include <mln/core/image/slice_image.hh>
-# include <mln/util/timer.hh>
#include <mln/core/image/tr_image.hh>
#include <mln/core/image/extension_fun.hh>
@@ -70,6 +71,7 @@
#include <mln/accu/sum.hh>
#include <mln/debug/histo.hh>
+# include <mln/util/timer.hh>
namespace mln
{
@@ -77,7 +79,8 @@ namespace mln
namespace registration
{
-
+ // std::string method = "compute_on_subsets";
+ std::string method = "compute_on_subset_and_p";
using namespace fun::x2x;
/*! Register point in \p c using a function of closest points
@@ -127,15 +130,15 @@ namespace mln
{
typedef mln_image_from_grid(mln_grid(P), P) I;
typedef mln_ch_value(I, P) cp_ima_t;
- typedef mln_ch_value(I,value::int_u8) dmap_t;
+ typedef mln_ch_value(I,value::int_u16) dmap_t;
public:
closest_point_with_map(const p_array<P>& X)
{
box3d box = geom::bbox(X);
- box.enlarge(1, box.nrows() / 2);
- box.enlarge(2, box.ncols() / 2);
+ box.enlarge(1, box.nrows());
+ box.enlarge(2, box.ncols());
std::cout << "Map image defined on " << box << std::endl;
typedef mln_ch_value(I, bool) model_t;
@@ -147,13 +150,13 @@ namespace mln
util::timer t;
t.start();
dmap_X_ = canvas::distance_geodesic(model, c6(),
- mln_max(value::int_u8),
+ mln_max(value::int_u16),
f);
std::cout << "canvas::distance_geodesic - " << t << "s" << std::endl;
cp_ima_ = f.cp_ima;
-#ifndef NDEBUG
+//#ifndef NDEBUG
mln_ch_value(I, bool) debug2(box);
data::fill(debug2, false);
mln_ch_value(I, value::rgb8) debug(box);
@@ -175,7 +178,7 @@ namespace mln
io::pbm::save(slice(debug2,0), "debug2-b.ppm");
io::ppm::save(slice(debug,0), "debug.ppm");
std::cout << "map saved" << std::endl;
-#endif
+//#endif
}
mln_site(I) operator()(const mln_site(I)& p) const
@@ -278,19 +281,58 @@ namespace mln
template <typename P, typename F>
- p_array<P>
- remove_too_far_sites(image3d<value::rgb8>& out, const p_array<P>& P_,
+ void
+ remove_too_far_sites_debug(image3d<value::rgb8>& out, const p_array<P>& P_,
const F& closest_point,
const std::pair<algebra::quat,mln_vec(P)>& pair,
- const p_array<P>& X, p_array<P>& removed_set,
- unsigned r)
+ const p_array<P>& X,
+ unsigned r, int d_min, int d_max, unsigned prefix)
+ {
+ unsigned removed = 0;
+ accu::histo<value::int_u8> h;
+ mln_piter(p_array<P>) p(P_);
+ data::fill(out, literal::black);
+ data::fill((out | X).rw(), literal::white);
+
+ for_all(p)
+ {
+ vec3d_f Pk_i = pair.first.rotate(p.to_vec()) + pair.second;
+ vec3d_f Yk_i = closest_point(Pk_i).to_vec();
+
+ int d_i = closest_point.dmap_X_(Pk_i);
+ if (d_i >= d_min && d_i <= d_max)
+ out(Pk_i) = literal::green;
+ else
+ {
+ ++removed;
+ out(Pk_i) = literal::red;
+ }
+ }
+
+ std::ostringstream ss1;
+ ss1 << "histo_" << prefix << r << ".dat";
+// debug::histo_plot(h, ss1.str());
+ std::cout << h << std::endl;
+
+ std::ostringstream ss2;
+ ss2 << "out_" << prefix << r << ".ppm";
+ io::ppm::save(mln::slice(out,0), ss2.str());
+
+ std::cout << "Points removed with the whole set and current d_min/d_max: " << removed << std::endl;
+
+ }
+
+ template <typename P, typename F>
+ void
+ compute_distance_criteria(const p_array<P>& P_,
+ const F& closest_point,
+ const std::pair<algebra::quat,mln_vec(P)>& pair,
+ unsigned r, int& d_min, int& d_max)
{
mln_piter(p_array<P>) p(P_);
accu::histo<value::int_u8> h;
-// float sd = compute_standard_deviation(P_, pair, closest_point);
float sd;
- int d_min, d_max;
{
accu::sum<float> s, s2;
for_all(p)
@@ -306,17 +348,31 @@ namespace mln
d_min = int(mean - sd);
d_max = int(mean + sd);
}
-
std::cout << "Standard deviation = " << sd << std::endl;
+ std::ostringstream ss1;
+ ss1 << "histo_" << r << ".dat";
+ debug::histo_plot(h, ss1.str());
+ std::cout << h << std::endl;
std::cout << "d thresholds = " << d_min << ' ' << d_max << std::endl;
+ }
+ template <typename P, typename F>
+ p_array<P>
+ remove_too_far_sites(image3d<value::rgb8>& out, const p_array<P>& P_,
+ const F& closest_point,
+ const std::pair<algebra::quat,mln_vec(P)>& pair,
+ const p_array<P>& X, p_array<P>& removed_set,
+ unsigned r, int d_min, int d_max,
+ const std::string& method)
+ {
p_array<P> tmp;
unsigned removed = 0;
- data::fill(out, literal::white);
- data::fill((out | X).rw(), literal::black);
+ data::fill(out, literal::black);
+ data::fill((out | X).rw(), literal::white);
+ mln_piter(p_array<P>) p(P_);
for_all(p)
{
vec3d_f Pk_i = pair.first.rotate(p.to_vec()) + pair.second;
@@ -336,13 +392,8 @@ namespace mln
}
}
- std::ostringstream ss1;
- ss1 << "histo_" << r << ".dat";
- debug::histo_plot(h, ss1.str());
- std::cout << h << std::endl;
-
std::ostringstream ss2;
- ss2 << "out_0" << r << ".ppm";
+ ss2 << method << "_" << r << "_removed_sites" << ".ppm";
io::ppm::save(mln::slice(out,0), ss2.str());
std::cout << "Points removed: " << removed << std::endl;
@@ -350,6 +401,37 @@ namespace mln
return tmp;
}
+ template <typename P>
+ void
+ display_sites_used_in_icp(image3d<value::rgb8>& out, const p_array<P>& P_sub,
+ const p_array<P>& P_, const p_array<P>& X,
+ unsigned r, const std::string& prefix,
+ const std::pair<algebra::quat,mln_vec(P)>& pair,
+ const std::string& period, const value::rgb8& c)
+ {
+ data::fill(out, literal::black);
+ data::fill((out | X).rw(), literal::white);
+
+ mln_piter(p_array<P>) p1(P_);
+ for_all(p1)
+ {
+ vec3d_f Pk_i = pair.first.rotate(p1.to_vec()) + pair.second;
+ out(Pk_i) = literal::red;
+ }
+
+ mln_piter(p_array<P>) p2(P_sub);
+ for_all(p2)
+ {
+ vec3d_f Pk_i = pair.first.rotate(p2.to_vec()) + pair.second;
+ out(Pk_i) = c;
+ }
+
+ std::ostringstream ss;
+ ss << prefix << "_" << r << "_" << period << ".ppm";
+
+ io::ppm::save(slice(out,0), ss.str());
+ }
+
template <typename P, typename F>
inline
@@ -591,85 +673,18 @@ namespace mln
return result;
}
-
- /// Shuffle the sites in P_.
- /// Use one third of P_'s sites for each run.
- /// For each run, it removes sites which are too close or too far.
- template <typename P, typename F>
- inline
- composed< translation<P::dim,float>,rotation<P::dim,float> >
- icp_clean(const p_array<P>& P_,
- const p_array<P>& X,
- const F& closest_point)
- {
- util::timer t;
- t.start();
-
- // P_bak is shuffled.
- p_array<P> P_bak = P_;
- std::vector<mln_element(p_array<P>)>& v = P_bak.hook_std_vector_();
- std::random_shuffle(v.begin(), v.end());
-
- // P_sub = 1/3 * P_bak;
- p_array<P> P_sub = P_bak;
- P_sub.hook_std_vector_().resize(P_bak.nsites() / 3);
-
- unsigned r = 0;
- std::pair<algebra::quat,mln_vec(P)> pair;
- pair.first = algebra::quat(1,0,0,0);
- pair.second = literal::zero;
- box3d box = geom::bbox(X);
- box.enlarge(40);
- image3d<value::rgb8> out(box);
- p_array<P> removed_set;
- do
- {
- /// Compute transformation.
- pair = icp(P_sub, X, closest_point,
- pair.first,
- pair.second);
-
- pair = icp(P_sub, X, closest_point,
- pair.first,
- pair.second);
-
- P_sub = remove_too_far_sites(out, P_sub,
- closest_point, pair, X, removed_set, r);
-
-
- ++r;
-
- //Add more data
- if (r < 3)
- for (unsigned i = (P_bak.nsites() / 3) * r;
- i < (P_bak.nsites() / 3) * (r + 1); ++i)
- {
- P_sub.append(P_bak[i]);
- }
-
- } while (r < 4);
- std::cout << "icp = " << t << std::endl;
-
- typedef rotation<3u,float> rot_t;
- rot_t tqR(pair.first);
- typedef translation<3u,float> trans_t;
- trans_t tqT(pair.second);
- composed<trans_t,rot_t> result(tqT, tqR);
-
- return result;
- }
-
-
/// Shuffle sites in P_.
/// Do the first run with all sites.
/// For each run, remove sites which are too far or too close.
- template <typename P, typename F>
+ template <typename P>
inline
composed< translation<P::dim,float>,rotation<P::dim,float> >
- icp_clean2(const p_array<P>& P_,
- const p_array<P>& X,
- const F& closest_point)
+ registration(const p_array<P>& P_,
+ const p_array<P>& X)
{
+ registration::closest_point_with_map<P> closest_point(X);
+// registration::closest_point_basic<point3d> closest_point(X);
+
util::timer t;
t.start();
@@ -681,21 +696,38 @@ namespace mln
pair.first = algebra::quat(1,0,0,0);
pair.second = literal::zero;
box3d box = geom::bbox(X);
- box.enlarge(40);
+ box.enlarge(1, 60);
+ box.enlarge(2, 60);
image3d<value::rgb8> out(box);
p_array<P> removed_set;
+
do
{
+ std::cout << std::endl << std::endl << "==== New run - " << r << std::endl;
pair = icp(P_bak, X, closest_point,
pair.first,
pair.second);
+ display_sites_used_in_icp(out, P_bak, P_, X, r, method, pair, "final", literal::blue);
+
+ int d_min, d_max;
+ compute_distance_criteria(P_bak, closest_point, pair, r, d_min, d_max);
+
P_bak = remove_too_far_sites(out, P_bak,
- closest_point, pair, X, removed_set, r);
+ closest_point, pair, X, removed_set,
+ r, d_min, d_max, method);
+
+// P_bak = remove_too_far_sites(out, P_,
+// closest_point, pair, X, removed_set,
+// r, d_min, d_max, method);
+
+
+ display_sites_used_in_icp(out, P_bak, P_, X, r, method, pair, "schanges", literal::green);
++r;
- } while (r < 4);
+ std::cout << "==== End of run" << std::endl;
+ } while (r < 10);
std::cout << "icp = " << t << std::endl;
draw_last_run(box, P_bak, removed_set, X, pair.first, pair.second);
@@ -710,45 +742,6 @@ namespace mln
}
-
- /// Run icp once with 1/10 of the sites and run it once again with the
- /// resulting tranformation and all the sites.
- template <typename P, typename F>
- inline
- composed< translation<P::dim,float>,rotation<P::dim,float> >
- icp_fast(const p_array<P>& P_,
- const p_array<P>& X,
- const F& closest_point)
- {
- typedef std::pair<algebra::quat,mln_vec(P)> pair_t;
-
- p_array<P> P_sub = P_;
- std::vector<mln_element(p_array<P>)>& v = P_sub.hook_std_vector_();
- std::random_shuffle(v.begin(), v.end());
- v.resize(P_.nsites() / 10);
-
- util::timer t;
- t.start();
- pair_t tmp = icp(P_sub, X, closest_point,
- algebra::quat(1,0,0,0), literal::zero);
-
- std::cout << "icp_1 - " << t << "s" << std::endl;
- t.restart();
-
- pair_t tmp2 = icp(P_, X, closest_point,
- tmp.first, tmp.second);
-
- std::cout << "icp_2 - " << t << "s" << std::endl;
-
- typedef rotation<3u,float> rot_t;
- rot_t tqR(tmp2.first);
- typedef translation<3u,float> trans_t;
- trans_t tqT(tmp2.second);
- composed<rot_t,trans_t> result(tqR, tqT);
-
- return result;
- }
-
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln::registration
--
1.5.6.5
1
0
* lazzara/igr.cc: update code. More debug.
* lazzara/igr-cloud.cc: new. Register clouds of points.
* lazzara/irm_seg_with_mm_and_rag.mine.cc: new. Segment using
meyer_wst and register clouds of points.
---
milena/sandbox/ChangeLog | 11 +
milena/sandbox/lazzara/igr-cloud.cc | 61 ++++
milena/sandbox/lazzara/igr.cc | 297 ++++++++----------
.../lazzara/irm_seg_with_mm_and_rag.mine.cc | 331 ++++++++++++++++++++
4 files changed, 533 insertions(+), 167 deletions(-)
create mode 100644 milena/sandbox/lazzara/igr-cloud.cc
create mode 100644 milena/sandbox/lazzara/irm_seg_with_mm_and_rag.mine.cc
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index f82dab8..0e61ceb 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,14 @@
+2009-02-09 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Update igr's code.
+
+ * lazzara/igr.cc: update code. More debug.
+
+ * lazzara/igr-cloud.cc: new. Register clouds of points.
+
+ * lazzara/irm_seg_with_mm_and_rag.mine.cc: new. Segment using
+ meyer_wst and register clouds of points.
+
2009-02-09 Fabien Freling <freling(a)lrde.epita.fr>
Implement fastest versions of labeling.
diff --git a/milena/sandbox/lazzara/igr-cloud.cc b/milena/sandbox/lazzara/igr-cloud.cc
new file mode 100644
index 0000000..18d976f
--- /dev/null
+++ b/milena/sandbox/lazzara/igr-cloud.cc
@@ -0,0 +1,61 @@
+# include <cmath>
+# include <algorithm>
+
+# include <mln/core/alias/vec3d.hh>
+# include <mln/math/jacobi.hh>
+# include <mln/fun/x2x/all.hh>
+# include <mln/fun/x2v/all.hh>
+# include <mln/convert/to.hh>
+# include <mln/accu/compute.hh>
+# include <mln/accu/center.hh>
+# include <mln/accu/rms.hh>
+# include <mln/trait/image_from_grid.hh>
+# include <mln/set/compute.hh>
+
+//Should be removed when closest_point functors are moved.
+# include <mln/core/alias/neighb3d.hh>
+# include <mln/transform/internal/closest_point_functor.hh>
+# include <mln/canvas/distance_geodesic.hh>
+# include <mln/pw/all.hh>
+
+# include <mln/io/ppm/save.hh>
+# include <mln/io/pbm/save.hh>
+# include <mln/debug/colorize.hh>
+
+# include <mln/literal/black.hh>
+# include <mln/literal/white.hh>
+# include <mln/literal/colors.hh>
+
+# include <mln/core/image/slice_image.hh>
+# include <mln/util/timer.hh>
+
+#include <mln/core/image/tr_image.hh>
+#include <mln/core/image/extension_fun.hh>
+
+#include <mln/accu/histo.hh>
+#include <mln/accu/sum.hh>
+#include <mln/debug/histo.hh>
+#include <mln/io/cloud/load.hh>
+
+#include <mln/registration/icp2.hh>
+
+int main(int, char *argv[])
+{
+ using namespace mln;
+ using namespace fun::x2x;
+ using value::rgb8;
+ using value::int_u8;
+ using value::label_16;
+
+ //Load image
+ typedef image3d<bool> K;
+
+ p_array<point3d> in_3d_, ref_3d_;
+ io::cloud::load(in_3d_, argv[1]);
+ io::cloud::load(ref_3d_, argv[2]);
+
+ typedef rotation<3u,float> rot_t;
+ typedef translation<3u,float> trans_t;
+ composed<trans_t,rot_t> qk = registration::registration(in_3d_, ref_3d_);
+
+}
diff --git a/milena/sandbox/lazzara/igr.cc b/milena/sandbox/lazzara/igr.cc
index 05d8471..0df1d92 100644
--- a/milena/sandbox/lazzara/igr.cc
+++ b/milena/sandbox/lazzara/igr.cc
@@ -16,6 +16,10 @@
#include <mln/io/cloud/load.hh>
#include <mln/util/timer.hh>
+#include <mln/core/concept/function.hh>
+#include <mln/trait/ch_value.hh>
+
+#include <mln/fun/p2b/big_chess.hh>
struct threshold : mln::Function_p2b<threshold>
{
@@ -29,130 +33,10 @@ struct threshold : mln::Function_p2b<threshold>
namespace mln
{
- using namespace fun::x2x;
-
- template <typename P>
- struct transf_quat_t
- {
- transf_quat_t()
- : q_(1,0,0,0), t_(literal::zero)
- {
- }
-
-
- inline
- float epsilon()
- {
- static const float e = 1e-5;
- return e;
- }
-
- inline
- bool about_equal(float val1, float val2)
- {
- return fabs(val1 - val2) < epsilon();
- }
-
- template <unsigned n>
- algebra::vec<n,float> rotate(const algebra::quat& q, const algebra::vec<n,float>& p)
- {
- return (q * algebra::quat(0. ,p) * q.inv()).v();
- }
-
-
- bool check_rotation(const algebra::h_mat<3,float>& mat, const algebra::quat& q)
- {
- srand(time(0));
- assert(q.is_unit());
- rotation<3,float> rot(mat);
-
- algebra::vec<3,float>
- tmp = make::vec(rand(), rand(), rand()),
- p = tmp / norm::l2(tmp),
- p_rot_1 = rotate(q, p),
- p_rot_2 = rot(p);
- return about_equal(norm::l2(p_rot_1 - p_rot_2), 0.f);
- }
-
-
- transf_quat_t(const algebra::quat& q, const vec3d_f& t)
- : q_(q), t_(t)
- {
- assert(q.is_unit());
- float
- w = q.to_vec()[0],
- x = q.to_vec()[1], x2 = 2*x*x, xw = 2*x*w,
- y = q.to_vec()[2], y2 = 2*y*y, xy = 2*x*y, yw = 2*y*w,
- z = q.to_vec()[3], z2 = 2*z*z, xz = 2*x*z, yz = 2*y*z, zw = 2*z*w;
- float data[9] = {1.f - y2 - z2, xy - zw, xz + yw,
- xy + zw, 1.f - x2 - z2, yz - xw,
- xz - yw, yz + xw, 1.f - x2 - y2};
-
- algebra::h_mat<3,float> tmp = make::h_mat(data);
- std::cout << tmp << std::endl;
- // postcondition
- assert(check_rotation(tmp, q));
- }
-
- void
- set_quat(const algebra::quat& q)
- {
- q_ = q;
- }
-
-
- void
- set_trans(const vec3d_f& t)
- {
- t_ = t;
- }
-
- algebra::vec<P::dim,float>
- operator()(const algebra::vec<P::dim,float>& v) const
- {
- return (q_ * algebra::quat(0., v) * q_.inv()).v() + t_;
- }
-
- algebra::quat q_;
- vec3d_f t_;
- };
-
-
- template <typename P>
- struct transf_mat_t
- {
- typedef rotation<P::dim,float> rot_t;
- typedef translation<P::dim,float> trans_t;
-
- transf_mat_t() {}
- transf_mat_t(const algebra::quat& q, const vec3d_f& t)
- : r_(q), t_(t), c_(r_, t_)
- {
- }
-
- void
- set_quat(const algebra::quat& q)
- {
- r_ = rot_t(q);
- }
-
- void
- set_trans_(const vec3d_f& t)
- {
- t_ = trans_t(t);
- }
-
- algebra::vec<P::dim,float>
- operator()(const algebra::vec<P::dim,float>& v) const
- {
- return c_(v);
- }
-
- rot_t r_;
- trans_t t_;
- composed<rot_t, trans_t> c_;
- };
-
+ namespace registration
+ {
+ extern std::string method;
+ }
}
@@ -240,18 +124,16 @@ get_main_object_shape(const mln::Image<I>& in)
typedef image2d<bool> J;
-// threshold f;
-// J in_bw = binarization::binarization(in, f);
-// io::pbm::save(in_bw, "01_in_bw.pbm");
+ threshold f;
+ J in_bw = binarization::binarization(in, f);
+ io::pbm::save(in_bw, "01_in_bw.pbm");
-// J ima = keep_largest_component(in_bw);
- J ima = keep_largest_component(in);
-// io::pbm::save(in_bw, "02_ima.pbm");
- io::pbm::save(in, "ima.pbm");
+ J ima = keep_largest_component(in_bw);
+// J ima = keep_largest_component(in);
+ io::pbm::save(ima, "02_ima.pbm");
std::cout << "Compute gradient" << std::endl;
J ima_grad = morpho::gradient(ima, win_c4p());
- io::pbm::save(ima_grad, "ima_grad.pbm");
return ima_grad;
}
@@ -262,31 +144,87 @@ namespace mln
namespace debug
{
+
template <typename I, typename T>
- void
- compare_registration(Image<I>& P_, Image<I>& X_, const T& transf)
+ image3d<value::rgb8>
+ make_registered_image(Image<I>& P_, Image<I>& X_, const T& transf)
{
I& P = exact(P_);
I& X = exact(X_);
mln_pset(I) box = geom::bbox(X);
- box.enlarge(40);
+ box.enlarge(1, 60);
+ box.enlarge(2, 60);
typedef mln_ch_value(I,value::rgb8) result_t;
result_t result(box);
extension_fun<result_t,pw::cst_<mln_value(result_t)> > ext_result(result, pw::cst(value::rgb8(0,0,0)));
extension_fun<I,pw::cst_<mln_value(I)> > ext_X(X, pw::cst(false));
-
data::fill(ext_result, literal::black);
- data::fill((ext_result | (pw::value(ext_X) == true)).rw(), literal::white);
mln_VAR(ig, (P | pw::value(P) == true));
mln_piter(ig_t) p(ig.domain());
for_all(p)
ext_result(transf(p.to_vec())) = literal::green;
- io::ppm::save(slice(ext_result,0), "registered-1.ppm");
+ return ext_result;
}
+
+ template <typename I, typename J>
+ void
+ compare_registration(Image<I>& registered_, Image<J>& X_)
+ {
+ I& registered = exact(registered_);
+ J& X = exact(X_);
+
+ typedef mln_ch_value(I,value::rgb8) result_t;
+ result_t result;
+ initialize(result, registered);
+ extension_fun<J,pw::cst_<mln_value(J)> > ext_X(X, pw::cst(false));
+
+ data::fill(result, literal::black);
+ data::fill((result | (pw::value(ext_X) == true)).rw(), literal::white);
+ data::fill((result | (pw::value(registered) != pw::cst(literal::black))).rw(),
+ literal::green);
+
+ io::ppm::save(slice(result,0), "final_registered.ppm");
+ }
+
+
+
+ template <typename I, typename T>
+ void
+ compare_registration2(Image<I>& P_, Image<I>& X_,
+ const T& transf)
+ {
+ I& P = exact(P_);
+ const I& X = exact(X_);
+
+ typedef extension_fun<I,pw::cst_<mln_value(I)> > ext_P_t;
+ ext_P_t ext_P(P, pw::cst(value::rgb8(literal::black)));
+ tr_image<box3d, ext_P_t, T> trima(P.domain(), ext_P, transf);
+ io::ppm::save(slice(trima, 0), "trima.ppm");
+
+ I reg(X.domain());
+ data::fill(reg, literal::black);
+ mln_piter(I) p(P.domain());
+ for_all(p)
+ if (reg.domain().has(transf(p.to_vec())))
+ reg(transf(p.to_vec())) = P(p);
+ io::ppm::save(slice(reg,0), "registered-2.ppm");
+
+ I tmp2 = duplicate(X);
+ fun::p2b::big_chess<box3d> fun2(tmp2.domain(), 20);
+ data::paste((reg | fun2), tmp2);
+ io::ppm::save(slice(tmp2,0), "registration_filter-a.ppm");
+
+ I tmp = duplicate(X);
+ fun::p2b::big_chess<box3d> fun(tmp.domain(), 20);
+ data::paste((trima | fun), tmp);
+
+ io::ppm::save(slice(tmp,0), "registration_filter.ppm");
+ }
+
}
}
@@ -302,42 +240,67 @@ int main(int, char* argv[])
//Load image
typedef image2d<rgb8> I;
typedef image2d<bool> J;
-
-// I in;
-// J in;
-// io::pbm::load(in, argv[1]);
-// J in_grad = get_main_object_shape(in);
-
-// I ref;
-// J ref;
-// io::pbm::load(ref, argv[2]);
-// J ref_grad = get_main_object_shape(ref);
-
typedef image3d<bool> K;
-
- p_array<point3d> in_3d_, ref_3d_;
- io::cloud::load(in_3d_, argv[1]);
- io::cloud::load(ref_3d_, argv[2]);
-
- std::cout << "* loading data" << std::endl;
- std::cout << " igr.cc - in_3d_.nsites = " << in_3d_.nsites() << std::endl;
- std::cout << " igr.cc - ref_3d_.nsites = " << ref_3d_.nsites() << std::endl;
- K in_3d = convert::to<K>(in_3d_);
- K ref_3d = convert::to<K>(ref_3d_);
-
- registration::closest_point_with_map<point3d> closest_point(ref_3d_);
-// registration::closest_point_basic<point3d> closest_point(ref_3d_);
-
+ typedef image3d<value::rgb8> L;
+
+ I in;
+ io::ppm::load(in, argv[1]);
+ J in_obj = get_main_object_shape(in);
+ io::pbm::save(in_obj, "in_obj.pbm");
+
+ I ref;
+ io::ppm::load(ref, argv[2]);
+ J ref_obj = get_main_object_shape(ref);
+ io::pbm::save(ref_obj, "ref_obj.pbm");
+
+// p_array<point3d> in_3d_, ref_3d_;
+// io::cloud::load(in_3d_, argv[1]);
+// io::cloud::load(ref_3d_, argv[2]);
+//
+// std::cout << "* loading data" << std::endl;
+// std::cout << " igr.cc - in_3d_.nsites = " << in_3d_.nsites() << std::endl;
+// std::cout << " igr.cc - ref_3d_.nsites = " << ref_3d_.nsites() << std::endl;
+// K in_3d = convert::to<image3d<bool> >(in_3d_);
+// K ref_3d = convert::to<image3d<bool> >(ref_3d_);
+// io::pbm::save(slice(in_3d,0), "in_shape.ppm");
+// io::pbm::save(slice(ref_3d,0), "ref_shape.ppm");
+// K in = duplicate(in_3d);
+// K ref = duplicate(ref_3d);
+
+ K in_3d = make::image3d(in_obj);
+ K ref_3d = make::image3d(ref_obj);
+ std::cout << " igr.cc - in_3d.nsites = " << in_3d.nsites() << std::endl;
+ std::cout << " igr.cc - ref_3d.nsites = " << ref_3d.nsites() << std::endl;
+
+ typedef p_array<point3d> p_arr_t;
+ p_arr_t in_3d_ = convert::to<p_arr_t>(in_3d);
+ p_arr_t ref_3d_ = convert::to<p_arr_t>(ref_3d);
+
+
+/// Add objects shapes in original images.
+ L in_wborders = make::image3d(duplicate(in));
+ data::fill((in_wborders | in_3d_).rw(), literal::green);
+ io::ppm::save(slice(in_wborders,0), "in_with_borders.ppm");
+
+ L ref_wborders = make::image3d(duplicate(ref));
+ data::fill((ref_wborders | ref_3d_).rw(), literal::green);
+ io::ppm::save(slice(ref_wborders,0), "ref_with_borders.ppm");
+
+
+
+ // Starting registration.
util::timer t;
t.start();
-
typedef rotation<3u,float> rot_t;
typedef translation<3u,float> trans_t;
- composed<trans_t,rot_t> qk = registration::icp_clean2(in_3d_, ref_3d_, closest_point);
+ composed<trans_t,rot_t> qk = registration::registration(in_3d_, ref_3d_);
+ std::cout << "igr.cc - Registration - " << t << "s" << std::endl;
- std::cout << "igr.cc - Registration - " << t << std::endl;
std::cout << "* Build result image" << std::endl;
- debug::compare_registration(in_3d, ref_3d, qk);
+ image3d<value::rgb8> registered = debug::make_registered_image(in_3d, ref_3d, qk);
+ debug::compare_registration(registered, ref_3d);
+
+ debug::compare_registration2(in_wborders, ref_wborders, qk);
}
diff --git a/milena/sandbox/lazzara/irm_seg_with_mm_and_rag.mine.cc b/milena/sandbox/lazzara/irm_seg_with_mm_and_rag.mine.cc
new file mode 100644
index 0000000..5b54eca
--- /dev/null
+++ b/milena/sandbox/lazzara/irm_seg_with_mm_and_rag.mine.cc
@@ -0,0 +1,331 @@
+
+#include <iterator>
+#include <iostream>
+#include <algorithm>
+
+#include <mln/core/image/image2d.hh>
+
+#include <mln/core/alias/neighb2d.hh>
+#include <mln/core/alias/window2d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/image/extension_fun.hh>
+#include <mln/core/image/tr_image.hh>
+#include <mln/core/var.hh>
+#include <mln/win/rectangle2d.hh>
+
+#include <mln/fun/p2b/big_chess.hh>
+#include <mln/fun/x2x/all.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/pgm/save.hh>
+#include <mln/io/pbm/save.hh>
+#include <mln/io/ppm/save.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_16.hh>
+
+#include <mln/level/transform.hh>
+
+#include <mln/convert/to_window.hh>
+#include <mln/convert/to_image.hh>
+#include <mln/convert/to_fun.hh>
+
+#include <mln/labeling/compute.hh>
+#include <mln/labeling/background.hh>
+
+#include <mln/level/convert.hh>
+
+#include <mln/make/image3d.hh>
+
+#include <mln/morpho/gradient.hh>
+#include <mln/morpho/closing_area.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/accu/mean.hh>
+//#include <mln/level/take.hh>
+
+#include <mln/util/graph.hh>
+
+#include <mln/literal/colors.hh>
+
+#include <mln/debug/println.hh>
+
+#include <mln/registration/icp2.hh>
+
+mln::value::int_u8 foo(unsigned u)
+{
+ return u == 0 ?
+ 0 : // wshed line
+ 1 + (u - 1) % 255; // basin
+}
+
+
+namespace mln
+{
+ namespace debug
+ {
+
+ template <typename I, typename T>
+ image3d<value::rgb8>
+ make_registered_image(Image<I>& P_, Image<I>& X_, const T& transf)
+ {
+ I& P = exact(P_);
+ I& X = exact(X_);
+
+ mln_pset(I) box = geom::bbox(X);
+ box.enlarge(1, 60);
+ box.enlarge(2, 60);
+
+ typedef mln_ch_value(I,value::rgb8) result_t;
+ result_t result(box);
+ extension_fun<result_t,pw::cst_<mln_value(result_t)> > ext_result(result, pw::cst(value::rgb8(0,0,0)));
+ extension_fun<I,pw::cst_<mln_value(I)> > ext_X(X, pw::cst(false));
+ data::fill(ext_result, literal::black);
+
+ mln_VAR(ig, (P | pw::value(P) == true));
+ mln_piter(ig_t) p(ig.domain());
+ for_all(p)
+ ext_result(transf(p.to_vec())) = literal::green;
+
+ return ext_result;
+ }
+
+ template <typename I, typename J>
+ void
+ compare_registration(Image<I>& registered_, Image<J>& X_)
+ {
+ I& registered = exact(registered_);
+ J& X = exact(X_);
+
+ typedef mln_ch_value(I,value::rgb8) result_t;
+ result_t result;
+ initialize(result, registered);
+ extension_fun<J,pw::cst_<mln_value(J)> > ext_X(X, pw::cst(false));
+
+ data::fill(result, literal::black);
+ data::fill((result | (pw::value(ext_X) == true)).rw(), literal::white);
+ data::fill((result | (pw::value(registered) != pw::cst(literal::black))).rw(),
+ literal::green);
+
+ io::ppm::save(slice(result,0), "tmp_final_registered.ppm");
+ }
+
+
+
+ template <typename I, typename T>
+ void
+ compare_registration2(Image<I>& P_, Image<I>& X_,
+ const T& transf)
+ {
+ I& P = exact(P_);
+ const I& X = exact(X_);
+
+ //FIXME: tr_image is bugged!
+// typedef extension_fun<I,pw::cst_<mln_value(I)> > ext_P_t;
+// ext_P_t ext_P(P, pw::cst(value::int_u8(0u)));
+// tr_image<box3d, ext_P_t, T> trima(P.domain(), ext_P, transf);
+// io::pgm::save(slice(trima, 0), "tmp_trima.ppm");
+
+ I reg(X.domain());
+ data::fill(reg, literal::zero);
+ mln_piter(I) p(P.domain());
+ for_all(p)
+ if (reg.domain().has(transf(p.to_vec())))
+ reg(transf(p.to_vec())) = P(p);
+ io::pgm::save(slice(reg,0), "tmp_registered-2.ppm");
+
+ I tmp2 = duplicate(X);
+ fun::p2b::big_chess<box3d> fun2(tmp2.domain(), 20);
+ data::paste((reg | fun2), tmp2);
+ io::pgm::save(slice(tmp2,0), "tmp_registration_filter-a.ppm");
+
+// I tmp = duplicate(X);
+// fun::p2b::big_chess<box3d> fun(tmp.domain(), 20);
+// data::paste((trima | fun), tmp);
+//
+// io::pgm::save(slice(tmp,0), "tmp_registration_filter.ppm");
+ }
+
+ }
+
+
+ struct threshold : Function_p2b<threshold>
+ {
+ bool operator()(const value::rgb8& val) const
+ {
+ unsigned inty = (val.red() + val.blue() + val.green());
+ return inty > 100 && inty < 600;
+ }
+
+ bool operator()(const unsigned& val) const
+ {
+ return val < 120;// && val < 230;
+ }
+ };
+
+ template <typename I>
+ mln_ch_value(I,bool)
+ fill_holes(const mln::Image<I>& ima)
+ {
+ using namespace mln;
+
+ mln_ch_value(I,bool) output;
+ initialize(output, ima);
+ data::fill(output, true);
+
+ value::label_16 nlabels;
+ mln_ch_value(I, value::label_16) lbl = labeling::background(ima, c4(), nlabels);
+
+ mln_VAR(lbl_count, labeling::compute(accu::meta::count(), ima, lbl, nlabels));
+
+ unsigned max_id = 1;
+ for (unsigned i = 2; i <= nlabels; ++i)
+ if (lbl_count[max_id] < lbl_count[i])
+ max_id = i;
+
+ data::fill((output | pw::value(lbl) == max_id).rw(), false);
+
+ return output;
+ }
+
+
+ template <typename I>
+ mln_ch_value(I,bool)
+ keep_largest_component(const Image<I>& ima)
+ {
+ using namespace mln;
+
+ image2d<bool> in_bw_cleaned = fill_holes(ima);
+// io::pbm::save(in_bw_cleaned, "in_bw_cleaned.pbm");
+
+ logical::not_inplace(in_bw_cleaned);
+ image2d<bool> in_bw_cleaned_full = fill_holes(in_bw_cleaned);
+// io::pbm::save(in_bw_cleaned_full, "in_bw_cleaned_full.pbm");
+
+ logical::not_inplace(in_bw_cleaned_full);
+ return in_bw_cleaned_full;
+ }
+
+ template <typename I>
+ mln_ch_value(I,bool)
+ get_main_object_shape(const Image<I>& in)
+ {
+ using namespace mln;
+
+ typedef image2d<bool> J;
+
+// threshold f;
+// J in_bw = binarization::binarization(in, f);
+// io::pbm::save(in_bw, "01_in_bw.pbm");
+
+// J ima = keep_largest_component(in_bw);
+ J ima = keep_largest_component(in);
+
+ std::cout << "Compute gradient" << std::endl;
+ J ima_grad = morpho::gradient(ima, win_c4p());
+
+ return ima_grad;
+ }
+
+ //FIXME: add conversion from label_16 to bool.
+ struct to_bool : Function_v2v<to_bool>
+ {
+ typedef bool result;
+ bool operator()(const value::label_16& l) const
+ {
+ return l != 0u;
+ }
+
+ };
+
+
+ template <typename I>
+ mln_ch_value(I,bool)
+ get_cloud_image(const Image<I>& irm)
+ {
+ using namespace mln;
+ using value::int_u8;
+ using value::label_16;
+
+ window2d c4p = convert::to_window(c4());
+ c4p.insert(0,0);
+ // debug::println(convert::to_image(c4p));
+ image2d<int_u8> grad = morpho::gradient(irm, c4p);
+ io::pgm::save( grad, "tmp_grad_c4p.pgm" );
+
+ image2d<int_u8> clo;
+ initialize(clo, irm);
+
+ clo = morpho::closing_area(grad, c4(), 100);
+ io::pgm::save( clo, "tmp_clo_a100.pgm" );
+
+ label_16 nbasins;
+ image2d<label_16> wshed = morpho::meyer_wst(clo, c4(), nbasins);
+ std::cout << "nbasins = " << nbasins << std::endl;
+ io::pgm::save( level::transform(wshed, convert::to_fun(foo)),
+ "tmp_wshed.pgm" );
+
+ mln_VAR(mean_values, labeling::compute(accu::meta::mean(), irm, wshed, nbasins));
+ fun::i2v::array<label_16> to_keep(nbasins.next(), 0);
+ threshold f;
+ for (label_16 i = 1; i < mean_values.nelements(); ++i)
+ if (f(mean_values[i]))
+ to_keep(i) = i;
+
+ wshed = level::transform(wshed, to_keep);
+ io::pgm::save( level::transform(wshed, convert::to_fun(foo)),
+ "tmp_wshed_2.pgm" );
+
+ image2d<bool> wshed_bw = level::transform(wshed, to_bool());
+ image2d<bool> main_obj = get_main_object_shape(wshed_bw);
+ io::pbm::save(main_obj, "tmp_main_obj");
+
+ return main_obj;
+ }
+
+} // end of namespace mln
+
+
+int main(int, char *argv[])
+{
+ using namespace mln;
+ using value::int_u8;
+ using value::label_16;
+
+ image2d<int_u8> irm;
+ io::pgm::load(irm, argv[1]);
+
+ image2d<int_u8> irm_ref;
+ io::pgm::load(irm_ref, argv[2]);
+
+ std::cout << "compute irm" << std::endl;
+ image3d<bool> P = make::image3d(get_cloud_image(irm));
+ std::cout << "compute irm_ref" << std::endl;
+ image3d<bool> X = make::image3d(get_cloud_image(irm_ref));
+
+ std::cout << "Registration" << std::endl;
+ typedef fun::x2x::rotation<3u,float> rot_t;
+ typedef fun::x2x::translation<3u,float> trans_t;
+ typedef p_array<point3d> arr_t;
+ arr_t P_arr = convert::to<arr_t>(P);
+ arr_t X_arr = convert::to<arr_t>(X);
+ fun::x2x::composed<trans_t,rot_t> qk = registration::registration(P_arr, X_arr);
+
+
+ std::cout << "* Build result image" << std::endl;
+ image3d<value::rgb8> registered = debug::make_registered_image(P, X, qk);
+ debug::compare_registration(registered, X);
+
+
+
+ image3d<int_u8> irm_wborders = make::image3d(duplicate(irm));
+ data::fill((irm_wborders | P_arr).rw(), 255);
+ io::pgm::save(slice(irm_wborders,0), "tmp_irm_with_borders.ppm");
+
+ image3d<int_u8> ref_wborders = make::image3d(duplicate(irm_ref));
+ data::fill((ref_wborders | X_arr).rw(), 255);
+ io::pgm::save(slice(ref_wborders,0), "tmp_ref_with_borders.ppm");
+
+ debug::compare_registration2(irm_wborders, ref_wborders, qk);
+
+}
--
1.5.6.5
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Optimize the video labeling canvas.
* mln/core/concept/neighborhood.hh (negative_offsets_wrt): New.
* mln/core/concept/window.hh: Likewise.
* mln/canvas/labeling.hh (labeling): Strenghten 's' type.
Use negative_offsets_wrt.
* mln/labeling/flat_zones.hh
(flat_zones_functor): Remove useless typedef S.
Fix ctor.
(flat_zones): Fix.
* tests/labeling/flat_zones.cc: Upgrade file doc style.
Add commented bench.
Add consistency test wrt both implementations.
mln/canvas/labeling.hh | 48 +++++++++++++++++++++------------------
mln/core/concept/neighborhood.hh | 18 ++++++++++++++
mln/core/concept/window.hh | 30 ++++++++++++++++++++++++
mln/labeling/flat_zones.hh | 16 ++++---------
tests/labeling/flat_zones.cc | 47 ++++++++++++++++++++++++++++++++++----
5 files changed, 122 insertions(+), 37 deletions(-)
Index: mln/core/concept/neighborhood.hh
--- mln/core/concept/neighborhood.hh (revision 3320)
+++ mln/core/concept/neighborhood.hh (working copy)
@@ -102,6 +102,10 @@
util::array<int>
offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
+ template <typename I, typename N>
+ util::array<int>
+ negative_offsets_wrt(const Image<I>& ima, const Neighborhood<N>& nbh);
+
# ifndef MLN_INCLUDE_ONLY
@@ -160,6 +164,20 @@
return offsets_wrt(ima, nbh.win());
}
+ template <typename I, typename N>
+ util::array<int>
+ negative_offsets_wrt(const Image<I>& ima_, const Neighborhood<N>& nbh_)
+ {
+ mln_is_simple_neighborhood(N)::check();
+
+ const I& ima = exact(ima_);
+ const N& nbh = exact(nbh_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(nbh.is_valid());
+
+ return negative_offsets_wrt(ima, nbh.win());
+ }
+
# endif // ! MLN_INCLUDE_ONLY
} // end of namespace mln
Index: mln/core/concept/window.hh
--- mln/core/concept/window.hh (revision 3320)
+++ mln/core/concept/window.hh (working copy)
@@ -119,6 +119,10 @@
util::array<int>
offsets_wrt(const Image<I>& ima, const Window<W>& win);
+ template <typename I, typename W>
+ util::array<int>
+ negative_offsets_wrt(const Image<I>& ima, const Window<W>& win);
+
namespace convert
@@ -339,6 +343,32 @@
}
+ template <typename I, typename W>
+ inline
+ util::array<int>
+ negative_offsets_wrt(const Image<I>& ima_, const Window<W>& win_)
+ {
+ mln_is_simple_window(W)::check();
+
+ const I& ima = exact(ima_);
+ const W& win = exact(win_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(win.is_valid());
+
+ util::array<int> arr;
+ unsigned n = win.size();
+
+ for (unsigned i = 0; i < n; ++i)
+ {
+ int offset = ima.delta_index(win.dp(i));
+ if (offset < 0)
+ arr.append(offset);
+ }
+
+ return arr;
+ }
+
+
namespace convert
{
Index: mln/canvas/labeling.hh
--- mln/canvas/labeling.hh (revision 3320)
+++ mln/canvas/labeling.hh (working copy)
@@ -119,7 +119,7 @@
typename S, typename F>
mln_ch_value(I, L)
labeling(const Image<I>& input_, const Neighborhood<N>& nbh_, L& nlabels,
- const S& s, F& f)
+ const Site_Set<S>& s_, F& f)
{
trace::entering("canvas::impl::generic::labeling");
@@ -127,6 +127,7 @@
const I& input = exact(input_);
const N& nbh = exact(nbh_);
+ const S& s = exact(s_);
// Local type.
typedef mln_psite(I) P;
@@ -254,7 +255,7 @@
// Initialization.
{
initialize(deja_vu, input);
- mln::data::fill(deja_vu, false);
+ mln::data::fill(deja_vu, true);
extension::fill(deja_vu, false); // So that the extension is ignored.
initialize(parent, input);
@@ -268,8 +269,10 @@
// First Pass.
{
+ util::array<int> dp = negative_offsets_wrt(input, nbh);
+ const unsigned n_nbhs = dp.nelements();
+
mln_pixter(const I) px(input);
- mln_nixter(const I, N) nx(px, nbh);
for_all(px)
{
unsigned p = px.offset();
@@ -279,10 +282,10 @@
// Make-Set.
parent.element(p) = p;
f.init_attr_(p);
- for_all(nx)
+ for (unsigned i = 0; i < n_nbhs; ++i)
{
- unsigned n = nx.offset();
- if (deja_vu.element(n))
+ unsigned n = p + dp[i];
+ if (deja_vu.element(n)) // Only false in the external border.
{
if (f.equiv_(n, p))
{
@@ -298,8 +301,6 @@
f.do_no_union_(n, p);
}
}
-
- deja_vu.element(p) = true;
}
}
@@ -465,19 +466,21 @@
typename F>
inline
mln_ch_value(I, L)
- labeling_video(metal::false_, const Image<I>& input,
- const Neighborhood<N>& nbh, L& nlabels, F& functor)
+ labeling_video_dispatch(metal::false_,
+ const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels,
+ F& functor)
{
- return impl::generic::labeling(input, nbh, input.domain(),
- nlabels, functor);
+ return impl::generic::labeling(input, nbh, input.domain(), nlabels,
+ functor);
}
template <typename I, typename N, typename L,
typename F>
inline
mln_ch_value(I, L)
- labeling_video(metal::true_, const Image<I>& input,
- const Neighborhood<N>& nbh, L& nlabels, F& functor)
+ labeling_video_dispatch(metal::true_,
+ const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels,
+ F& functor)
{
return impl::labeling_video_fastest(input, nbh, nlabels, functor);
}
@@ -486,8 +489,8 @@
typename F>
inline
mln_ch_value(I, L)
- labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh,
- L& nlabels, F& functor)
+ labeling_video_dispatch(const Image<I>& input, const Neighborhood<N>& nbh, L& nlabels,
+ F& functor)
{
enum {
test = mlc_equal(mln_trait_image_speed(I),
@@ -495,8 +498,9 @@
&&
mln_is_simple_neighborhood(N)::value
};
- return labeling_video(metal::bool_<test>(), input,
- nbh, nlabels, functor);
+ return labeling_video_dispatch(metal::bool_<test>(),
+ input, nbh, nlabels,
+ functor);
}
@@ -513,8 +517,8 @@
increasing ?
level::sort_psites_increasing(input) :
level::sort_psites_decreasing(input);
- return impl::generic::labeling(input, nbh, nlabels,
- s, functor);
+ return impl::generic::labeling(input, nbh, nlabels, s,
+ functor);
}
template <typename I, typename N, typename L, typename F>
@@ -528,8 +532,8 @@
increasing ?
level::sort_offsets_increasing(input) :
level::sort_offsets_decreasing(input);
- return impl::labeling_sorted_fastest(input, nbh, nlabels,
- s, functor);
+ return impl::labeling_sorted_fastest(input, nbh, nlabels, s,
+ functor);
}
template <typename I, typename N, typename L, typename F>
Index: mln/labeling/flat_zones.hh
--- mln/labeling/flat_zones.hh (revision 3320)
+++ mln/labeling/flat_zones.hh (working copy)
@@ -67,16 +67,12 @@
template <typename I>
struct flat_zones_functor
{
- typedef mln_psite(I) P;
-
- // Requirements from mln::canvas::labeling:
-
- typedef mln_pset(I) S;
-
const I& input;
// Generic implementation.
+ typedef mln_psite(I) P;
+
void init() {}
bool handles(const P&) const { return true; }
bool equiv(const P& n, const P& p) const { return input(n) ==
@@ -99,7 +95,7 @@
// end of requirements.
- flat_zones_functor(const I& input, const N& nbh)
+ flat_zones_functor(const I& input)
: input(input)
{}
};
@@ -122,9 +118,9 @@
const N& nbh = exact(nbh_);
mln_precondition(input.is_valid());
- // Calls the only implementation.
- typedef flat_zones_functor<I,N,L> F;
- F f(exact(input), exact(nbh));
+ // Call the labeling canvas.
+ typedef impl::flat_zones_functor<I> F;
+ F f(input);
mln_ch_value(I, L) output = canvas::labeling_video(input, nbh, nlabels, f);
trace::exiting("labeling::flat_zones");
Index: tests/labeling/flat_zones.cc
--- tests/labeling/flat_zones.cc (revision 3320)
+++ tests/labeling/flat_zones.cc (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 2007, 2008, 2009 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,11 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/*! \file tests/labeling/flat_zones.cc
- *
- * \brief Test on mln::labeling::flat_zones.
- */
+/// \file tests/labeling/flat_zones.cc
+///
+/// Test on mln::labeling::flat_zones.
+///
+/// \todo Move commented bench to the 'bench' directory.
#include <mln/core/image/image2d.hh>
#include <mln/value/int_u8.hh>
@@ -38,6 +40,7 @@
#include <mln/labeling/blobs.hh>
#include <mln/pw/all.hh>
+#include <mln/level/compare.hh>
#include "tests/data.hh"
@@ -49,11 +52,44 @@
image2d<int_u8> lena = io::pgm::load<int_u8>(MLN_IMG_DIR "/tiny.pgm");
+
+ // Bench code:
+
+// for (unsigned i = 0; i < 10; ++i)
+// {
+// typedef image2d<int_u8> I;
+// labeling::impl::flat_zones_functor<I> f(lena);
+// unsigned n;
+// canvas::impl::labeling_video_fastest(lena,
+// c4(),
+// n,
+// f);
+// }
+
+
unsigned n;
image2d<unsigned> labels = labeling::flat_zones(lena, c4(), n);
mln_assertion(n == 247);
{
+ typedef image2d<int_u8> I;
+ labeling::impl::flat_zones_functor<I> f(lena);
+
+ unsigned nlabels_generic, nlabels_fastest;
+ mln_assertion(canvas::impl::generic::labeling(lena,
+ c4(),
+ nlabels_generic,
+ lena.domain(),
+ f)
+ ==
+ canvas::impl::labeling_video_fastest(lena,
+ c4(),
+ nlabels_fastest,
+ f));
+ mln_assertion(nlabels_generic == nlabels_fastest);
+ }
+
+ {
unsigned n_ = 0;
for (unsigned i = 0; i <= 255; ++i)
{
@@ -64,4 +100,5 @@
}
mln_assertion(n_ == n);
}
+
}
1
0
URL: https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2009-02-09 Fabien Freling <freling(a)lrde.epita.fr>
Fix header inclusion of labeling.hh.
* mln/labeling/level.hh: Fix.
* mln/labeling/regional_maxima.hh: Fix.
* mln/labeling/regional_minima.hh: Fix.
---
level.hh | 4 +---
regional_maxima.hh | 4 +---
regional_minima.hh | 4 +---
3 files changed, 3 insertions(+), 9 deletions(-)
Index: trunk/milena/mln/labeling/level.hh
===================================================================
--- trunk/milena/mln/labeling/level.hh (revision 3319)
+++ trunk/milena/mln/labeling/level.hh (revision 3320)
@@ -36,9 +36,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
-
-# include "labeling.hh"
-
+# include <mln/canvas/labeling.hh>
# include <mln/data/fill.hh>
Index: trunk/milena/mln/labeling/regional_minima.hh
===================================================================
--- trunk/milena/mln/labeling/regional_minima.hh (revision 3319)
+++ trunk/milena/mln/labeling/regional_minima.hh (revision 3320)
@@ -35,9 +35,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
-
-# include "labeling.hh"
-
+# include <mln/canvas/labeling.hh>
# include <mln/data/fill.hh>
# include <mln/level/sort_psites.hh>
Index: trunk/milena/mln/labeling/regional_maxima.hh
===================================================================
--- trunk/milena/mln/labeling/regional_maxima.hh (revision 3319)
+++ trunk/milena/mln/labeling/regional_maxima.hh (revision 3320)
@@ -35,9 +35,7 @@
# include <mln/core/concept/image.hh>
# include <mln/core/concept/neighborhood.hh>
-
-# include "labeling.hh"
-
+# include <mln/canvas/labeling.hh>
# include <mln/data/fill.hh>
# include <mln/level/sort_psites.hh>
1
0