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
January 2009
- 9 participants
- 152 discussions
* mln/registration/icp2.hh: temporary version. Should be more cleaned
up in a near future.
---
milena/ChangeLog | 7 +
milena/mln/registration/icp2.hh | 230 +++++++++++++++++++++++++++++++++++++++
2 files changed, 237 insertions(+), 0 deletions(-)
create mode 100644 milena/mln/registration/icp2.hh
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 1e0bb0f..053015a 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,10 @@
+2009-01-28 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ First revamp of ICP.
+
+ * mln/registration/icp2.hh: temporary version. Should be more cleaned
+ up in a near future.
+
2009-01-28 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a maker of image3d from an array of 2D images.
diff --git a/milena/mln/registration/icp2.hh b/milena/mln/registration/icp2.hh
new file mode 100644
index 0000000..e077b4e
--- /dev/null
+++ b/milena/mln/registration/icp2.hh
@@ -0,0 +1,230 @@
+// 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_REGISTRATION_ICP_HH
+# define MLN_REGISTRATION_ICP_HH
+
+/// \file mln/registration/icp.hh
+///
+/// Register an image over an another using the ICP algorithm.
+
+# include <mln/fun/x2x/all.hh>
+# include <mln/fun/x2v/all.hh>
+# include <mln/convert/to.hh>
+# include <mln/transform/internal/closest_point_functor.hh>
+# include <mln/canvas/distance_geodesic.hh>
+# include <mln/accu/compute.hh>
+# include <mln/accu/center.hh>
+
+namespace mln
+{
+
+ namespace registration
+ {
+
+ using namespace fun::x2x;
+
+ /*! Register point in \p c using a map of closest points \p map
+ *
+ * \param[in] c The cloud of points.
+ * \param[in] map The map of closest points.
+ * \param[in] epsilon ICP stops if sqr_norm(qk - qk-1) /
+ * sqr_norm(qk) > epsilon
+ * \param[out] qk The rigid transformation obtained.
+ *
+ * \pre \p ima has to be initialized.
+ */
+ template <typename D, typename M, typename T>
+ void
+ icp(const Image<D>& data, const Image<M>& model, T& qk);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P, typename C, typename T>
+ inline
+ float
+ compute_d_k(const p_array<P>& data_P,
+ const C& cp_X,
+ const T& qk,
+ const T& qk_next)
+ {
+ float f = 0.f;
+ mln_piter(p_array<P>) p(data_P);
+ for_all(p)
+ {
+ // yk_i - pk+1_i
+ f += norm::l2(cp_X(qk(p.to_site().to_vec())).to_vec() - qk_next(p.to_site().to_vec()));
+ }
+ return f / data_P.nsites();
+ }
+
+ template <typename P, typename C, typename T>
+ inline
+ float
+ compute_e_k(const p_array<P>& data_P,
+ const C& cp_X,
+ const T& qk)
+ {
+ float f = 0.f;
+ mln_piter(p_array<P>) p(data_P);
+ for_all(p)
+ {
+ // yk_i - pk_i
+ f += norm::l2(cp_X(qk(p.to_site().to_vec())).to_vec() - qk(p.to_site().to_vec()));
+ }
+ return f / data_P.nsites();
+ }
+
+
+ template <typename P, typename T>
+ fun::x2x::rotation<3u, float>
+ get_rot(const p_array<P>& data_P,
+ const algebra::vec<3u,float>& mu_P,
+ const algebra::vec<3u,float>& mu_Yk,
+ const T& qk)
+ {
+ // FIXME: Make use of a cross_covariance accu (maybe not because of map(ck[i]))
+ algebra::mat<3u,3u,float> Mk;
+ mln_piter(p_array<P>) p(data_P);
+ for_all(p)
+ {
+ algebra::vec<3u,float> P_i = p.to_site().to_vec();
+ algebra::vec<3u,float> Yk_i = qk(p.to_site().to_vec());
+ Mk += make::mat(P_i - mu_P) * trans(make::mat(Yk_i - mu_Yk));
+ }
+ Mk /= data_P.nsites();
+
+ algebra::vec<3u,float> A;
+ A[0] = Mk(1,2) - Mk(2,1);
+ A[1] = Mk(2,0) - Mk(0,2);
+ A[2] = Mk(0,1) - Mk(1,0);
+
+ algebra::mat<4u,4u,float> Qk;
+ float t = tr(Mk);
+
+ Qk(0,0) = t;
+ for (int i = 1; i < 4; i++)
+ {
+ Qk(i,0) = A[i - 1];
+ Qk(0,i) = A[i - 1];
+ for (int j = 1; j < 4; j++)
+ if (i == j)
+ Qk(i,j) = 2 * Mk(i - 1,i - 1) - t;
+ }
+
+ Qk(1,2) = Mk(0,1) + Mk(1,0);
+ Qk(2,1) = Mk(0,1) + Mk(1,0);
+
+ Qk(1,3) = Mk(0,2) + Mk(2,0);
+ Qk(3,1) = Mk(0,2) + Mk(2,0);
+
+ Qk(2,3) = Mk(1,2) + Mk(2,1);
+ Qk(3,2) = Mk(1,2) + Mk(2,1);
+
+ algebra::quat qR = math::jacobi(Qk);
+
+ return fun::x2x::rotation<3u, float>(qR);
+ }
+
+
+
+ template <typename P, typename C, typename T>
+ T
+ get_transformation(const p_array<P>& data_P,
+ const algebra::vec<P::dim,float>& mu_P,
+ const C& cp_X,
+ const T& qk)
+ {
+ algebra::vec<P::dim,float> mu_Yk;
+
+ // Compute mu_Yk, mass center of Yk.
+ mln_piter(p_array<P>) p(data_P);
+ for_all(p)
+ mu_Yk += cp_X(qk(p.to_site().to_vec())).to_vec();
+ mu_Yk /= data_P.nsites();
+
+ // qR
+ rotation<P::dim, float> tqR = get_rot(data_P, mu_P, mu_Yk, qk);
+
+ // qT
+ const algebra::vec<P::dim,float> qT = mu_Yk - tqR(mu_P);
+ translation<P::dim, float> tqT(qT);
+
+ return compose(tqR, tqT);
+ }
+
+
+ template <typename D, typename M, typename T>
+ inline
+ void
+ icp(const Image<D>& data, const Image<M>& model_X, T& qk)
+ {
+ trace::entering("registration::icp");
+
+ typedef mln_psite(M) P;
+ typedef p_array<P> cloud_t;
+
+ cloud_t data_P = convert::to<cloud_t>(exact(data));
+
+ // Compute distance map and closest point image.
+ transform::internal::closest_point_functor<M> f;
+ typedef mln_ch_value(M,value::int_u16) I;
+ I dmap_X = canvas::distance_geodesic(model_X, c6(),
+ mln_max(value::int_u16), f);
+
+ const mln_ch_value(M, P)& cp_X = f.cp_ima;
+
+ algebra::vec<P::dim,float> mu_P = set::compute(accu::meta::center(),
+ exact(data).domain()).to_vec();
+
+ float d_k_prev = 0, d_k = mln_max(float);
+ float e_k_prev = 0, e_k = mln_max(float);
+ do
+ {
+ d_k_prev = d_k;
+ e_k_prev = e_k;
+
+ //compute qk
+ T qk_next = get_transformation(data_P, mu_P, cp_X, qk);
+
+ d_k = compute_d_k(data_P, cp_X, qk, qk_next);
+ std::cout << d_k << std::endl;
+ e_k = compute_e_k(data_P, cp_X, qk);
+
+ qk = qk_next;
+ } while ((d_k_prev - d_k) >= 1e-3);
+
+ trace::exiting("registration::icp");
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::registration
+
+} // end of namespace mln
+
+#endif // ! MLN_REGISTRATION_ICP_HH
--
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>
Add a maker of image3d from an array of 2D images.
* mln/trait/concrete.hh: Upgrade file doc style.
(mon_concrete_): New macro.
* mln/core/image/slice_image.hh (ch_value): New specialization.
* mln/make/image2d.hh (todo): New.
* mln/make/image3d.hh: New.
* mln/make/all.hh: Update.
* tests/make/image3d.cc: New.
* tests/make/Makefile.am: Update.
mln/core/image/slice_image.hh | 14 ++++++
mln/make/all.hh | 1
mln/make/image2d.hh | 3 +
mln/make/image3d.hh | 90 ++++++++++++++++++++++++++++++++++++++++++
mln/trait/concrete.hh | 12 +++--
tests/make/Makefile.am | 2
tests/make/image3d.cc | 54 +++++++++++++++++++++++++
7 files changed, 171 insertions(+), 5 deletions(-)
Index: mln/trait/concrete.hh
--- mln/trait/concrete.hh (revision 3215)
+++ mln/trait/concrete.hh (working copy)
@@ -1,4 +1,5 @@
-// Copyright (C) 2007 EPITA Research and Development Laboratory
+// Copyright (C) 2007, 2008 EPITA Research and Development Laboratory
+// (LRDE)
//
// This file is part of the Olena Library. This library is free
// software; you can redistribute it and/or modify it under the terms
@@ -28,15 +29,16 @@
#ifndef MLN_TRAIT_CONCRETE_HH
# define MLN_TRAIT_CONCRETE_HH
-/*! \file mln/trait/concrete.hh
- *
- * \brief Definition of the concrete image trait.
- */
+/// \file mln/trait/concrete.hh
+///
+/// Definition of the concrete image trait.
# include <mln/trait/ch_value.hh>
# define mln_concrete(I) typename mln::trait::concrete< I >::ret
+# define mln_concrete_(I) mln::trait::concrete< I >::ret
+
# define mln_concrete_ch_value(I, V) mln_ch_value(mln_concrete(I), V)
Index: mln/core/image/slice_image.hh
--- mln/core/image/slice_image.hh (revision 3215)
+++ mln/core/image/slice_image.hh (working copy)
@@ -132,6 +132,20 @@
+
+ namespace trait
+ {
+
+ template <typename I, typename V>
+ struct ch_value< slice_image<I>, V >
+ {
+ typedef image2d<V> ret;
+ };
+
+ } // end of namespace mln::trait
+
+
+
# ifndef MLN_INCLUDE_ONLY
Index: mln/make/all.hh
--- mln/make/all.hh (revision 3215)
+++ mln/make/all.hh (working copy)
@@ -51,6 +51,7 @@
# include <mln/make/graph.hh>
# include <mln/make/image.hh>
# include <mln/make/image2d.hh>
+# include <mln/make/image3d.hh>
# include <mln/make/mat.hh>
# include <mln/make/pix.hh>
# include <mln/make/pixel.hh>
Index: mln/make/image2d.hh
--- mln/make/image2d.hh (revision 3215)
+++ mln/make/image2d.hh (working copy)
@@ -31,6 +31,9 @@
/// \file mln/make/image2d.hh
///
/// Routine to create a 2D image from a 1D array.
+///
+/// \todo Think about removing make::image2d since it is redundant
+/// with convert::to and convert::from_to.
# include <mln/core/image/image2d.hh>
Index: mln/make/image3d.hh
--- mln/make/image3d.hh (revision 0)
+++ mln/make/image3d.hh (revision 0)
@@ -0,0 +1,90 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_MAKE_IMAGE3D_HH
+# define MLN_MAKE_IMAGE3D_HH
+
+/// \file mln/make/image3d.hh
+///
+/// Routine to create a 3D image from an array of 2D images.
+///
+/// \todo Think about removing make::image3d since it is redundant
+/// with convert::to and convert::from_to.
+
+# include <mln/core/image/image3d.hh>
+# include <mln/core/image/image2d.hh>
+# include <mln/core/image/slice_image.hh>
+# include <mln/data/paste.hh>
+# include <mln/util/array.hh>
+
+
+
+namespace mln
+{
+
+ namespace make
+ {
+
+ /// Create an image3d from an array of 2D images.
+ ///
+ template <typename I>
+ mln::image3d<mln_value(I)>
+ image3d(const util::array<I>& ima);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename I>
+ inline
+ mln::image3d<mln_value(I)>
+ image3d(const util::array<I>& ima)
+ {
+ mlc_is_a(mln_pset(I), Box)::check();
+ mln_precondition(! ima.is_empty());
+
+ def::coord n_slices = ima.nelements();
+ mln::box2d b = ima[0].domain();
+ mln::box3d b_ = make::box3d(0, b.pmin().row(), b.pmin().col(),
+ n_slices - 1, b.pmax().row(), b.pmax().col());
+ mln::image3d<mln_value(I)> output(b_);
+ for (def::coord sli = 0; sli < n_slices; ++sli)
+ {
+ mln_assertion(ima[sli].domain() == b);
+ data::paste(ima[sli], slice(output, sli).rw());
+ }
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::make
+
+} // end of namespace mln
+
+
+#endif // ! MLN_MAKE_IMAGE3D_HH
Index: tests/make/Makefile.am
--- tests/make/Makefile.am (revision 3215)
+++ tests/make/Makefile.am (working copy)
@@ -5,12 +5,14 @@
check_PROGRAMS = \
dual_neighb \
image2d \
+ image3d \
mat \
w_window \
w_window_directional
dual_neighb_SOURCES = dual_neighb.cc
image2d_SOURCES = image2d.cc
+image3d_SOURCES = image3d.cc
mat_SOURCES = mat.cc
w_window_SOURCES = w_window.cc
w_window_directional_SOURCES = w_window_directional.cc
Index: tests/make/image3d.cc
--- tests/make/image3d.cc (revision 0)
+++ tests/make/image3d.cc (revision 0)
@@ -0,0 +1,54 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/make/image3d.cc
+///
+/// Tests on mln::make::image3d.
+
+#include <mln/make/image3d.hh>
+#include <mln/debug/iota.hh>
+#include <mln/core/routine/duplicate.hh>
+#include <mln/level/compare.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ unsigned n_slices = 3;
+
+ image3d<int> vol(n_slices, 2, 4);
+ debug::iota(vol);
+
+ typedef image2d<int> I;
+ util::array<I> ima;
+ for (unsigned i = 0; i < n_slices; ++i)
+ ima.append( duplicate(slice(vol, i)) );
+
+ image3d<int> vol_ = make::image3d(ima);
+ mln_assertion(vol_ == vol);
+}
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add a slice morpher.
* mln/core/image/slice_image.hh: New.
* mln/core/image/all.hh: Update.
* tests/core/image/slice_image.cc: New.
* tests/core/image/Makefile.am: Update.
* tests/core/image/p2p_image.cc: Fix file doc.
mln/core/image/all.hh | 1
mln/core/image/slice_image.hh | 276 ++++++++++++++++++++++++++++++++++++++++
tests/core/image/Makefile.am | 2
tests/core/image/p2p_image.cc | 2
tests/core/image/slice_image.cc | 51 +++++++
5 files changed, 331 insertions(+), 1 deletion(-)
Index: mln/core/image/all.hh
--- mln/core/image/all.hh (revision 3214)
+++ mln/core/image/all.hh (working copy)
@@ -78,6 +78,7 @@
//# include <mln/core/image/rle_encode.hh>
//# include <mln/core/image/rle_image.hh>
# include <mln/core/image/safe.hh>
+# include <mln/core/image/slice_image.hh>
# include <mln/core/image/sparse_encode.hh>
# include <mln/core/image/sparse_image.hh>
# include <mln/core/image/sub_image.hh>
Index: mln/core/image/slice_image.hh
--- mln/core/image/slice_image.hh (revision 0)
+++ mln/core/image/slice_image.hh (revision 0)
@@ -0,0 +1,276 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_SLICE_IMAGE_HH
+# define MLN_CORE_IMAGE_SLICE_IMAGE_HH
+
+/// \file mln/core/image/slice_image.hh
+///
+/// Definition of an image FIXME: Doc!
+///
+/// \todo Write init_.
+
+# include <mln/core/internal/image_domain_morpher.hh>
+# include <mln/core/alias/box3d.hh>
+# include <mln/core/alias/box2d.hh>
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I> struct slice_image;
+
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::slice_image<I>.
+ template <typename I>
+ struct data< slice_image<I> >
+ {
+ data(I& ima, def::coord sli);
+
+ I ima_;
+ def::coord sli_;
+ box2d b_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I>
+ struct image_< slice_image<I> > : default_image_morpher< I,
+ mln_value(I),
+ slice_image<I> >
+ {
+ typedef trait::image::category::domain_morpher category;
+
+ typedef trait::image::dimension::two_d dimension;
+
+// typedef trait::image::ext_domain::none ext_domain; // No extension of domain.
+// typedef trait::image::ext_value::irrelevant ext_value;
+// typedef trait::image::ext_io::irrelevant ext_io;
+
+ typedef trait::image::vw_io::none vw_io;
+ typedef trait::image::vw_set::none vw_set;
+ typedef trait::image::value_alignement::not_aligned value_alignement;
+ typedef trait::image::value_storage::disrupted value_storage;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ /// FIXME: Doc!
+ template <typename I>
+ struct slice_image : public internal::image_domain_morpher< I,
+ box2d,
+ slice_image<I> >
+ {
+ /// Skeleton.
+ typedef slice_image< tag::image_<I> > skeleton;
+
+ /// Constructor without argument.
+ slice_image();
+
+ /// Constructor from an image \p ima and a predicate \p f.
+ slice_image(I& ima, def::coord sli);
+
+ void init_(I& ima, def::coord sli);
+
+
+ /// Give the definition domain.
+ const box2d& domain() const;
+
+ /// Give the slice number.
+ def::coord sli() const;
+
+ /// Read-only access to the image value located at point \p p.
+ mln_rvalue(I) operator()(const point2d& p) const;
+
+ /// Read-write access to the image value located at point \p p.
+ mln_morpher_lvalue(I) operator()(const point2d& p);
+ };
+
+
+
+ template <typename I>
+ slice_image<I>
+ slice(Image<I>& ima, def::coord sli);
+
+ template <typename I>
+ slice_image<const I>
+ slice(const Image<I>& ima, def::coord sli);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+
+// // init_.
+
+// template <typename I, typename J>
+// void init_(tag::image_t, slice_image<I>& target, const J& model)
+// {
+// I ima;
+// init_(tag::image, ima, exact(model));
+// def::coord sli;
+// // FIXME
+// // init_(tag::???, sli, exact(model));
+// target.init_(ima, sli);
+// }
+
+
+ // internal::data< slice_image<I> >
+
+ namespace internal
+ {
+
+ template <typename I>
+ inline
+ data< slice_image<I> >::data(I& ima, def::coord sli)
+ : ima_(ima),
+ sli_(sli)
+ {
+ b_ = make::box2d(ima.domain().pmin().row(), ima.domain().pmin().col(),
+ ima.domain().pmax().row(), ima.domain().pmax().col());
+ }
+
+ }
+
+
+ // slice_image<I>
+
+ template <typename I>
+ inline
+ slice_image<I>::slice_image()
+ {
+ }
+
+ template <typename I>
+ inline
+ slice_image<I>::slice_image(I& ima, def::coord sli)
+ {
+ init_(ima, sli);
+ }
+
+ template <typename I>
+ inline
+ void
+ slice_image<I>::init_(I& ima, def::coord sli)
+ {
+ mln_precondition(! this->is_valid());
+ this->data_ = new internal::data< slice_image<I> >(ima, sli);
+ }
+
+ template <typename I>
+ inline
+ const box2d&
+ slice_image<I>::domain() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->b_;
+ }
+
+ template <typename I>
+ inline
+ def::coord
+ slice_image<I>::sli() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->sli_;
+ }
+
+ template <typename I>
+ inline
+ mln_rvalue(I)
+ slice_image<I>::operator()(const point2d& p) const
+ {
+ mln_precondition(this->has(p));
+ point3d p_(this->data_->sli_, p.row(), p.col());
+ mln_precondition(this->data_->ima_.has(p_));
+ return this->data_->ima_(p_);
+ }
+
+ template <typename I>
+ inline
+ mln_morpher_lvalue(I)
+ slice_image<I>::operator()(const point2d& p)
+ {
+ mln_precondition(this->has(p));
+ point3d p_(this->data_->sli_, p.row(), p.col());
+ mln_precondition(this->data_->ima_.has(p_));
+ return this->data_->ima_(p_);
+ }
+
+
+ // Routines.
+
+ template <typename I>
+ inline
+ slice_image<I>
+ slice(Image<I>& ima_, def::coord sli)
+ {
+ mlc_equal(mln_pset(I), box3d)::check();
+
+ I& ima = exact(ima_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(sli >= ima.domain().pmin().sli() &&
+ sli <= ima.domain().pmax().sli());
+
+ slice_image<I> tmp(ima, sli);
+ return tmp;
+ }
+
+ template <typename I>
+ inline
+ slice_image<const I>
+ slice(const Image<I>& ima_, def::coord sli)
+ {
+ mlc_equal(mln_pset(I), box3d)::check();
+
+ I& ima = exact(ima_);
+ mln_precondition(ima.is_valid());
+ mln_precondition(sli >= ima.domain().pmin().sli() &&
+ sli <= ima.domain().pmax().sli());
+
+ slice_image<I> tmp(ima, sli);
+ return tmp;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+
+#endif // ! MLN_CORE_IMAGE_SLICE_IMAGE_HH
Index: tests/core/image/slice_image.cc
--- tests/core/image/slice_image.cc (revision 0)
+++ tests/core/image/slice_image.cc (revision 0)
@@ -0,0 +1,51 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/core/image/slice_image.cc
+///
+/// Tests on mln::slice_image.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image3d.hh>
+#include <mln/core/image/slice_image.hh>
+
+#include <mln/debug/iota.hh>
+#include <mln/level/compare.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ image3d<int> ima(3, 2, 4);
+
+ for (def::coord s = 0; s < 3; ++s)
+ debug::iota(slice(ima, s).rw());
+
+ mln_assertion( slice(ima, 1) == slice(ima, 0) );
+ mln_assertion( slice(ima, 2) == slice(ima, 0) );
+}
Index: tests/core/image/p2p_image.cc
--- tests/core/image/p2p_image.cc (revision 3214)
+++ tests/core/image/p2p_image.cc (working copy)
@@ -25,7 +25,7 @@
// reasons why the executable file might be covered by the GNU General
// Public License.
-/// \file tests/core/image/image2d.cc
+/// \file tests/core/image/p2p_image.cc
///
/// Tests on mln::p2p_image.
Index: tests/core/image/Makefile.am
--- tests/core/image/Makefile.am (revision 3214)
+++ tests/core/image/Makefile.am (working copy)
@@ -25,6 +25,7 @@
plain \
## rle_image \
safe_image \
+ slice_image \
## sparse_image \
sub_image \
t_image \
@@ -54,6 +55,7 @@
plain_SOURCES = plain.cc
##rle_image_SOURCES = rle_image.cc
safe_image_SOURCES = safe_image.cc
+slice_image_SOURCES = slice_image.cc
##sparse_image_SOURCES = sparse_image.cc
sub_image_SOURCES = sub_image.cc
t_image_SOURCES = t_image.cc
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Add fun p2p translation and p2p_image morpher.
* mln/core/image/p2p_image.hh: New.
* mln/core/image/all.hh: Update.
* mln/fun/p2p/all.hh: New.
* mln/fun/p2p/mirror.hh (endif): Fix comment style.
* mln/fun/p2p/translation.hh: New.
* tests/core/image/p2p_image.cc: New.
* tests/core/image/Makefile.am: Update.
* tests/fun/p2p: New.
* tests/fun/p2p/translation.cc: New.
* tests/fun/p2p/Makefile.am: New.
* tests/fun/Makefile.am: Update.
* mln/core/image/image_if.hh (undef): Fix, i.e., remove.
mln/core/image/all.hh | 1
mln/core/image/image_if.hh | 3
mln/core/image/p2p_image.hh | 274 ++++++++++++++++++++++++++++++++++++++++++
mln/fun/p2p/all.hh | 53 ++++++++
mln/fun/p2p/mirror.hh | 2
mln/fun/p2p/translation.hh | 116 +++++++++++++++++
tests/core/image/Makefile.am | 2
tests/core/image/p2p_image.cc | 60 +++++++++
tests/fun/Makefile.am | 2
tests/fun/p2p/Makefile.am | 10 +
tests/fun/p2p/translation.cc | 44 ++++++
11 files changed, 562 insertions(+), 5 deletions(-)
Index: mln/core/image/image_if.hh
--- mln/core/image/image_if.hh (revision 3213)
+++ mln/core/image/image_if.hh (working copy)
@@ -264,7 +264,4 @@
} // end of namespace mln
-# undef Super
-
-
#endif // ! MLN_CORE_IMAGE_IMAGE_IF_HH
Index: mln/core/image/p2p_image.hh
--- mln/core/image/p2p_image.hh (revision 0)
+++ mln/core/image/p2p_image.hh (revision 0)
@@ -0,0 +1,274 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_CORE_IMAGE_P2P_IMAGE_HH
+# define MLN_CORE_IMAGE_P2P_IMAGE_HH
+
+/// \file mln/core/image/p2p_image.hh
+///
+/// Definition of a image FIXME: Doc!
+
+# include <mln/core/internal/image_domain_morpher.hh>
+# include <mln/core/concept/function.hh>
+# include <mln/accu/bbox.hh>
+
+
+namespace mln
+{
+
+ // Forward declaration.
+ template <typename I, typename F> struct p2p_image;
+
+
+ namespace internal
+ {
+
+ /// Data structure for \c mln::p2p_image<I,F>.
+ template <typename I, typename F>
+ struct data< p2p_image<I,F> >
+ {
+ data(I& ima, const F& f);
+
+ I ima_;
+ F f_;
+ mln_pset(I) b_;
+ };
+
+ } // end of namespace mln::internal
+
+
+ namespace trait
+ {
+
+ template <typename I, typename F>
+ struct image_< p2p_image<I,F> > : default_image_morpher< I,
+ mln_value(I),
+ p2p_image<I,F> >
+ {
+ typedef trait::image::category::domain_morpher category;
+
+ typedef trait::image::ext_domain::none ext_domain; // No extension of domain.
+ typedef trait::image::ext_value::irrelevant ext_value;
+ typedef trait::image::ext_io::irrelevant ext_io;
+
+ typedef trait::image::vw_io::none vw_io;
+ typedef trait::image::vw_set::none vw_set;
+ typedef trait::image::value_alignement::not_aligned value_alignement;
+ typedef trait::image::value_storage::disrupted value_storage;
+ };
+
+ } // end of namespace mln::trait
+
+
+
+ /// FIXME: Doc!
+ template <typename I, typename F>
+ struct p2p_image : public internal::image_domain_morpher< I,
+ mln_pset(I),
+ p2p_image<I, F> >
+ {
+ /// Skeleton.
+ typedef p2p_image< tag::image_<I>, tag::function_<F> > skeleton;
+
+ /// Constructor without argument.
+ p2p_image();
+
+ /// Constructor from an image \p ima and a predicate \p f.
+ p2p_image(I& ima, const F& f);
+
+ void init_(I& ima, const F& f);
+
+ /// Give the definition domain.
+ const mln_pset(I)& domain() const;
+
+ /// Give the p2p function.
+ const F& fun() const;
+
+ /// Read-only access to the image value located at point \p p.
+ mln_rvalue(I) operator()(const mln_psite(I)& p) const;
+
+ /// Read-write access to the image value located at point \p p.
+ mln_morpher_lvalue(I) operator()(const mln_psite(I)& p);
+ };
+
+
+
+ /// FIXME: Doc!
+ template <typename I, typename F>
+ p2p_image<I,F>
+ apply_p2p(Image<I>& ima, const Function_p2p<F>& f);
+
+ /// FIXME: Doc!
+ template <typename I, typename F>
+ p2p_image<const I,F>
+ apply_p2p(const Image<I>& ima, const Function_p2p<F>& f);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ // init_.
+
+ template <typename I, typename F>
+ void init_(tag::function_t, F& f, const p2p_image<I,F>& model)
+ {
+ f = model.fun();
+ }
+
+ template <typename I, typename F, typename J>
+ void init_(tag::image_t, p2p_image<I,F>& target, const J& model)
+ {
+ I ima;
+ init_(tag::image, ima, exact(model));
+ F f;
+ init_(tag::function, f, exact(model));
+ target.init_(ima, f);
+ }
+
+ // internal::data< p2p_image<I,F> >
+
+ namespace internal
+ {
+
+ template <typename I, typename F>
+ inline
+ data< p2p_image<I,F> >::data(I& ima, const F& f)
+ : ima_(ima),
+ f_(f)
+ {
+ accu::bbox<mln_site(I)> a;
+ mln_pset(I) b = ima.domain();
+ a.take(f(b.pmin()));
+ a.take(f(b.pmax()));
+ b_ = a.to_result();
+ mln_invariant(b_.nsites() == b.nsites());
+ }
+
+ }
+
+
+ // p2p_image<I,F>
+
+ template <typename I, typename F>
+ inline
+ p2p_image<I,F>::p2p_image()
+ {
+ }
+
+ template <typename I, typename F>
+ inline
+ p2p_image<I,F>::p2p_image(I& ima, const F& f)
+ {
+ init_(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ void
+ p2p_image<I,F>::init_(I& ima, const F& f)
+ {
+ mln_precondition(! this->is_valid());
+ this->data_ = new internal::data< p2p_image<I,F> >(ima, f);
+ }
+
+ template <typename I, typename F>
+ inline
+ const mln_pset(I)&
+ p2p_image<I,F>::domain() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->b_;
+ }
+
+ template <typename I, typename F>
+ inline
+ const F&
+ p2p_image<I,F>::fun() const
+ {
+ mln_precondition(this->is_valid());
+ return this->data_->f_;
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_rvalue(I)
+ p2p_image<I,F>::operator()(const mln_psite(I)& p) const
+ {
+ mln_precondition(this->has(p));
+ mln_invariant(this->data_->ima_.has(this->data_->f_.inverse(p)));
+ return this->data_->ima_(this->data_->f_.inverse(p));
+ }
+
+ template <typename I, typename F>
+ inline
+ mln_morpher_lvalue(I)
+ p2p_image<I,F>::operator()(const mln_psite(I)& p)
+ {
+ mln_precondition(this->has(p));
+ mln_invariant(this->data_->ima_.has(this->data_->f_.inverse(p)));
+ return this->data_->ima_(this->data_->f_.inverse(p));
+ }
+
+
+ // Routines.
+
+ template <typename I, typename F>
+ inline
+ p2p_image<I,F>
+ apply_p2p(Image<I>& ima_, const Function_p2p<F>& f)
+ {
+ mlc_is_a(mln_pset(I), Box)::check();
+
+ I& ima = exact(ima_);
+ mln_precondition(ima.is_valid());
+
+ p2p_image<I,F> tmp(ima, exact(f));
+ return tmp;
+ }
+
+ template <typename I, typename F>
+ inline
+ p2p_image<const I, F>
+ apply_p2p(const Image<I>& ima_, const Function_p2p<F>& f)
+ {
+ mlc_is_a(mln_pset(I), Box)::check();
+
+ const I& ima = exact(ima_);
+ mln_precondition(ima.is_valid());
+
+ p2p_image<const I, F> tmp(ima, exact(f));
+ return tmp;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+} // end of namespace mln
+
+
+
+#endif // ! MLN_CORE_IMAGE_P2P_IMAGE_HH
Index: mln/core/image/all.hh
--- mln/core/image/all.hh (revision 3213)
+++ mln/core/image/all.hh (working copy)
@@ -73,6 +73,7 @@
//# include <mln/core/image/mono_rle_image.hh>
//# include <mln/core/image/obased_rle_encode.hh>
//# include <mln/core/image/obased_rle_image.hh>
+# include <mln/core/image/p2p_image.hh>
# include <mln/core/image/plain.hh>
//# include <mln/core/image/rle_encode.hh>
//# include <mln/core/image/rle_image.hh>
Index: mln/fun/p2p/all.hh
--- mln/fun/p2p/all.hh (revision 0)
+++ mln/fun/p2p/all.hh (revision 0)
@@ -0,0 +1,53 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_P2P_ALL_HH
+# define MLN_FUN_P2P_ALL_HH
+
+/// \file mln/fun/p2p/all.hh
+///
+/// File that includes all functions from grid point to grid point.
+
+
+namespace mln
+{
+ namespace fun
+ {
+
+ /// Namespace of functions from grid point to grid point.
+ namespace p2p
+ {}
+
+ }
+}
+
+
+# include <mln/fun/p2p/mirror.hh>
+# include <mln/fun/p2p/translation.hh>
+
+
+#endif // ! MLN_FUN_P2P_ALL_HH
Index: mln/fun/p2p/mirror.hh
--- mln/fun/p2p/mirror.hh (revision 3213)
+++ mln/fun/p2p/mirror.hh (working copy)
@@ -87,5 +87,5 @@
} // end of namespace mln
-#endif /* MLN_FUN_P2P_MIRROR_HH */
+#endif // ! MLN_FUN_P2P_MIRROR_HH
Index: mln/fun/p2p/translation.hh
--- mln/fun/p2p/translation.hh (revision 0)
+++ mln/fun/p2p/translation.hh (revision 0)
@@ -0,0 +1,116 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+// (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_FUN_P2P_TRANSLATION_HH
+# define MLN_FUN_P2P_TRANSLATION_HH
+
+/// \file mln/fun/p2p/translation.hh
+///
+/// FIXME: doc
+
+# include <mln/core/concept/function.hh>
+
+
+namespace mln
+{
+
+ namespace fun
+ {
+
+ namespace p2p
+ {
+
+ template <typename P>
+ struct translation_t : public Function_p2p< translation_t<P> >
+ {
+ typedef P result;
+
+ translation_t(const mln_delta(P)& dp);
+
+ P operator()(const P& p) const;
+ P inverse(const P& p) const;
+
+ protected:
+ mln_delta(P) dp_;
+ };
+
+
+ template <typename D>
+ translation_t<mln_site(D)>
+ translation(const Gdpoint<D>& dp);
+
+
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <typename P>
+ inline
+ translation_t<P>::translation_t(const mln_delta(P)& dp)
+ : dp_(dp)
+ {
+ }
+
+ template <typename P>
+ inline
+ P
+ translation_t<P>::operator()(const P& p) const
+ {
+ return p + dp_;
+ }
+
+ template <typename P>
+ inline
+ P
+ translation_t<P>::inverse(const P& p) const
+ {
+ return p - dp_;
+ }
+
+
+ template <typename D>
+ inline
+ translation_t<mln_site(D)>
+ translation(const Gdpoint<D>& dp)
+ {
+ translation_t<mln_site(D)> tmp(exact(dp));
+ return tmp;
+ }
+
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::fun::p2p
+
+ } // end of namespace mln::fun
+
+} // end of namespace mln
+
+
+#endif // ! MLN_FUN_P2P_TRANSLATION_HH
+
+
Index: tests/core/image/p2p_image.cc
--- tests/core/image/p2p_image.cc (revision 0)
+++ tests/core/image/p2p_image.cc (revision 0)
@@ -0,0 +1,60 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/core/image/image2d.cc
+///
+/// Tests on mln::p2p_image.
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/p2p_image.hh>
+#include <mln/fun/p2p/translation.hh>
+
+#include <mln/debug/iota.hh>
+
+
+
+# define ima_ apply_p2p(ima, fun::p2p::translation(dp))
+
+
+
+int main()
+{
+ using namespace mln;
+
+ box2d b = make::box2d(0,0, 2,2);
+ image2d<int> ima(b, 0); // No border.
+
+ debug::iota(ima);
+
+ dpoint2d dp(-1,+1);
+ box2d b_ = make::box2d(-1,+1, 1,3);
+
+ mln_assertion( ima_.domain() == b_ );
+
+ mln_assertion( ima_(point2d(-1,+1)) == 1 );
+ mln_assertion( ima_(point2d( 1, 3)) == 9 );
+}
Index: tests/core/image/Makefile.am
--- tests/core/image/Makefile.am (revision 3213)
+++ tests/core/image/Makefile.am (working copy)
@@ -21,6 +21,7 @@
## mono_obased_rle_image \
## mono_rle_image \
## obased_rle_image \
+ p2p_image \
plain \
## rle_image \
safe_image \
@@ -49,6 +50,7 @@
##mono_obased_rle_image_SOURCES = mono_obased_rle_image.cc
##mono_rle_image_SOURCES = mono_rle_image.cc
##obased_rle_image_SOURCES = obased_rle_image.cc
+p2p_image_SOURCES = p2p_image.cc
plain_SOURCES = plain.cc
##rle_image_SOURCES = rle_image.cc
safe_image_SOURCES = safe_image.cc
Index: tests/fun/p2p/translation.cc
--- tests/fun/p2p/translation.cc (revision 0)
+++ tests/fun/p2p/translation.cc (revision 0)
@@ -0,0 +1,44 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/// \file tests/fun/p2p/translation.cc
+///
+/// Tests on mln::fun::p2p::translation.
+
+#include <mln/core/alias/point2d.hh>
+#include <mln/fun/p2p/translation.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ point2d p(0,0);
+ dpoint2d dp(-1,+1);
+
+ mln_invariant(fun::p2p::translation(dp)(p) == point2d(-1,+1));
+}
Index: tests/fun/p2p/Makefile.am
--- tests/fun/p2p/Makefile.am (revision 0)
+++ tests/fun/p2p/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 = \
+ translation
+
+translation_SOURCES = translation.cc
+
+TESTS = $(check_PROGRAMS)
Index: tests/fun/Makefile.am
--- tests/fun/Makefile.am (revision 3213)
+++ tests/fun/Makefile.am (working copy)
@@ -2,4 +2,4 @@
include $(top_srcdir)/milena/tests/tests.mk
-SUBDIRS = i2v p2b p2v v2v vv2v x2x
+SUBDIRS = i2v p2b p2p p2v v2v vv2v x2x
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Fix regsitration.
* mln/registration/multiscale.hh: Fix error.
* mln/registration/icp.hh: Fix call.
* mln/registration/get_rtransf.hh: Fix minor error.
fun/x2x/composed.hh | 4 ++--
registration/get_rtransf.hh | 14 ++++++++++++--
registration/icp.hh | 20 ++++++++++++++++++--
registration/multiscale.hh | 16 ++++++++++++++--
4 files changed, 46 insertions(+), 8 deletions(-)
Index: mln/registration/multiscale.hh
--- mln/registration/multiscale.hh (revision 3212)
+++ mln/registration/multiscale.hh (working copy)
@@ -40,6 +40,17 @@
namespace registration
{
+ /*! Register point in \p c using a multiscale icp algorithm
+ *
+ * \param[in] cloud Image to register
+ * \param[in] surface Image using to register onto
+ * \param[in] q Subsampling quotient
+ * \param[in] nb_it Number of registrations
+ * \param[out] The rigid transformation obtained.
+ *
+ * \pre \p cloud has to be initialized.
+ * \pre \p surface has to be initialized.
+ */
template <typename I, typename J>
inline
composed< rotation<I::psite::dim, float>, translation<I::Psite::dim, float> >
@@ -113,7 +124,7 @@
//working box
const box<mln_psite(I)> working_box =
- enlarge(bigger(geom::bbox(c), geom::bbox(x)), 100);
+ enlarge(bigger(geom::bbox(c), geom::bbox(x)), 1000); //warning 100 could be insufficient
//make a lazy_image map via function closest_point
fun::x2p::closest_point<mln_psite(I)> fun(x, working_box);
@@ -121,12 +132,13 @@
map(fun, fun.domain());
//init rigid transform qk
+ // FIXME: check qk initialisation.
composed< rotation<I::psite::dim, float>, translation<I::psite::dim, float> > qk;
//run registration
for (int e = nb_it-1; e >= 0; e--)
{
- unsigned int l = cloud.nsites() / std::pow(q, e);
+ unsigned int l = c.nsites() / std::pow(q, e);
l = (l < 1) ? 1 : l;
icp_subset(c, l, map, qk);
}
Index: mln/registration/icp.hh
--- mln/registration/icp.hh (revision 3212)
+++ mln/registration/icp.hh (working copy)
@@ -169,8 +169,18 @@
//work on a reduced version of c_
p_array<P> c = c_;
+
+ std::cout << "c_length" << c_length << std::endl;
+ std::cout << "-nsites" << c_.nsites() << std::endl;
+
+ std::cout << "bad point" << c[9100] << std::endl;
+
+ //FIXME: Use c_ and specify c_length to function using c_
c.hook_std_vector_().resize(c_length);
+ std::cout << "+nsites" << c.nsites() << std::endl;
+ std::cout << "bad point" << c[9100] << std::endl;
+
p_array<P> ck(c);
algebra::vec<P::dim,float> mu_c = center(c);
@@ -180,6 +190,7 @@
unsigned int k = 0;
do {
+ std::cout << "*------" << std::endl;
buf_dk.store(d_k);
//compute qk
@@ -196,14 +207,16 @@
k++;
//FIXME: Add matrix norm
//} while ((qk - buf_qk[1]).sqr_norm() / qk.sqr_norm() > epsilon);
- } while (d_k > epsilon);
+
+ std::cout << d_k << std::endl;
+
+ } while (d_k > 9.2);
trace::exiting("registration::impl::icp_");
}
} // end of namespace mln::registration::impl
-
template <typename P, typename M>
inline
composed<rotation<P::dim, float>, translation<P::dim, float> >
@@ -211,6 +224,9 @@
const float epsilon = 1e-3)
{
composed<rotation<P::dim, float>, translation<P::dim, float> > qk;
+
+ std::cout << " icp " << std::endl;
+
impl::icp_(c, c.nsites(), map, qk, epsilon);
return qk;
}
Index: mln/registration/get_rtransf.hh
--- mln/registration/get_rtransf.hh (revision 3212)
+++ mln/registration/get_rtransf.hh (working copy)
@@ -63,9 +63,19 @@
{
//mu_xk = center map(Ck)
algebra::vec<P::dim,float> mu_xk(literal::zero);
+
+ std::cout << c.nsites() << std::endl;
for (unsigned i = 0; i < c.nsites(); ++i)
- mu_xk += convert::to< algebra::vec<P::dim,float> >(map(
- convert::to< algebra::vec<P::dim,float> >(ck[i])));
+ {
+ if (not map.has(ck[i]))
+ {
+ std::cout << ck[i] << " " << i << std::endl;
+ }
+ else
+ mu_xk += convert::to< algebra::vec<P::dim,float> >
+ (map(convert::to< algebra::vec<P::dim,float> >(ck[i])));
+
+ }
mu_xk /= c.nsites();
// qR
Index: mln/fun/x2x/composed.hh
--- mln/fun/x2x/composed.hh (revision 3212)
+++ mln/fun/x2x/composed.hh (working copy)
@@ -87,7 +87,7 @@
/// Return the inverse function.
invert inv() const;
- protected:
+ //protected:
F f_;
G g_;
@@ -115,7 +115,7 @@
/// Set the new second transformation.
void set_second(const G& g);
- protected:
+ //protected:
F f_;
G g_;
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Ugo Jardonnet <ugo.jardonnet(a)lrde.epita.fr>
Fix igr registration.
* lazzara/igr.cc: Fix registration call.
igr.cc | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
Index: lazzara/igr.cc
--- lazzara/igr.cc (revision 3211)
+++ lazzara/igr.cc (working copy)
@@ -5,6 +5,7 @@
#include <mln/debug/colorize.hh>
#include <mln/registration/registration.hh>
+#include <mln/registration/multiscale.hh>
struct threshold : mln::Function_p2b<threshold>
{
@@ -61,7 +62,7 @@
return in_bw_cleaned_full;
}
-int main(int argc, char* argv[])
+int main(int, char* argv[])
{
using namespace mln;
using value::rgb8;
@@ -88,18 +89,28 @@
I ref;
io::ppm::load(ref, argv[2]);
J ref_bw = binarization::binarization(ref, f);
+
+ io::pbm::save(ref_bw, "ref_bw.pbm");
+
+ J surf = keep_largest_component(ref_bw);
+ J surf_grad = morpho::gradient(surf, win_c4p());
+
std::cout << "Computing registration..." << std::endl;
- J cloud = ima_grad | pw::value(ima_grad) == true;
- mln_VAR(registration, registration::registration(cloud, ref_bw));
- mln_VAR(icp, registration::icp(convert::to_p_array(cloud), ref_bw));
+ J cloud = ima_grad | pw::value(ima_grad) == true; //FIXME: cannot use pw::image with registration.
+ // mln_VAR(surface, (surf_grad | pw::value(surf_grad) == true));
+ mln_VAR(registration, registration::multiscale(cloud, surf_grad, 5, 3));
std::cout << "Build result image" << std::endl;
J res;
initialize(res, ima_grad);
- mln_piter_(J) p(ima_grad.domain());
+
+ data::fill(res, false);
+
+ mln_VAR(ig, (ima_grad | pw::value(ima_grad) == true));
+ mln_piter_(ig_t) p(ig.domain());
for_all(p)
- if (res.has(registration(p.to_site().to_vec())))
- res(registration(p.to_site().to_vec())) = ima_grad(p);
+ res(registration(p.to_site().to_vec())) = true;
+
io::pbm::save(res, "04_registered.pbm");
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update segmentation scheme.
* theo/color/segment.cc: Move some contents into...
* theo/color/segment.hh: ...this new file.
* theo/color/segment_debase.cc: New.
segment.cc | 355 --------------------------------------------
segment.hh | 431 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
segment_debase.cc | 103 ++++++++++++
3 files changed, 537 insertions(+), 352 deletions(-)
Index: theo/color/segment.hh
--- theo/color/segment.hh (revision 0)
+++ theo/color/segment.hh (revision 0)
@@ -0,0 +1,431 @@
+#include <cstdlib>
+
+#include <mln/core/var.hh>
+#include <mln/core/site_set/p_array.hh>
+
+#include <mln/data/fill.hh>
+#include <mln/util/ord.hh>
+#include <mln/make/pix.hh>
+#include <mln/debug/println.hh>
+
+#include <mln/level/sort_psites.hh>
+#include <mln/labeling/regional_minima.hh>
+#include <mln/pw/all.hh>
+
+#include <mln/morpho/tree/data.hh>
+#include <mln/morpho/closing_attribute.hh>
+
+#include "change_attributes.hh"
+
+
+
+namespace mln
+{
+
+
+ // Sorting.
+
+
+ template <typename I>
+ struct my_less_
+ {
+ const I& ima_;
+
+ inline
+ my_less_(const I& ima)
+ : ima_(ima)
+ {
+ }
+
+ inline
+ bool operator()(const mln_site(I)& lhs,
+ const mln_site(I)& rhs) const
+ {
+ return util::ord_strict(ima_(lhs), ima_(rhs))
+ || (ima_(lhs) == ima_(rhs)
+ &&
+ util::ord_strict(lhs, rhs));
+ }
+ };
+
+
+ template <typename I, typename S>
+ p_array<mln_site(I)> my_sort_increasing(const I& ima, const S& s)
+ {
+ p_array<mln_site(I)> v;
+ convert::from_to(s, v);
+ std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
+ my_less_<I>(ima));
+ return v;
+ }
+
+
+
+
+ // Tree -> attributes (on nodes only).
+ // -----------------------------------
+
+
+
+ template <typename A, typename T>
+ inline
+ mln_ch_value(typename T::function, mln_result(A))
+ compute_attribute_on_nodes(const A& a, const T& t)
+ {
+ typedef typename T::function I;
+
+ mln_ch_value(I, A) acc;
+ mln_ch_value(I, mln_result(A)) attr;
+
+ // Initialization of 'acc'.
+ {
+ initialize(acc, t.f());
+ data::fill(acc, a); // Transfer "dynamic data" (state) of 'a'.
+ }
+
+ // Initialize every attribute with the corresponding pixel.
+ {
+ mln_piter(I) p(t.f().domain());
+ for_all(p)
+ acc(p).take_as_init(make::pix(t.f(), p));
+ }
+
+ // Propagate attribute from a site to its parent.
+ {
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (! t.is_root(p))
+ acc(t.parent(p)).take(acc(p));
+ // No back-propagation to non-node sites.
+ }
+
+
+ // Change accumulator into its result.
+ {
+ initialize(attr, acc);
+ typedef typename T::nodes_t N;
+ mln_piter(N) p(t.nodes());
+ for_all(p)
+ {
+ mln_invariant(t.is_a_node(p));
+ attr(p) = acc(p).to_result();
+ }
+ }
+
+ return attr;
+ }
+
+
+
+
+ // Tree -> nchildren (on nodes).
+ // -----------------------------
+
+
+ template <typename T>
+ inline
+ mln_ch_value(typename T::function, unsigned)
+ compute_nchildren(const T& t)
+ {
+ typedef typename T::function I;
+ mln_ch_value(I, unsigned) nchildren;
+ initialize(nchildren, t.f());
+ data::fill(nchildren, 0);
+
+ {
+ mln_fwd_piter(T) p(t.domain());
+ // Propagate attribute from a site to its parent.
+ for_all(p)
+ if (t.is_a_non_root_node(p))
+ {
+ mln_invariant(t.is_a_node(t.parent(p)));
+ ++nchildren(t.parent(p)); // so parent(p) is a node
+ }
+ }
+
+ return nchildren;
+ }
+
+
+
+
+ template <typename A, typename T, typename N>
+ inline
+ mln_concrete(typename T::function)
+ run_filter(const A& a, const T& t, const N& nbh,
+ unsigned n_objects,
+ unsigned& less,
+ mln_value(A)& lambda,
+ bool echo = false)
+ {
+ typedef typename T::function I;
+
+ unsigned n_regmins_f; // This value can be obtained while computing the attributes!
+ mln_ch_value(I, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
+ if (echo)
+ {
+ debug::println("f =", t.f());
+ debug::println("regmins(f) =", regmins_f);
+ // debug::println("par on nodes = ", t.parent_image() | t.nodes());
+ std::cout << "n regmins(f) = " << n_regmins_f << std::endl
+ << std::endl;
+ }
+ if (n_objects >= n_regmins_f)
+ {
+ std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
+ std::cout << "aborting!" << std::endl;
+ std::abort();
+ }
+
+ lambda = mln_max(mln_value(A));
+
+ mln_ch_value(I, unsigned) nchildren = compute_nchildren(t);
+ if (echo)
+ debug::println("nchildren (before) =", nchildren | t.nodes());
+
+ typedef p_array<mln_site(I)> S;
+ S s = my_sort_increasing(a, t.nodes());
+
+ const typename T::parent_t& par = t.parent_image();
+
+ unsigned count = n_regmins_f;
+ less = 0;
+
+ // For display only.
+ mln_ch_value(I, bool) filtered;
+ initialize(filtered, t.f());
+ data::fill(filtered, false);
+
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (a(p) > lambda)
+ break;
+
+ if (a(p) < lambda && par(p) != p)
+ {
+ mln_assertion(nchildren(par(p)) > 0);
+
+ filtered(p) = true; // For display only.
+
+ --nchildren(par(p));
+ if (nchildren(par(p)) != 0)
+ {
+ if (count <= n_objects)
+ {
+ ++less; // minus 1 object wrt the expected number!
+ }
+ --count;
+ if (count == n_objects)
+ {
+ lambda = a(p) + 1;
+ std::cout << "lambda = " << lambda << std::endl
+ << std::endl;
+ }
+ }
+ }
+ }
+
+ if (echo)
+ {
+ back_propagate(filtered, t);
+ debug::println("filtered =", filtered);
+ debug::println("a < lambda = ", (pw::value(a) < pw::cst(lambda)) | a.domain());
+ }
+
+
+ if (less != 0)
+ std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
+ << std::endl;
+
+ if (echo)
+ debug::println("nchildren (after) =", nchildren | t.nodes());
+
+ // Filtering.
+ mln_concrete(I) g;
+ {
+ initialize(g, t.f());
+ mln_bkd_piter(T) p(t.domain());
+ for_all(p)
+ if (t.is_a_node(p) && a(p) >= lambda)
+ g(p) = t.f(p);
+ else
+ g(p) = g(par(p));
+
+ if (echo)
+ debug::println("g =", g);
+ }
+
+ if (echo)
+ {
+ unsigned n_regmins_g;
+ mln_VAR(regmin_g, labeling::regional_minima(g, nbh, n_regmins_g));
+ debug::println( "regmin(g)", regmin_g);
+ debug::println("a | regmin(g) = ", a | (pw::value(regmin_g) != 0));
+
+ }
+
+ return g;
+ }
+
+
+
+ template <typename A, typename I, typename N>
+ void
+ test_filter(A a, mln_result(A) lambda,
+ const I& f, const I& g, const N& nbh,
+ unsigned n_objects, unsigned less,
+ bool echo = false)
+ {
+ mln_concrete(I) g_ref = morpho::closing_attribute<A>(f, nbh, lambda);
+
+ unsigned n_regmins_g_ref;
+ mln_ch_value(I, unsigned) regmin_g_ref = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
+ bool consistency = (n_regmins_g_ref + less == n_objects);
+
+ bool wrong_filtering = (g != g_ref);
+
+ if (wrong_filtering)
+ {
+ std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
+ << std::endl;
+ if (echo)
+ {
+ debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
+
+ debug::println("g_ref =", g_ref);
+ debug::println("regmin(g_ref) =", regmin_g_ref);
+ std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << std::endl;
+ }
+ }
+
+ if (consistency == false)
+ {
+ std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
+ << " n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << " n_less = " << less << std::endl
+ << " n_objects = " << n_objects << std::endl
+ << std::endl;
+
+ if (echo && ! wrong_filtering)
+ {
+ debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
+
+ debug::println("g_ref =", g_ref);
+ debug::println("regmin(g_ref) =", regmin_g_ref);
+ std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << std::endl;
+ }
+ }
+ }
+
+
+
+ // Filter facade.
+
+ template <typename F, typename N, typename A>
+ inline
+ mln_concrete(F)
+ filter(const F& f, // a "gradient" of color image
+ const N& nbh,
+ const A& a_, // an attribute
+ bool do_extinction,
+ unsigned n_objects,
+ bool echo = false)
+ {
+ typedef p_array<mln_psite(F)> S;
+ S s = level::sort_psites_decreasing(f);
+
+ typedef morpho::tree::data<F,S> tree_t;
+ tree_t t(f, s, nbh);
+
+ mln_VAR(a, compute_attribute_on_nodes(a_, t));
+ back_propagate(a, t);
+
+ if (echo)
+ {
+ debug::println("par =", t.parent_image() | t.nodes());
+ debug::println("a =", a | t.nodes());
+ debug::println("a = ", a);
+ }
+
+ if (do_extinction)
+ extinct_attributes(t, a);
+
+ if (echo)
+ debug::println("a' =", a | t.nodes());
+
+ mln_value(a_t) lambda;
+ unsigned less;
+ mln_concrete(F) g = run_filter(a, t, nbh, n_objects, // input
+ less, lambda, // output
+ echo);
+
+ if (do_extinction == false)
+ test_filter(a_, lambda, f, g, nbh,
+ n_objects, less,
+ echo);
+
+ return g;
+ }
+
+
+
+ // Granulometry.
+
+ template <typename F, typename N, typename A>
+ inline
+ void
+ gran_filter(const F& f, const N& nbh, const A& a_)
+ {
+ typedef p_array<mln_psite(F)> S;
+ S s = level::sort_psites_decreasing(f);
+
+ typedef morpho::tree::data<F,S> T;
+ T t(f, s, nbh);
+
+ mln_VAR(a, compute_attribute_on_nodes(a_, t));
+ back_propagate(a, t);
+
+
+ unsigned n_regmins_f; // This value can be obtained while computing the attributes!
+ mln_ch_value(F, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
+
+ mln_ch_value(F, unsigned) nchildren = compute_nchildren(t);
+
+ {
+
+ typedef p_array<mln_site(F)> S;
+ S s = my_sort_increasing(a, t.nodes());
+
+ const typename T::parent_t& par = t.parent_image();
+ unsigned count = n_regmins_f;
+
+ mln_fwd_piter(S) p(s);
+ p.start();
+ std::ofstream file("gran.txt");
+ file << a(p) << ' ' << count << std::endl;
+
+ for_all(p)
+ {
+ if (par(p) != p)
+ {
+ mln_assertion(nchildren(par(p)) > 0);
+ --nchildren(par(p));
+ if (nchildren(par(p)) != 0)
+ {
+ --count;
+ file << a(p) << ' ' << count << std::endl;
+ }
+ }
+ }
+ file.close();
+
+ }
+
+ }
+
+
+
+} // end of namespace mln
Index: theo/color/segment.cc
--- theo/color/segment.cc (revision 3210)
+++ theo/color/segment.cc (working copy)
@@ -1,6 +1,3 @@
-#include <cstdlib>
-
-#include <mln/core/var.hh>
#include <mln/core/image/image2d.hh>
#include <mln/core/alias/box3d.hh>
@@ -11,7 +8,6 @@
#include <mln/value/label_8.hh>
#include <mln/core/image/image_if.hh>
-#include <mln/pw/all.hh>
#include <mln/core/routine/extend.hh>
#include <mln/core/routine/duplicate.hh>
#include <mln/data/paste.hh>
@@ -23,26 +19,19 @@
#include <mln/math/diff_abs.hh>
-#include <mln/debug/println.hh>
-
#include <mln/morpho/dilation.hh>
#include <mln/morpho/erosion.hh>
-#include <mln/morpho/tree/data.hh>
#include <mln/morpho/meyer_wst.hh>
-#include <mln/morpho/closing_attribute.hh>
-
-#include <mln/core/site_set/p_array.hh>
-#include <mln/level/sort_psites.hh>
-#include <mln/labeling/regional_minima.hh>
#include <mln/accu/count.hh>
#include <mln/accu/volume.hh>
#include "sum_pix.hh"
-#include "change_attributes.hh"
+#include "segment.hh"
+
namespace mln
{
@@ -238,344 +227,6 @@
}
- // Sorting.
-
-
- template <typename I>
- struct my_less_
- {
- const I& ima_;
-
- inline
- my_less_(const I& ima)
- : ima_(ima)
- {
- }
-
- inline
- bool operator()(const mln_site(I)& lhs,
- const mln_site(I)& rhs) const
- {
- return util::ord_strict(ima_(lhs), ima_(rhs))
- || (ima_(lhs) == ima_(rhs)
- &&
- util::ord_strict(lhs, rhs));
- }
- };
-
-
- template <typename I, typename S>
- p_array<mln_site(I)> my_sort_increasing(const I& ima, const S& s)
- {
- p_array<mln_site(I)> v;
- convert::from_to(s, v);
- std::sort(v.hook_std_vector_().begin(), v.hook_std_vector_().end(),
- my_less_<I>(ima));
- return v;
- }
-
-
-
-
- // Tree -> attributes (on nodes only).
- // -----------------------------------
-
-
-
- template <typename A, typename T>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_attribute_on_nodes(const A& a, const T& t)
- {
- typedef typename T::function I;
-
- mln_ch_value(I, A) acc;
- mln_ch_value(I, mln_result(A)) attr;
-
- // Initialization of 'acc'.
- {
- initialize(acc, t.f());
- data::fill(acc, a); // Transfer "dynamic data" (state) of 'a'.
- }
-
- // Initialize every attribute with the corresponding pixel.
- {
- mln_piter(I) p(t.f().domain());
- for_all(p)
- acc(p).take_as_init(make::pix(t.f(), p));
- }
-
- // Propagate attribute from a site to its parent.
- {
- mln_fwd_piter(T) p(t.domain());
- for_all(p)
- if (! t.is_root(p))
- acc(t.parent(p)).take(acc(p));
- // No back-propagation to non-node sites.
- }
-
-
- // Change accumulator into its result.
- {
- initialize(attr, acc);
- typedef typename T::nodes_t N;
- mln_piter(N) p(t.nodes());
- for_all(p)
- {
- mln_invariant(t.is_a_node(p));
- attr(p) = acc(p).to_result();
- }
- }
-
- return attr;
- }
-
-
-
-
- // Tree -> nchildren (on nodes).
- // -----------------------------
-
-
- template <typename T>
- inline
- mln_ch_value(typename T::function, unsigned)
- compute_nchildren(const T& t)
- {
- typedef typename T::function I;
- mln_ch_value(I, unsigned) nchildren;
- initialize(nchildren, t.f());
- data::fill(nchildren, 0);
-
- {
- mln_fwd_piter(T) p(t.domain());
- // Propagate attribute from a site to its parent.
- for_all(p)
- if (t.is_a_non_root_node(p))
- {
- mln_invariant(t.is_a_node(t.parent(p)));
- ++nchildren(t.parent(p)); // so parent(p) is a node
- }
- }
-
- return nchildren;
- }
-
-
-
-
- template <typename A, typename T, typename N>
- inline
- mln_concrete(typename T::function)
- filter(const A& a, const T& t, const N& nbh,
- unsigned n_objects,
- unsigned& less,
- mln_value(A)& lambda,
- bool echo = false)
- {
- typedef typename T::function I;
-
- unsigned n_regmins_f; // This value can be obtained while computing the attributes!
- mln_ch_value(I, unsigned) regmins_f = labeling::regional_minima(t.f(), nbh, n_regmins_f);
- if (echo)
- {
- debug::println("f =", t.f());
- debug::println("regmins(f) =", regmins_f);
- // debug::println("par on nodes = ", t.parent_image() | t.nodes());
- std::cout << "n regmins(f) = " << n_regmins_f << std::endl
- << std::endl;
- }
- if (n_objects >= n_regmins_f)
- {
- std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
- std::cout << "aborting!" << std::endl;
- std::abort();
- }
-
- lambda = mln_max(mln_value(A));
-
- mln_ch_value(I, unsigned) nchildren = compute_nchildren(t);
- if (echo)
- debug::println("nchildren (before) =", nchildren | t.nodes());
-
- typedef p_array<mln_site(I)> S;
- S s = my_sort_increasing(a, t.nodes());
-
- const typename T::parent_t& par = t.parent_image();
-
- unsigned count = n_regmins_f;
- less = 0;
-
- // For display only.
- mln_ch_value(I, bool) filtered;
- initialize(filtered, t.f());
- data::fill(filtered, false);
-
- mln_fwd_piter(S) p(s);
- for_all(p)
- {
- if (a(p) < lambda && par(p) != p)
- {
- mln_assertion(nchildren(par(p)) > 0);
-
- filtered(p) = true; // For display only.
-
- --nchildren(par(p));
- if (nchildren(par(p)) != 0)
- {
- if (count <= n_objects)
- {
- ++less; // minus 1 object wrt the expected number!
- }
- --count;
- if (count == n_objects)
- {
- lambda = a(p) + 1;
- std::cout << "lambda = " << lambda << std::endl
- << std::endl;
- break; // Stop iterations.
- }
- }
- }
- }
-
- if (echo)
- {
- back_propagate(filtered, t);
- debug::println("filtered =", filtered);
- debug::println("a < lambda = ", (pw::value(a) < pw::cst(lambda)) | a.domain());
- }
-
-
- if (less != 0)
- std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
- << std::endl;
-
- if (echo)
- debug::println("nchildren (after) =", nchildren | t.nodes());
-
- // Filtering.
- mln_concrete(I) g;
- {
- initialize(g, t.f());
- mln_bkd_piter(T) p(t.domain());
- for_all(p)
- if (t.is_a_node(p) && a(p) >= lambda)
- g(p) = t.f(p);
- else
- g(p) = g(par(p));
-
- if (echo)
- debug::println("g =", g);
- }
-
- if (echo)
- {
- unsigned n_regmins_g;
- mln_VAR(regmin_g, labeling::regional_minima(g, nbh, n_regmins_g));
- debug::println( "regmin(g)", regmin_g);
- debug::println("a | regmin(g) = ", a | (pw::value(regmin_g) != 0));
-
- }
-
- return g;
- }
-
-
-
- template <typename A, typename I, typename N>
- void
- test_filter(A a, mln_result(A) lambda,
- const I& f, const I& g, const N& nbh,
- unsigned n_objects, unsigned less,
- bool echo = false)
- {
- mln_concrete(I) g_ref = morpho::closing_attribute<A>(f, nbh, lambda);
-
- unsigned n_regmins_g_ref;
- mln_ch_value(I, unsigned) regmin_g_ref = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
- bool consistency = (n_regmins_g_ref + less == n_objects);
-
- if (g != g_ref)
- {
- std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
- << std::endl;
-
- debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
-
- debug::println("g_ref =", g_ref);
- debug::println("regmin(g_ref) =", regmin_g_ref);
- std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << std::endl;
- }
-
- if (consistency == false)
- {
- std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
- << " n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << " n_less = " << less << std::endl
- << " n_objects = " << n_objects << std::endl
- << std::endl;
-
- debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
-
- debug::println("g_ref =", g_ref);
- debug::println("regmin(g_ref) =", regmin_g_ref);
- std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << std::endl;
-
- }
- }
-
-
-
- // Filter facade.
-
- template <typename F, typename N, typename A>
- inline
- mln_concrete(F)
- filter_color(const F& f, // a "gradient" of color image
- const N& nbh,
- const A& a_, // an attribute
- bool do_extinction,
- unsigned n_objects,
- bool echo = false)
- {
- typedef p_array<mln_psite(F)> S;
- S s = level::sort_psites_decreasing(f);
-
- typedef morpho::tree::data<F,S> tree_t;
- tree_t t(f, s, nbh);
-
- mln_VAR(a, compute_attribute_on_nodes(a_, t));
- back_propagate(a, t);
-
- if (echo)
- {
- debug::println("par =", t.parent_image() | t.nodes());
- debug::println("a =", a | t.nodes());
- debug::println("a = ", a);
- }
- if (do_extinction)
- extinct_attributes(t, a);
- if (echo)
- debug::println("a' =", a | t.nodes());
-
-
- mln_value(a_t) lambda;
- unsigned less;
- mln_concrete(F) g = filter(a, t, nbh, n_objects, // input
- less, lambda, // output
- echo);
-
- test_filter(a_, lambda, f, g, nbh,
- n_objects, less,
- echo);
-
- return g;
- }
-
-
} // mln
@@ -636,7 +287,7 @@
blen_image = input_;
accu::blen_pix<I> a_;
- f_t g = filter_color(f, e2e(),
+ f_t g = filter(f, e2e(),
a_, do_extinction,
n_objects,
echo);
Index: theo/color/segment_debase.cc
--- theo/color/segment_debase.cc (revision 0)
+++ theo/color/segment_debase.cc (revision 0)
@@ -0,0 +1,103 @@
+
+#include <mln/core/image/image2d.hh>
+#include <mln/core/image/image_if.hh>
+#include <mln/core/alias/neighb2d.hh>
+
+#include <mln/value/int_u8.hh>
+#include <mln/value/label_8.hh>
+#include <mln/value/rgb8.hh>
+#include <mln/literal/colors.hh>
+
+#include <mln/io/pgm/load.hh>
+#include <mln/io/ppm/save.hh>
+#include <mln/io/pgm/save.hh>
+
+#include <mln/level/convert.hh>
+
+#include <mln/morpho/elementary/gradient.hh>
+#include <mln/morpho/meyer_wst.hh>
+
+#include <mln/accu/volume.hh>
+#include "sum_pix.hh"
+
+#include "segment.hh"
+
+
+
+
+
+void usage(char* argv[])
+{
+ std::cerr << "usage: " << argv[0] << " input.pgm n extinction output.ppm echo" << std::endl;
+ std::cerr << " n >= 2" << std::endl;
+ std::cerr << " extinction = 0 (none) or 1 (effective)" << std::endl;
+ std::cerr << " echo = 0 (mute) or 1 (verbose)" << std::endl;
+ abort();
+}
+
+
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+
+ using value::int_u8;
+ using value::rgb8;
+
+
+ if (argc != 6)
+ usage(argv);
+
+
+ // Gray-level debase version.
+ // --------------------------
+
+ typedef image2d<int_u8> I;
+
+ I input;
+ io::pgm::load(input, argv[1]);
+
+ unsigned n_objects = atoi(argv[2]);
+ bool do_extinction = atoi(argv[3]);
+ bool echo = atoi(argv[5]);
+
+
+ // Neighborhood.
+ mln_VAR(nbh, c4());
+
+
+ // Changing input into 'f'.
+
+ I f = morpho::elementary::gradient(input, c4());
+ io::pgm::save(f, "temp_f.pgm");
+
+
+ // // granulometry:
+ // gran_filter(f, c4(), a_);
+
+
+
+ // accu::count< util::pix<I> > a_;
+ // accu::sum_pix< util::pix<I> > a_;
+ accu::volume<I> a_;
+
+ I g = filter(f, c4(),
+ a_, do_extinction,
+ n_objects,
+ echo);
+
+ if (echo)
+ debug::println("activity (g != f) = ", (pw::value(g) != pw::value(f)) | f.domain());
+
+
+ // Watershed transform.
+
+ typedef value::label_8 L;
+ L nbasins;
+ mln_ch_value_(I, L) w = morpho::meyer_wst(g, c4(), nbasins);
+
+ image2d<rgb8> output = level::convert(rgb8(), input);
+ data::fill((output | (pw::value(w) == 0)).rw(), literal::red);
+
+ io::ppm::save(output, argv[4]);
+}
1
0
* lazzara/igr.cc: new file.
---
milena/sandbox/ChangeLog | 6 ++
milena/sandbox/lazzara/igr.cc | 106 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 0 deletions(-)
create mode 100644 milena/sandbox/lazzara/igr.cc
diff --git a/milena/sandbox/ChangeLog b/milena/sandbox/ChangeLog
index 7e2cd40..0d25be8 100644
--- a/milena/sandbox/ChangeLog
+++ b/milena/sandbox/ChangeLog
@@ -1,3 +1,9 @@
+2009-01-27 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ First draft of a program for IGR's images.
+
+ * lazzara/igr.cc: new file.
+
2009-01-27 Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update color segmentation.
diff --git a/milena/sandbox/lazzara/igr.cc b/milena/sandbox/lazzara/igr.cc
new file mode 100644
index 0000000..2579fa6
--- /dev/null
+++ b/milena/sandbox/lazzara/igr.cc
@@ -0,0 +1,106 @@
+#include <mln/essential/2d.hh>
+#include <mln/binarization/binarization.hh>
+#include <mln/labeling/background.hh>
+
+#include <mln/debug/colorize.hh>
+
+#include <mln/registration/registration.hh>
+
+struct threshold : mln::Function_p2b<threshold>
+{
+ bool operator()(const mln::value::rgb8& val) const
+ {
+ unsigned inty = (val.red() + val.blue() + val.green());
+ return inty > 100 && inty < 600;
+ }
+};
+
+
+
+
+template <typename I>
+mln_concrete(I)
+fill_holes(const mln::Image<I>& ima)
+{
+ using namespace mln;
+
+ mln_concrete(I) 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_concrete(I)
+keep_largest_component(const mln::Image<I>& ima)
+{
+ using namespace mln;
+
+ image2d<bool> in_bw_cleaned = fill_holes(ima);
+ io::pbm::save(in_bw_cleaned, "0x_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, "0x_in_bw_cleaned_full.pbm");
+
+ logical::not_inplace(in_bw_cleaned_full);
+ return in_bw_cleaned_full;
+}
+
+int main(int argc, char* argv[])
+{
+ using namespace mln;
+ using value::rgb8;
+ using value::int_u8;
+ using value::label_16;
+
+ //Load image
+ typedef image2d<rgb8> I;
+ typedef image2d<bool> J;
+ I in;
+ io::ppm::load(in, argv[1]);
+
+ 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);
+ io::pbm::save(in_bw, "02_ima.pbm");
+
+ std::cout << "Compute gradient" << std::endl;
+ J ima_grad = morpho::gradient(ima, win_c4p());
+ io::pbm::save(ima_grad, "03_ima_grad.pbm");
+
+ I ref;
+ io::ppm::load(ref, argv[2]);
+ J ref_bw = binarization::binarization(ref, f);
+ std::cout << "Computing registration..." << std::endl;
+ J cloud = ima_grad | pw::value(ima_grad) == true;
+ mln_VAR(registration, registration::registration(cloud, ref_bw));
+ mln_VAR(icp, registration::icp(convert::to_p_array(cloud), ref_bw));
+
+ std::cout << "Build result image" << std::endl;
+ J res;
+ initialize(res, ima_grad);
+ mln_piter_(J) p(ima_grad.domain());
+ for_all(p)
+ if (res.has(registration(p.to_site().to_vec())))
+ res(registration(p.to_site().to_vec())) = ima_grad(p);
+
+ io::pbm::save(res, "04_registered.pbm");
+
+}
--
1.5.6.5
1
0
* mln/convert/to_p_array.hh: move conversion from here...
* mln/convert/impl/from_image_to_site_set.hh: to here... And update
dispatch accordingly.
* tests/registration/multiscale.cc: use a smaller image.
---
milena/ChangeLog | 10 ++
milena/mln/convert/impl/from_image_to_site_set.hh | 125 +++++++++++++--------
milena/mln/convert/to_p_array.hh | 10 +-
milena/tests/registration/multiscale.cc | 16 ++-
4 files changed, 103 insertions(+), 58 deletions(-)
diff --git a/milena/ChangeLog b/milena/ChangeLog
index 3427ea1..e8d9456 100644
--- a/milena/ChangeLog
+++ b/milena/ChangeLog
@@ -1,3 +1,13 @@
+2009-01-27 Guillaume Lazzara <z(a)lrde.epita.fr>
+
+ Fix conversion from Image to p_array.
+
+ * mln/convert/to_p_array.hh: move conversion from here...
+ * mln/convert/impl/from_image_to_site_set.hh: to here... And update
+ dispatch accordingly.
+
+ * tests/registration/multiscale.cc: use a smaller image.
+
2009-01-27 Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
Fix mln::registration::multiscale test.
diff --git a/milena/mln/convert/impl/from_image_to_site_set.hh b/milena/mln/convert/impl/from_image_to_site_set.hh
index 6304117..4effab4 100644
--- a/milena/mln/convert/impl/from_image_to_site_set.hh
+++ b/milena/mln/convert/impl/from_image_to_site_set.hh
@@ -65,18 +65,20 @@ namespace mln
# ifndef MLN_INCLUDE_ONLY
-
- // Case: binary image -> set of point runs.
-
- template <typename I, typename P, typename S>
- void
- from_image_to_site_set_(const I& input, const Gpoint<P>&,
- S& s, const mln::p_run<P>&)
+ namespace internal
{
- s.clear();
- mln_fwd_piter(I) p(input.domain());
- p.start();
- for (;;)
+
+ // Case: binary image -> set of point runs.
+
+ template <typename I, typename P, typename S>
+ void
+ from_image_to_site_set(const I& input, const Gpoint<P>&,
+ S& s, const mln::p_run<P>&)
+ {
+ s.clear();
+ mln_fwd_piter(I) p(input.domain());
+ p.start();
+ for (;;)
{
// Skip background.
while (p.is_valid() && input(p) == false)
@@ -87,28 +89,29 @@ namespace mln
P start = p, q;
// Go to run end.
do
- {
- q = p;
- p.next();
- }
+ {
+ q = p;
+ p.next();
+ }
while (p.is_valid() && input(p) == true &&
- // p follows q in a run, i.e., "p == q + right":
- cut_(p.to_site()) == cut_(q) && p.last_coord() == q.last_coord() + 1);
+ // p follows q in a run, i.e., "p == q + right":
+ cut_(p.to_site()) == cut_(q) && p.last_coord() == q.last_coord() + 1);
s.insert(p_run<P>(start, q));
}
- }
-
-
- template <typename I, typename P, typename S>
- void
- from_image_to_site_set_(const I& input, const Gpoint<P>&,
- S& s, const std::pair< mln_value(I), p_run<P> >&)
- {
- s.clear();
- mln_value(I) O = literal::zero;
- mln_fwd_piter(I) p(input.domain());
- p.start();
- for (;;)
+ }
+
+
+ template <typename I, typename P, typename S>
+ void
+ from_image_to_site_set(const I& input, const Gpoint<P>&,
+ S& s,
+ const std::pair< mln_value(I), p_run<P> >&)
+ {
+ s.clear();
+ mln_value(I) O = literal::zero;
+ mln_fwd_piter(I) p(input.domain());
+ p.start();
+ for (;;)
{
if (! p.is_valid()) // The end.
break;
@@ -116,27 +119,54 @@ namespace mln
P start = p, q;
// Go to run end.
do
- {
- q = p;
- p.next();
- }
+ {
+ q = p;
+ p.next();
+ }
while (p.is_valid() && input(p) == v &&
- cut_(p.to_site()) == cut_(q) && p.last_coord() == q.last_coord() + 1);
+ cut_(p.to_site()) == cut_(q) && p.last_coord() == q.last_coord() + 1);
s.insert(v, p_run<P>(start, q));
}
- }
+ }
- template <typename I, typename P, typename S>
- void
- from_image_to_site_set_(const I& input, const Gpoint<P>&,
- S& s, const std::pair< mln_value(I), P >&)
- {
- s.clear();
- mln_fwd_piter(I) p(input.domain());
- for_all(p)
- s.insert(input(p), p);
- }
+ template <typename I, typename P, typename S>
+ void
+ from_image_to_site_set(const I& input, const Gpoint<P>&,
+ S& s,
+ const std::pair< mln_value(I), P >&)
+ {
+ s.clear();
+ mln_fwd_piter(I) p(input.domain());
+ for_all(p)
+ s.insert(input(p), p);
+ }
+
+
+ template <typename I, typename S>
+ inline
+ void
+ from_image_to_site_set(const Image<I>& from, Site_Set<S>& to)
+ {
+ from_image_to_site_set(exact(from), mln_deduce(I, pset, element)(),
+ exact(to), mln_i_element(S)());
+ }
+
+ template <typename I>
+ inline
+ void
+ from_image_to_site_set(const Image<I>& from_, p_array<mln_psite(I)>& to)
+ {
+ const I& from = exact(from_);
+
+ mln_piter(I) p(from.domain());
+ for_all(p)
+ if (from(p))
+ to.append(p);
+ }
+
+
+ } // end of namespace mln::convert::impl::internal
// Facade.
@@ -146,8 +176,7 @@ namespace mln
void
from_image_to_site_set(const Image<I>& from, Site_Set<S>& to)
{
- from_image_to_site_set_(exact(from), mln_deduce(I, pset, element)(),
- exact(to), mln_i_element(S)());
+ internal::from_image_to_site_set(exact(from), exact(to));
}
# endif // ! MLN_INCLUDE_ONLY
diff --git a/milena/mln/convert/to_p_array.hh b/milena/mln/convert/to_p_array.hh
index bac55dc..1f62a65 100644
--- a/milena/mln/convert/to_p_array.hh
+++ b/milena/mln/convert/to_p_array.hh
@@ -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
@@ -30,7 +30,10 @@
# define MLN_CONVERT_TO_P_ARRAY_HH
/// \file mln/convert/to_p_array.hh
-/// \brief Conversions to mln::p_array.
+///
+/// Conversions to mln::p_array.
+///
+/// \todo Move these conversion in from_to related mechanisms.
# include <mln/core/site_set/p_array.hh>
# include <mln/core/concept/image.hh>
@@ -91,6 +94,7 @@ namespace mln
return v;
}
+ //FIXME: to remove, already added to from_image_to_site_set.hh.
template <typename I>
inline
p_array<mln_psite(I)>
diff --git a/milena/tests/registration/multiscale.cc b/milena/tests/registration/multiscale.cc
index da2f203..754e7d0 100644
--- a/milena/tests/registration/multiscale.cc
+++ b/milena/tests/registration/multiscale.cc
@@ -1,4 +1,5 @@
-// Copyright (C) 2008 EPITA Research and Development Laboratory (LRDE)
+// Copyright (C) 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/registration/registration.cc
- *
- * \brief Test on mln::registration::registration.cc
- */
+/// \file tests/registration/multiscale.cc
+///
+/// Test on mln::registration::multiscale.cc
+///
+/// FIXME: write a test!
#include "tests/data.hh"
#include <mln/io/pbm/all.hh>
@@ -43,8 +45,8 @@ int main()
image2d< bool > img2;
//load images
- io::pbm::load(img1, MLN_IMG_DIR "/lena.pbm");
- io::pbm::load(img2, MLN_IMG_DIR "/lena.pbm");
+ io::pbm::load(img1, MLN_IMG_DIR "/fly.pbm");
+ io::pbm::load(img2, MLN_IMG_DIR "/fly.pbm");
//FIXME: Auto test result
//FIXME: Make it pass
--
1.5.6.5
1
0
https://svn.lrde.epita.fr/svn/oln/trunk/milena/sandbox
Index: ChangeLog
from Thierry Geraud <thierry.geraud(a)lrde.epita.fr>
Update color segmentation.
* theo/color/segment.cc: Update.
* theo/color/change_attributes.hh: New.
change_attributes.hh | 203 ++++++++++++++++++++++++++++++++++++++++++++++++++
segment.cc | 206 +++++++++++++++++++++++++++++++++------------------
2 files changed, 340 insertions(+), 69 deletions(-)
Index: theo/color/segment.cc
--- theo/color/segment.cc (revision 3207)
+++ theo/color/segment.cc (working copy)
@@ -8,6 +8,8 @@
#include <mln/core/alias/neighb2d.hh>
#include <mln/make/double_neighb2d.hh>
+#include <mln/value/label_8.hh>
+
#include <mln/core/image/image_if.hh>
#include <mln/pw/all.hh>
#include <mln/core/routine/extend.hh>
@@ -38,6 +40,8 @@
#include <mln/accu/volume.hh>
#include "sum_pix.hh"
+#include "change_attributes.hh"
+
namespace mln
@@ -327,34 +331,6 @@
}
- template <typename A, typename T>
- inline
- mln_ch_value(typename T::function, mln_result(A))
- compute_rand_attribute_on_nodes(const A& a, const T& t)
- {
- typedef typename T::function I;
-
- mln_ch_value(I, mln_result(A)) attr;
- initialize(attr, t.f());
-
- // Initialize every attribute with the corresponding pixel.
- {
- mln_piter(I) p(t.f().domain());
- for_all(p)
- attr(p) = float(std::rand() % 10000) / 1000.f;
- }
-
- // Propagate attribute from a site to its parent.
- {
- mln_fwd_piter(T) p(t.domain());
- for_all(p)
- if (! t.is_root(p))
- attr(t.parent(p)) += attr(p);
- }
-
- return attr;
- }
-
// Tree -> nchildren (on nodes).
@@ -393,6 +369,7 @@
mln_concrete(typename T::function)
filter(const A& a, const T& t, const N& nbh,
unsigned n_objects,
+ unsigned& less,
mln_value(A)& lambda,
bool echo = false)
{
@@ -411,28 +388,38 @@
if (n_objects >= n_regmins_f)
{
std::cout << "warning: number of expected objects is greater than number of regmins!" << std::endl;
- std::cout << "aborting..." << std::endl;
- return duplicate(t.f());
+ std::cout << "aborting!" << std::endl;
+ std::abort();
}
lambda = mln_max(mln_value(A));
- mln_ch_value(typename T::function, unsigned) nchildren = compute_nchildren(t);
+ mln_ch_value(I, unsigned) nchildren = compute_nchildren(t);
+ if (echo)
+ debug::println("nchildren (before) =", nchildren | t.nodes());
typedef p_array<mln_site(I)> S;
S s = my_sort_increasing(a, t.nodes());
const typename T::parent_t& par = t.parent_image();
- unsigned
- count = n_regmins_f,
+ unsigned count = n_regmins_f;
less = 0;
+
+ // For display only.
+ mln_ch_value(I, bool) filtered;
+ initialize(filtered, t.f());
+ data::fill(filtered, false);
+
mln_fwd_piter(S) p(s);
for_all(p)
{
if (a(p) < lambda && par(p) != p)
{
mln_assertion(nchildren(par(p)) > 0);
+
+ filtered(p) = true; // For display only.
+
--nchildren(par(p));
if (nchildren(par(p)) != 0)
{
@@ -446,18 +433,26 @@
lambda = a(p) + 1;
std::cout << "lambda = " << lambda << std::endl
<< std::endl;
- // break; // Stop iterations.
+ break; // Stop iterations.
+ }
}
}
}
+
+ if (echo)
+ {
+ back_propagate(filtered, t);
+ debug::println("filtered =", filtered);
+ debug::println("a < lambda = ", (pw::value(a) < pw::cst(lambda)) | a.domain());
}
+
if (less != 0)
std::cerr << "WARNING: less objects (" << less << ") than expected..." << std::endl
<< std::endl;
if (echo)
- debug::println("nchildren =", nchildren | t.nodes());
+ debug::println("nchildren (after) =", nchildren | t.nodes());
// Filtering.
mln_concrete(I) g;
@@ -477,45 +472,107 @@
if (echo)
{
unsigned n_regmins_g;
- debug::println( "regmin(g)", labeling::regional_minima(g, nbh, n_regmins_g) );
+ mln_VAR(regmin_g, labeling::regional_minima(g, nbh, n_regmins_g));
+ debug::println( "regmin(g)", regmin_g);
+ debug::println("a | regmin(g) = ", a | (pw::value(regmin_g) != 0));
+
}
return g;
}
+
template <typename A, typename I, typename N>
void
test_filter(A a, mln_result(A) lambda,
const I& f, const I& g, const N& nbh,
+ unsigned n_objects, unsigned less,
bool echo = false)
{
mln_concrete(I) g_ref = morpho::closing_attribute<A>(f, nbh, lambda);
- if (echo)
- debug::println("g_ref =", g_ref);
unsigned n_regmins_g_ref;
- mln_ch_value(I, unsigned) regmin_g = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
-// if (echo)
- std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
- << std::endl;
+ mln_ch_value(I, unsigned) regmin_g_ref = labeling::regional_minima(g_ref, nbh, n_regmins_g_ref);
+ bool consistency = (n_regmins_g_ref + less == n_objects);
if (g != g_ref)
{
std::cerr << "OOPS: g DIFFERS FROM ref!" << std::endl
<< std::endl;
-// debug::println("diff", (pw::value(g_ref) == pw::value(g)) | g.domain());
+ debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
-// debug::println("g_ref", g_ref);
-// debug::println("g", g);
-// debug::println("regmin_g", regmin_g);
+ debug::println("g_ref =", g_ref);
+ debug::println("regmin(g_ref) =", regmin_g_ref);
+ std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << std::endl;
}
-// bool consistency = (n_regmins_g_ref + less == n_objects);
-// if (consistency == false)
-// std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
-// << std::endl;
+ if (consistency == false)
+ {
+ std::cerr << "OOPS: INCONSISTENCY (BUG...)!" << std::endl
+ << " n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << " n_less = " << less << std::endl
+ << " n_objects = " << n_objects << std::endl
+ << std::endl;
+
+ debug::println("diff = ", (pw::value(g_ref) == pw::value(g)) | g.domain());
+
+ debug::println("g_ref =", g_ref);
+ debug::println("regmin(g_ref) =", regmin_g_ref);
+ std::cout << "n_regmins(g_ref) = " << n_regmins_g_ref << std::endl
+ << std::endl;
+
+ }
+ }
+
+
+
+ // Filter facade.
+
+ template <typename F, typename N, typename A>
+ inline
+ mln_concrete(F)
+ filter_color(const F& f, // a "gradient" of color image
+ const N& nbh,
+ const A& a_, // an attribute
+ bool do_extinction,
+ unsigned n_objects,
+ bool echo = false)
+ {
+ typedef p_array<mln_psite(F)> S;
+ S s = level::sort_psites_decreasing(f);
+
+ typedef morpho::tree::data<F,S> tree_t;
+ tree_t t(f, s, nbh);
+
+ mln_VAR(a, compute_attribute_on_nodes(a_, t));
+ back_propagate(a, t);
+
+ if (echo)
+ {
+ debug::println("par =", t.parent_image() | t.nodes());
+ debug::println("a =", a | t.nodes());
+ debug::println("a = ", a);
+ }
+ if (do_extinction)
+ extinct_attributes(t, a);
+ if (echo)
+ debug::println("a' =", a | t.nodes());
+
+
+ mln_value(a_t) lambda;
+ unsigned less;
+ mln_concrete(F) g = filter(a, t, nbh, n_objects, // input
+ less, lambda, // output
+ echo);
+
+ test_filter(a_, lambda, f, g, nbh,
+ n_objects, less,
+ echo);
+
+ return g;
}
@@ -526,8 +583,10 @@
void usage(char* argv[])
{
- std::cerr << "usage: " << argv[0] << " input.ppm n output.ppm" << std::endl;
+ std::cerr << "usage: " << argv[0] << " input.ppm n extinction output.ppm echo" << std::endl;
std::cerr << " n >= 2" << std::endl;
+ std::cerr << " extinction = 0 (none) or 1 (effective)" << std::endl;
+ std::cerr << " echo = 0 (mute) or 1 (verbose)" << std::endl;
abort();
}
@@ -539,7 +598,7 @@
using value::int_u8;
using value::rgb8;
- if (argc != 4)
+ if (argc != 6)
usage(argv);
@@ -554,6 +613,9 @@
unsigned n_objects = atoi(argv[2]);
+ bool do_extinction = atoi(argv[3]);
+ bool echo = atoi(argv[5]);
+
// Changing input into 'f on edges'.
@@ -567,14 +629,6 @@
typedef f_t I;
- // Filtering f -> g.
-
- typedef p_array<point2d> S;
- S s = level::sort_psites_decreasing(f);
-
- typedef morpho::tree::data<I,S> tree_t;
- tree_t t(f, s, e2e());
-
// accu::count< util::pix<I> > a_;
// accu::volume<I> a_;
// accu::sum_pix< util::pix<I> > a_;
@@ -582,22 +636,36 @@
blen_image = input_;
accu::blen_pix<I> a_;
- mln_VAR(a, compute_attribute_on_nodes(a_, t));
+ f_t g = filter_color(f, e2e(),
+ a_, do_extinction,
+ n_objects,
+ echo);
- mln_value_(a_t) lambda;
- f_t g = filter(a, t, e2e(), n_objects, lambda);
+ if (echo)
+ debug::println("activity (g != f) = ", (pw::value(g) != pw::value(f)) | f.domain());
- test_filter(a_, lambda, f, g, e2e());
+ // Watershed transform.
+ typedef value::label_8 L;
+ L nbasins;
+ mln_ch_value_(f_t, L) w = morpho::meyer_wst(g, e2e(), nbasins);
- // Watershed transform.
+ // io::pgm::save(display_edge(w.unmorph_(), 0, 3), "temp_w.pgm");
- int_u8 nbasins;
- mln_ch_value_(f_t, int_u8) w_edges = morpho::meyer_wst(g, e2e(), nbasins);
+ if (echo)
+ {
+ image2d<int_u8> g_(f_.domain());
- // io::pgm::save(display_edge(w_edges.unmorph_(), 0, 3), "temp_w_edges.pgm");
+ data::fill(g_, 0);
+ data::paste(g | (pw::value(w) != 0), g_);
+ debug::println("g | basins = ", g_ | is_edge);
+
+ data::fill(g_, 0);
+ data::paste(g | (pw::value(w) == 0), g_);
+ debug::println("g | w line = ", g_ | is_edge);
+ }
- image2d<int_u8> w_all = w_edges.unmorph_();
+ image2d<L> w_all = w.unmorph_();
{
// edges -> squares
mln_VAR(w_squares, w_all | is_square);
Index: theo/color/change_attributes.hh
--- theo/color/change_attributes.hh (revision 0)
+++ theo/color/change_attributes.hh (revision 0)
@@ -0,0 +1,203 @@
+namespace mln
+{
+
+
+ // Display.
+ // --------
+
+
+ template <typename T, typename I>
+ void display_tree_attributes(const T& t, // Tree.
+ const I& a) // Attribute image.
+ {
+ typedef mln_site(I) P;
+
+ mln_ch_value(I, bool) deja_vu;
+ initialize(deja_vu, a);
+ data::fill(deja_vu, false);
+
+ typedef typename T::nodes_t nodes_t;
+ mln_fwd_piter(nodes_t) p(t.nodes());
+ for_all(p)
+ {
+ if (deja_vu(p))
+ continue;
+
+ P e = p;
+ do
+ {
+ std::cout << a(e) << ':' << e << " -> ";
+ deja_vu(e) = true;
+ e = t.parent(e);
+ }
+ while (! deja_vu(e));
+ std::cout << a(e) << ':' << e << std::endl;
+ }
+ std::cout << std::endl;
+ }
+
+
+
+ // Back-propagate values from nodes to component sites.
+ // ----------------------------------------------------
+
+ template <typename A, typename T>
+ void
+ back_propagate(A& a, const T& t)
+ {
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (! t.is_a_node(p))
+ {
+ mln_assertion(t.is_a_node(t.parent(p)));
+ a(p) = a(t.parent(p));
+ }
+ }
+
+
+
+
+ // Attribute Extinction.
+ // ---------------------
+
+ namespace internal
+ {
+
+ template <typename T>
+ struct node_pred : Function_p2b< node_pred<T> >
+ {
+ typedef bool result;
+
+ template <typename P>
+ bool operator()(const P& p) const
+ {
+ return t->is_a_node(p);
+ }
+
+ const T* t;
+ };
+
+ template <typename T, typename I, typename M>
+ inline
+ mln_value(I)
+ extinct_rec(const T& t, // tree
+ I& a, // attribute image
+ M& mark,
+ const mln_psite(I)& p)
+ {
+ mln_invariant(mark(p) == false);
+ mark(p) = true;
+ if (t.parent(p) == p || mark(t.parent(p)) == true) // Stop.
+ return a(p);
+ return a(p) = extinct_rec(t, a, mark, t.parent(p));
+ }
+
+ } // end of internal
+
+
+
+ template <typename T, typename I>
+ void
+ extinct_attributes(const T& t, // Tree.
+ I& a) // Attribute image.
+ {
+ typedef mln_site(I) P;
+ typedef mln_value(I) A; // Type of attributes.
+
+ mln_ch_value(I, bool) mark;
+ initialize(mark, a);
+ data::fill(mark, false);
+
+ internal::node_pred<T> node_only;
+ node_only.t = &t;
+
+ typedef p_array<P> S;
+ S s = level::sort_psites_increasing(a | node_only);
+ mln_invariant(geom::nsites(a | t.nodes()) == s.nsites());
+
+ mln_fwd_piter(S) p(s);
+ for_all(p)
+ {
+ if (mark(p) == true)
+ continue;
+ internal::extinct_rec(t, a, mark, p);
+ }
+
+ // debug::println(mark | t.nodes());
+ }
+
+
+
+ // Move down.
+ // ----------
+
+ template <typename A, typename T>
+ inline
+ void
+ move_down_attributes(A& a, const T& t)
+ {
+ typedef typename T::nodes_t N;
+ mln_fwd_piter(N) n(t.nodes());
+ for_all(n)
+ a(n) = a(t.parent(n));
+
+ for_all(n)
+ mln_invariant(a(n) <= a(t.parent(n)));
+ }
+
+
+
+
+ // Fuse down.
+ // ----------
+
+ template <typename A, typename T>
+ inline
+ void
+ fuse_down_attributes(A& a, const T& t)
+ {
+ typedef typename T::nodes_t N;
+ mln_fwd_piter(N) n(t.nodes());
+ for_all(n)
+ a(n) = (a(n) + a(t.parent(n))) / 2;
+
+ for_all(n)
+ mln_invariant(a(n) <= a(t.parent(n)));
+ }
+
+
+
+ // Rand.
+ // -----
+
+ template <typename A, typename T>
+ inline
+ mln_ch_value(typename T::function, mln_result(A))
+ compute_rand_attribute_on_nodes(const A& a, const T& t)
+ {
+ typedef typename T::function I;
+
+ mln_ch_value(I, mln_result(A)) attr;
+ initialize(attr, t.f());
+
+ // Initialize every attribute with the corresponding pixel.
+ {
+ mln_piter(I) p(t.f().domain());
+ for_all(p)
+ attr(p) = float(std::rand() % 10000) / 1000.f;
+ }
+
+ // Propagate attribute from a site to its parent.
+ {
+ mln_fwd_piter(T) p(t.domain());
+ for_all(p)
+ if (! t.is_root(p))
+ attr(t.parent(p)) += attr(p);
+ }
+
+ return attr;
+ }
+
+
+
+} // end of namespace mln
1
0