https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
Sandbox: ICP: Make check.
* sandbox/jardonnet/test/icp_check.sh: New Check Script.
* sandbox/jardonnet/test/bin: New Bin directory.
* sandbox/jardonnet/test/Makefile: Update for testes.
* sandbox/jardonnet/test/icp_lazy.cc: New dedicated to lazy_map.
* sandbox/jardonnet/registration/icp_lazy.hh: New dedicated to lazy map.
* sandbox/jardonnet/registration/quat7.hh: Update.
* sandbox/jardonnet/registration/chamfer.hh: Update.
* sandbox/jardonnet/registration/icp.hh: Update (dedicated to
distance_map).
* sandbox/jardonnet/registration/misc.hh: Move outside quat/ (removed).
* sandbox/jardonnet/registration/rotation.hh: Move outside quat/ (removed).
* sandbox/jardonnet/test/check: Remove old test script.
registration/icp.hh | 6 +
registration/icp_lazy.hh | 171
+++++++++++++++++++++++++++++++++++++++++++++++
registration/misc.hh | 19 +++++
registration/quat7.hh | 2
registration/rotation.hh | 70 +++++++++++++++++++
test/Makefile | 25 ++++++
test/icp_check.sh | 8 ++
test/icp_lazy.cc | 20 +++++
8 files changed, 315 insertions(+), 6 deletions(-)
Index: sandbox/jardonnet/test/icp_check.sh
--- sandbox/jardonnet/test/icp_check.sh (revision 0)
+++ sandbox/jardonnet/test/icp_check.sh (revision 0)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+for i in `\ls bin/`
+do
+ echo execute $i 01.pbm 02.pbm
+ ./bin/$i 01.pbm 02.pbm > ./bin/log_$i
+ echo ./bin/log_$i
+done
Property changes on: sandbox/jardonnet/test/icp_check.sh
___________________________________________________________________
Name: svn:executable
+ *
Index: sandbox/jardonnet/test/Makefile
--- sandbox/jardonnet/test/Makefile (revision 1820)
+++ sandbox/jardonnet/test/Makefile (working copy)
@@ -14,9 +14,6 @@
g++ gaussian.cc $(FLAG) -o '+gau.exe'
icp:
- g++ icp.cc $(FLAG) -o '+icp.exe'
-
-icp++:
g++ icp.cc -ffloat-store -I../../.. -O3 -DNDEBUG -o '+icp.exe'
icpsafe:
@@ -29,3 +26,25 @@
./+icp.exe 01.pbm 02.pbm > log
gnuplot plotscript
+check: clean
+ g++ icp.cc -I../../.. -O0 -o './bin/+icp_0'
+ g++ icp.cc -I../../.. -O0 -ffloat-store -o './bin/+icp_0f'
+ g++ icp.cc -I../../.. -O0 -DNDEBUG -o './bin/+icp_0D'
+ g++ icp.cc -I../../.. -O0 -DNDEBUG -ffloat-store -o './bin/+icp_0Df'
+ g++ icp.cc -I../../.. -O3 -o './bin/+icp_3'
+ g++ icp.cc -I../../.. -O3 -ffloat-store -o './bin/+icp_3f'
+ g++ icp.cc -I../../.. -O3 -DNDEBUG -o './bin/+icp_3D'
+ g++ icp.cc -I../../.. -O3 -DNDEBUG -ffloat-store -o './bin/+icp_3df'
+ g++ icp_lazy.cc -I../../.. -O0 -o './bin/+icp_lazy_0'
+ g++ icp_lazy.cc -I../../.. -O0 -ffloat-store -o './bin/+icp_lazy_0f'
+ g++ icp_lazy.cc -I../../.. -O0 -DNDEBUG -o './bin/+icp_lazy_0D'
+ g++ icp_lazy.cc -I../../.. -O0 -DNDEBUG -ffloat-store -o
'./bin/+icp_lazy_0Df'
+ g++ icp_lazy.cc -I../../.. -O3 -o './bin/+icp_lazy_3'
+ g++ icp_lazy.cc -I../../.. -O3 -ffloat-store -o './bin/+icp_lazy_3f'
+ g++ icp_lazy.cc -I../../.. -O3 -DNDEBUG -o './bin/+icp_lazy_3D'
+ g++ icp_lazy.cc -I../../.. -O3 -DNDEBUG -ffloat-store -o
'./bin/+icp_lazy_3df'
+
+clean:
+ rm -- ./bin/*
+
+.PHONY: check
\ No newline at end of file
Index: sandbox/jardonnet/test/icp_lazy.cc
--- sandbox/jardonnet/test/icp_lazy.cc (revision 0)
+++ sandbox/jardonnet/test/icp_lazy.cc (revision 0)
@@ -0,0 +1,20 @@
+#include <mln/core/image3d.hh>
+
+#include <mln/io/pbm/load.hh>
+#include <mln/io/pbm/save.hh>
+
+#include <sandbox/jardonnet/registration/icp_lazy.hh>
+
+int main(int, char* argv[])
+{
+ using namespace mln;
+
+ image2d< bool > img1;
+ image2d< bool > img2;
+
+ io::pbm::load(img1, argv[1]);
+ io::pbm::load(img2, argv[2]);
+
+ io::pbm::save(registration::icp(img1,img2), "./+registred.pbm");
+}
+
Index: sandbox/jardonnet/registration/quat7.hh
--- sandbox/jardonnet/registration/quat7.hh (revision 1820)
+++ sandbox/jardonnet/registration/quat7.hh (working copy)
@@ -8,7 +8,7 @@
# include <mln/algebra/mat.hh>
# include <mln/core/p_array.hh>
-# include "quat/all.hh"
+# include "rotation.hh"
# include "jacobi.hh"
# include <mln/norm/l2.hh>
Index: sandbox/jardonnet/registration/chamfer.hh
Index: sandbox/jardonnet/registration/icp_lazy.hh
--- sandbox/jardonnet/registration/icp_lazy.hh (revision 0)
+++ sandbox/jardonnet/registration/icp_lazy.hh (revision 0)
@@ -0,0 +1,171 @@
+// Copyright (C) 2008 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_REGISTRATION_ICP_HH
+# define MLN_REGISTRATION_ICP_HH
+
+/*! \file mln/registration/icp.hh
+ *
+ * \brief image registration
+ */
+
+# include <mln/algebra/quat.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/make/w_window.hh>
+# include <mln/make/w_window3d.hh>
+
+# include "tools.hh"
+
+# include "cloud.hh"
+# include "quat7.hh"
+# include "projection.hh"
+# include "chamfer.hh"
+
+namespace mln
+{
+
+ namespace registration
+ {
+
+ /*! Registration FIXME : doxy
+ *
+ *
+ */
+ template <typename I, typename J>
+ inline
+ mln_concrete(I)
+ icp(const Image<I>& cloud,
+ const Image<J>& surface);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ namespace impl
+ {
+
+ template <typename P, typename M>
+ inline
+ p_array<P>
+ icp_(p_array<P>& C,
+ const p_array<P>& X,
+ M& map)
+ {
+ trace::entering("registration::impl::icp_");
+
+ unsigned int k;
+ quat7<P::dim> old_qk, qk;
+ float err;
+ //float err_bis;
+ p_array<P> Ck(C), Xk(C); //FIXME: Xk copy C
+
+ algebra::vec<P::dim,float> mu_C = center(C), mu_Xk;
+
+ const float epsilon = 1;//1e-3;
+
+ //// step 1
+ k = 0;
+
+ do {
+ //std::cout << "step 2" << std::endl;
+
+ //// step 2
+ projection::memo(Ck, X, Xk, map);
+
+ mu_Xk = center(Xk);
+
+ //std::cout << "step 3" << std::endl;
+ //// step 3
+ old_qk = qk;
+ qk = match(C, mu_C, Xk, mu_Xk);
+
+ //std::cout << "step 4" << std::endl;
+ //// step 4
+ qk.apply_on(C, Ck); // Ck+1 = qk(C)
+
+ //std::cout << "step err" << std::endl;
+ //// err = d(Ck+1,Xk)
+ err = rms(Ck, Xk);
+ std::cout << k << ' ' << err << ' '
<< (qk -
old_qk).sqr_norm() << std::endl; //plot file
+
+ ++k;
+ } while (k < 3 || (qk - old_qk).sqr_norm() > epsilon);
+
+ trace::exiting("registration::impl::icp_");
+ return Ck;
+ }
+
+ } // end of namespace mln::registration::impl
+
+
+ //Only for 2d and 3d image
+ template <typename I, typename J>
+ inline
+ mln_concrete(I) //FIXME: should return something else ? qk ?
+ icp(const Image<I>& cloud_,
+ const Image<J>& surface_)
+ {
+ trace::entering("registration::icp");
+ mln_precondition(exact(cloud_).has_data());
+ mln_precondition(exact(surface_).has_data());
+
+ //convert to image: time consuming
+ typedef image3d<mln_value(I)> I3d;
+ I3d cloud = convert::to_image_3d(exact(cloud_));
+ const I3d surface = convert::to_image_3d(exact(surface_));
+
+ //build p_arrays.
+ p_array<mln_point(I3d)> c = convert::to_p_array(cloud);
+ p_array<mln_point(I3d)> x = convert::to_p_array(surface);
+
+ //build closest point map
+ //FIXME: like that lazy_map<I3d>
map(enlarge(bigger(c.bbox(),x.bbox()),50));
+ lazy_map<I3d> map(1000,1000,50);
+
+ p_array<mln_point(I3d)> res = impl::icp_(c, x, map);
+
+ //to 2d : projection (FIXME:if 3d)
+ //mln_concrete(I) output = convert::to_image<I>(res)?
+ mln_concrete(I) output(exact(cloud_).domain());
+ for (size_t i = 0; i < res.npoints(); i++)
+ {
+ point2d p(res[i][0], res[i][1]);
+ //FIXME: not necessary if output(res.bbox())
+ if (output.has(p))
+ output(p) = true;
+ }
+
+ trace::exiting("registration::icp");
+ return output;
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::registration
+
+} // end of namespace mln
+
+
+#endif // ! MLN_REGISTRATION_ICP_HH
Index: sandbox/jardonnet/registration/icp.hh
--- sandbox/jardonnet/registration/icp.hh (revision 1820)
+++ sandbox/jardonnet/registration/icp.hh (working copy)
@@ -87,8 +87,10 @@
//// step 1
k = 0;
+
do {
- std::cout << "step 2" << std::endl;
+ //std::cout << "step 2" << std::endl;
+
//// step 2
projection::fill_Xk(Ck, map, Xk);
//projection::de_base(Ck, X, Xk, err_bis);
@@ -157,7 +159,7 @@
p_array<mln_point(I3d)> res = impl::icp_(c, x, map);
//to 2d : projection (FIXME:if 3d)
- //mln_concrete(I) output = convert::to_image2d(res)?
+ //mln_concrete(I) output = convert::to_image<I>(res)?
mln_concrete(I) output(exact(cloud_).domain());
for (size_t i = 0; i < res.npoints(); i++)
{
Index: sandbox/jardonnet/registration/misc.hh
--- sandbox/jardonnet/registration/misc.hh (revision 0)
+++ sandbox/jardonnet/registration/misc.hh (revision 0)
@@ -0,0 +1,19 @@
+#ifndef MISC_HH
+# define MISC_HH
+
+
+inline
+float epsilon()
+{
+ static const float e = 1e-5;
+ return e;
+}
+
+inline
+bool about_equal(float val1, float val2)
+{
+ return fabs(val1 - val2) < epsilon();
+}
+
+
+#endif // ndef MISC_HH
Index: sandbox/jardonnet/registration/rotation.hh
--- sandbox/jardonnet/registration/rotation.hh (revision 0)
+++ sandbox/jardonnet/registration/rotation.hh (revision 0)
@@ -0,0 +1,70 @@
+#ifndef ROTATION_HH
+# define ROTATION_HH
+
+# include <stdlib.h>
+//# include "quat.hh"
+
+//# include "mat.hh"
+
+# include <mln/algebra/mat.hh>
+# include <mln/algebra/vec.hh>
+# include <mln/make/vec.hh>
+# include <mln/make/mat.hh>
+# include <mln/algebra/quat.hh>
+
+# include "misc.hh"
+
+// FIXME: rotation should be an abstract class
+// and derived classes encapsulate either a quaternion or a algebra::matrix
+namespace mln
+{
+
+ // FIXME : quat is not appriate here
+ template <unsigned n>
+ algebra::vec<n,float> rotate(const algebra::quat& q, const
algebra::vec<n,float>& p)
+ {
+
+ return (q * algebra::quat(0. ,p) * q.inv()).v();
+ }
+
+ //FIXME : check if correct with n != 3
+ template <unsigned n>
+ bool check_rotation(const algebra::mat<n,n,float>& mat,
+ const algebra::quat& q)
+ {
+ assert(q.is_unit());
+ algebra::vec<n,float>
+ tmp = make::vec(rand(), rand(), rand()),
+ p;
+ float nl2= norm::l2(tmp);
+ if(nl2 != 0)
+ p = tmp / nl2;
+ algebra::vec<n,float>
+ p_rot_1 = rotate(q, p),
+ p_rot_2 = mat * p;
+
+ return about_equal(norm::l2(p_rot_1 - p_rot_2), 0.f);
+ }
+
+
+ //FIXME : switch to n dim.
+ algebra::mat<3,3,float> quat2mat(const algebra::quat& q)
+ {
+ assert(q.is_unit());
+ float
+ w = q.to_vec()[0],
+ x = q.to_vec()[1], x2 = 2*x*x, xw = 2*x*w,
+ y = q.to_vec()[2], y2 = 2*y*y, xy = 2*x*y, yw = 2*y*w,
+ z = q.to_vec()[3], z2 = 2*z*z, xz = 2*x*z, yz = 2*y*z, zw =
2*z*w;
+ float t[9] = {1.f - y2 - z2, xy - zw, xz + yw,
+ xy + zw, 1.f - x2 - z2, yz - xw,
+ xz - yw, yz + xw, 1.f - x2 - y2};
+ algebra::mat<3,3,float> tmp = make::mat<3,3,9,float>(t);
+ // postcondition
+ assert(check_rotation(tmp, q));
+ return tmp;
+ }
+}
+
+
+#endif // ndef ROTATION_HH