https://svn.lrde.epita.fr/svn/oln/trunk/milena
Index: ChangeLog
from Ugo Jardonnet <jardonnet(a)lrde.epita.fr>
Sandbox: ICP : projection::memo.
* sandbox/jardonnet/test/icp.cc: Update.
* sandbox/jardonnet/test/check: Test projection techniques.
* sandbox/jardonnet/TODO: Update.
* sandbox/jardonnet/registration/quat7.hh: Correction.
* sandbox/jardonnet/registration/cloud.hh: Correction.
* sandbox/jardonnet/registration/jacobi.hh: Add FIXME (nD).
* sandbox/jardonnet/registration/icp.hh: Improvment.
* sandbox/jardonnet/registration/projection.hh: Add a projection
technique "memo" computing closest point only if needed.
* sandbox/jardonnet/registration/tools.hh: Gather together tools to add
to milena.
mln/make/window3d.hh | 2
sandbox/jardonnet/TODO | 14 ++
sandbox/jardonnet/registration/cloud.hh | 4
sandbox/jardonnet/registration/icp.hh | 117
+++++++----------------
sandbox/jardonnet/registration/jacobi.hh | 2
sandbox/jardonnet/registration/projection.hh | 57 ++++++++++-
sandbox/jardonnet/registration/quat7.hh | 50 ++-------
sandbox/jardonnet/registration/tools.hh | 137
+++++++++++++++++++++++++++
sandbox/jardonnet/test/check | 13 ++
9 files changed, 273 insertions(+), 123 deletions(-)
Index: mln/make/window3d.hh
--- mln/make/window3d.hh (revision 1814)
+++ mln/make/window3d.hh (working copy)
@@ -62,7 +62,7 @@
inline
mln::window3d window3d(bool (&values)[M])
{
- int h = unsigned(std::pow(float(M), 1 / 3)) / 2;
+ int h = unsigned(std::pow(float(M), float(1. / 3.))) / 2;
mln_precondition((2 * h + 1) * (2 * h + 1) * (2 * h + 1) == M);
mln::window3d tmp;
unsigned i = 0;
Index: sandbox/jardonnet/test/icp.cc
Index: sandbox/jardonnet/test/check
--- sandbox/jardonnet/test/check (revision 0)
+++ sandbox/jardonnet/test/check (revision 0)
@@ -0,0 +1,13 @@
+#!/bin/zsh
+
+touch log
+
+echo "### report : projection" >> log
+echo "*** maps ***" >> log
+time ./+icp_maps.exe +01.pbm +02.pbm >> log
+echo "*** de_base ***" >> log
+time ./+icp_base.exe +01.pbm +02.pbm >> log
+echo "*** memo ***" >> log
+time ./+icp_memo.exe +01.pbm +02.pbm >> log
+
+cat log
Property changes on: sandbox/jardonnet/test/check
___________________________________________________________________
Name: svn:executable
+ *
Index: sandbox/jardonnet/TODO
--- sandbox/jardonnet/TODO (revision 1814)
+++ sandbox/jardonnet/TODO (working copy)
@@ -6,3 +6,17 @@
gaussian.cc:22: error: no match for 'operator==' in 'img == out'
- -
+adapt test for threshold (old thresholding)
+- -
+
+- Enlever static dans projection::memo
+
+Note:
++01.bmp: 943 pts
+30 itérations : 30*943 = 28290 calcul de ppp
+Domaine +02.bmp: 777x480 = 362082
+nb de ppp calculé memo = 11749
+
+map 1:40
+de_base 10.5
+memo 9.5
\ No newline at end of file
Index: sandbox/jardonnet/registration/quat7.hh
--- sandbox/jardonnet/registration/quat7.hh (revision 1814)
+++ sandbox/jardonnet/registration/quat7.hh (working copy)
@@ -15,37 +15,9 @@
# include <mln/trait/all.hh>
+# include <mln/make/vec.hh>
-// FIXME : move elsewhere
-namespace mln
-{
- namespace algebra
- {
-
- template<unsigned n, unsigned m, typename T>
- mat<m,n,T>
- trans(const mat<n,m,T>& matrice)
- {
- mat<m,n,T> tmp;
- for (unsigned i = 0; i < n; ++i)
- for (unsigned j = 0; j < m; ++j)
- tmp(j,i) = matrice(i,j);
- return tmp;
- }
-
- // trace
-
- template<unsigned n, typename T> inline
- float tr(const mat<n,n,T>& m)
- {
- float f = 0.f;
- for (unsigned i = 0; i < n; ++i)
- f += m(i,i);
- return f;
- }
-
- }
-}
+# include "tools.hh"
namespace mln
{
@@ -89,10 +61,15 @@
assert(input.npoints() == output.npoints());
assert(_qR.is_unit());
- //FIXME utiliser equivalent pour p_array
- //std::transform(input.begin(), input.end(),
- // output.begin(),
- // *this);
+ for (size_t i = 0; i < input.npoints(); i++)
+ output.hook_()[i] = algebra::to_point<P>((*this)(input[i]));
+ }
+
+ friend std::ostream& operator << (std::ostream& os, quat7& q)
+ {
+ std::cout << q._qR << std::endl;
+ std::cout << q._qT << std::endl;
+ return os;
}
};
@@ -121,8 +98,6 @@
// qR
- //FIXME : use P::dim ?
- std::cout << "loop" << std::endl;
algebra::mat<P::dim,P::dim,float> Mk;
for (unsigned i = 0; i < C.npoints(); ++i)
{
@@ -131,12 +106,11 @@
Mk += make::mat(Ci - mu_C) * trans(make::mat(Xki - mu_Xk));
}
Mk /= C.npoints();
- std::cout << "loop end" << std::endl;
const algebra::mat<P::dim,P::dim,float> Ak = Mk - trans(Mk);
const float v[3] = {Ak(1,2), Ak(2,0), Ak(0,1)};
- const algebra::mat<3,1,float> D = make::mat<3,1,3,float>(v); //
FIXME why <...>
+ const algebra::mat<3,1,float> D = make::mat<3,1,3,float>(v);
algebra::mat<4,4,float> Qk;
Index: sandbox/jardonnet/registration/cloud.hh
--- sandbox/jardonnet/registration/cloud.hh (revision 1814)
+++ sandbox/jardonnet/registration/cloud.hh (working copy)
@@ -51,7 +51,7 @@
return f / a1.npoints();
}
- }
-}
+ } // end of namespace registration
+} // end of namespace mln
#endif // ndef CLOUD_HH
Index: sandbox/jardonnet/registration/jacobi.hh
--- sandbox/jardonnet/registration/jacobi.hh (revision 1814)
+++ sandbox/jardonnet/registration/jacobi.hh (working copy)
@@ -11,7 +11,7 @@
namespace mln
{
-
+ //FIXME: nD ?
#define rotateJacobi(a,i,j,k,l) g=a(i,j);h=a(k,l);a(i,j)=g-s*(h+g*tau); \
a(k,l)=h+s*(g-h*tau);
Index: sandbox/jardonnet/registration/icp.hh
--- sandbox/jardonnet/registration/icp.hh (revision 1814)
+++ sandbox/jardonnet/registration/icp.hh (working copy)
@@ -35,7 +35,10 @@
# include <mln/algebra/quat.hh>
# include <mln/algebra/vec.hh>
-# include <mln/core/w_window.hh>
+# include <mln/make/w_window.hh>
+# include <mln/make/window3d.hh>
+
+# include "tools.hh"
# include "cloud.hh"
# include "quat7.hh"
@@ -66,49 +69,47 @@
template <typename P, typename T1, typename T2>
inline
p_array<P>
- icp_(const p_array<P>& C,
- const p_array<P>&,
- std::pair<T1,T2>& map)
+ icp_(p_array<P>& C,
+ const p_array<P>& X,
+ std::pair<T1,T2>&)
{
trace::entering("registration::impl::icp_");
unsigned int k;
quat7<P::dim> old_qk, qk;
- float err, err_bis;
- p_array<P> Ck(C), Xk(C);
+ 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 = 1e-3;
+ const float epsilon = 1e-2;
- //step 1
+ //// step 1
k = 0;
- Ck = C;
-
do {
- std::cout << "step2: projection" << std::endl;
- //step 2
- err_bis = projection::fill_Xk(Ck, map, Xk);
+ //// step 2
+ //err_bis = projection::fill_Xk(Ck, map, Xk);
+ //projection::de_base(Ck, X, Xk, err_bis);
+ projection::memo(Ck, X, Xk, err_bis);
- std::cout << "step2.1: center" << std::endl;
mu_Xk = center(Xk);
- std::cout << "step3: Compute qk" << std::endl;
- // step 3
+ //// step 3
old_qk = qk;
qk = match(C, mu_C, Xk, mu_Xk);
- std::cout << "step4: apply qk" << std::endl;
- // step 4
+ //// step 4
qk.apply_on(C, Ck); // Ck+1 = qk(C)
- // err = d(Ck+1,Xk)
+ //// err = d(Ck+1,Xk)
err = rms(Ck, Xk);
+ std::cout << "error :" << err << std::endl;
++k;
- std::cout << "error is " << err << std::endl;
} while (k < 3 || (qk - old_qk).sqr_norm() > epsilon);
+ std::cout << "nb of iterations : " << k <<
std::endl;
trace::exiting("registration::impl::icp_");
return Ck;
}
@@ -116,42 +117,6 @@
} // end of namespace mln::registration::impl
- //FIXME: move?
- namespace convert
- {
- template <typename T>
- const image3d<T>&
- to_image_3d(const image3d<T>& img)
- {
- return img;
- }
-
- template <typename T>
- image3d<T>&
- to_image_3d(image3d<T>& img)
- {
- return img;
- }
-
- template <typename T>
- image3d<T>
- to_image_3d(const image2d<T>& img)
- {
- point3d pmin(img.domain().pmin()[0], img.domain().pmin()[1], -10);
- point3d pmax(img.domain().pmax()[0], img.domain().pmax()[1], 10);
- image3d<T> img3d(box3d(pmin,pmax));
-
- mln_piter(image3d<T>) p(img3d.domain());
- for_all(p)
- {
- if (p[2] == 0)
- img3d(p) = exact(img)(point2d(p[0],p[1]));
- }
- return img3d;
- }
- }
-
-
//Only for 2d and 3d image
template <typename I, typename J>
inline
@@ -163,44 +128,38 @@
mln_precondition(exact(cloud_).has_data());
mln_precondition(exact(surface_).has_data());
- std::cout << "convert to image3d" << std::endl;
//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_));
-
- std::cout << "chamfer" << std::endl;
-
- //FIXME: not a chamfer. etienne?
+ /*
//create a pair (distance map, closest point)
- // window<dpoint3d> win3d;
- w_window<dpoint3d, float> chamfer; // = make::w_window(win3d, fun);
- std::pair<mln_ch_value(I3d,float),
mln_ch_value(I3d,mln_point(I3d)) > maps =
- dt::chamfer(surface, chamfer);
+ bool w[27] = {true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true,
+ true, true, true, true, true, true, true, true, true};
+ window<mln_dpoint(I3d)> win3d = make::window3d(w);
+ fun::cham<point3d> fun;
+ w_window<mln_dpoint(I3d), float> chamfer = make::w_window(win3d,
fun);
+ */
+ std::pair<mln_ch_value(I3d,float),
mln_ch_value(I3d,mln_point(I3d)) > maps;// =
+ //dt::chamfer(surface, chamfer);
- std::cout << "Build p_array" << std::endl;
- //build p_arrays.
- p_array<mln_point(I3d)> c,x;
- mln_piter(I3d) p1(cloud.domain());
- for_all(p1)
- if (exact(cloud)(p1))
- c.append(p1);
-
- mln_piter(I3d) p2(surface.domain());
- for_all(p2)
- if (exact(surface)(p2))
- x.append(p2);
+ //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);
- std::cout << "Start ICP" << std::endl;
p_array<mln_point(I3d)> res = impl::icp_(c, x, maps);
//to 2d : projection (FIXME:if 3d)
+ //mln_concrete(I) output = convert::to_image2d(res)?
mln_concrete(I) output(exact(cloud_).domain());
- for (unsigned i; i < res.npoints(); i++)
+ 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;
}
Index: sandbox/jardonnet/registration/projection.hh
--- sandbox/jardonnet/registration/projection.hh (revision 1814)
+++ sandbox/jardonnet/registration/projection.hh (working copy)
@@ -21,16 +21,18 @@
for (size_t i = 0; i < Ck.npoints(); ++i)
{
+ //FIXME: bof
+ //if (map.second.has(Ck[i]))
+ //{
//x[i] := Ck[i] closest point in X
Xk.hook_()[i] = map.second(Ck[i]);
//err := Distance between Ck[i] and its closest point
err += map.first(Ck[i]);
+ //}
}
return err /= Ck.npoints();
}
-
-
template <typename P>
void de_base(// input
const p_array<P>& Ck,
@@ -63,7 +65,58 @@
}
err /= Ck.npoints();
}
+
+
+ template <typename P>
+ void memo(// input
+ const p_array<P>& Ck,
+ const p_array<P>& X,
+ // inout
+ p_array<P>& Xk,
+ float& err)
+ {
+ //FIXME: remove static
+ //FIXME: domain generated by X and C's domain?
+ static image3d<point3d> map(1000,1000,10);
+ static image3d<bool> mapset(1000,1000,10);
+
+ assert(Ck.npoints() == Xk.npoints());
+
+ err = 0.f;
+
+ for (size_t i = 0; i < Ck.npoints(); ++i)
+ {
+ float best_d;
+ if (mapset(Ck[i]) == false)
+ {
+ algebra::vec<P::dim,float> Cki = Ck[i];
+ algebra::vec<P::dim,float> best_x = X[0];
+ best_d = norm::l2(Cki - best_x);
+ for (size_t j = 1; j < X.npoints(); ++j)
+ {
+ algebra::vec<P::dim,float> Xj = X[j];
+ float d = norm::l2(Cki - Xj);
+ if (d < best_d)
+ {
+ best_d = d;
+ best_x = Xj;
}
}
+ Xk.hook_()[i] = algebra::to_point<P>(best_x);
+ map(Ck[i]) = Xk[i];
+ mapset(Ck[i]) = true;
+ }
+ else
+ {
+ Xk.hook_()[i] = map(Ck[i]);
+ }
+ err += best_d;
+ }
+ err /= Ck.npoints();
+ }
+
+ } // end of namespace projection
+
+} // end of namespace mln
#endif // ndef PROJECTION_HH
Index: sandbox/jardonnet/registration/tools.hh
--- sandbox/jardonnet/registration/tools.hh (revision 0)
+++ sandbox/jardonnet/registration/tools.hh (revision 0)
@@ -0,0 +1,137 @@
+#ifndef REGISTRATION_TOOL_HH
+# define REGISTRATION_TOOL_HH
+
+// temporary
+
+# include <mln/algebra/mat.hh>
+# include <mln/core/p_array.hh>
+
+namespace mln
+{
+
+ //FIXME: move?
+ namespace convert
+ {
+
+ template <typename I>
+ inline
+ p_array<mln_point(I)>
+ to_p_array(const Image<I>& img_)
+ {
+ const I& img = exact(img_);
+
+ p_array<mln_point(I)> a;
+
+ mln_piter(I) p(img.domain());
+ for_all(p)
+ if (img(p))
+ a.append(p);
+ return a;
+ }
+
+ //FIXME: to write
+ /*
+ template <typename A>
+ inline
+ image2d<mln_value(A)>
+ to_image2d(const A& a)
+ {
+ image2d<mln_value(A)> img(a.bbox());
+ for (size_t i = 0; i < a.npoints(); i++)
+ {
+ point2d p(res[i][0], res[i][1]);
+ //FIXME: BOF
+ //if (output.has(p))
+ output(p) = true;
+ }
+ }
+ */
+
+ template <typename T>
+ inline
+ const image3d<T>&
+ to_image_3d(const image3d<T>& img)
+ {
+ return img;
+ }
+
+ template <typename T>
+ image3d<T>&
+ to_image_3d(image3d<T>& img)
+ {
+ return img;
+ }
+
+ template <typename T>
+ inline
+ image3d<T>
+ to_image_3d(const image2d<T>& img)
+ {
+ point3d pmin(img.domain().pmin()[0], img.domain().pmin()[1], -1);
+ point3d pmax(img.domain().pmax()[0], img.domain().pmax()[1], 1);
+ image3d<T> img3d(box3d(pmin,pmax));
+
+ mln_piter(image3d<T>) p(img3d.domain());
+ for_all(p)
+ {
+ if (p[2] == 0)
+ img3d(p) = exact(img)(point2d(p[0],p[1]));
+ }
+ return img3d;
+ }
+
+ } // end of namespace convert
+
+
+
+ namespace fun
+ {
+ //FIXME: temporary
+ template <typename C, typename T= float>
+ struct cham : public Function_p2v< cham<C,T> >
+ {
+ typedef T result;
+ //bad
+ T operator()(dpoints_fwd_piter<mln::dpoint_<mln::grid::cube, int>
& v) const
+ {
+ C o = C::origin;
+ if (v < o)
+ return 1.;
+ else
+ return 0.;
+ }
+ };
+ } // end of namespace fun
+
+
+
+ namespace algebra
+ {
+
+ template<unsigned n, unsigned m, typename T>
+ mat<m,n,T>
+ trans(const mat<n,m,T>& matrice)
+ {
+ mat<m,n,T> tmp;
+ for (unsigned i = 0; i < n; ++i)
+ for (unsigned j = 0; j < m; ++j)
+ tmp(j,i) = matrice(i,j);
+ return tmp;
+ }
+
+ // trace
+
+ template<unsigned n, typename T> inline
+ float tr(const mat<n,n,T>& m)
+ {
+ float f = 0.f;
+ for (unsigned i = 0; i < n; ++i)
+ f += m(i,i);
+ return f;
+ }
+
+ } // end of namespace algebra
+
+} // end of namespace mln
+
+#endif // REGISTRATION_TOOLS_HH