1792: Icp : n dim, refactored, uses p_array, vec -> rounded point proc.

https://svn.lrde.epita.fr/svn/oln/trunk/milena Index: ChangeLog from Ugo Jardonnet <ugo.jardonnet@lrde.epita.fr> Icp : n dim, refactored, uses p_array, vec -> rounded point proc. * mln/core/point.hh: Fix convertion to vec. * mln/algebra/quat.hh: Fix namespace. * mln/algebra/vec.hh: add to_point procedure. * sandbox/jardonnet/test/icp.cc, * sandbox/jardonnet/registration/quat7.hh, * sandbox/jardonnet/registration/cloud.hh, * sandbox/jardonnet/registration/jacobi.hh, * sandbox/jardonnet/registration/icp.hh, * sandbox/jardonnet/registration/projection.hh, * sandbox/jardonnet/registration/quat/all.hh, * sandbox/jardonnet/registration/quat/rotation.hh: Update for p_array and n dim (not ready yet). * sandbox/jardonnet/registration/quat/interpol.hh: Remove. Provided by qut.hh mln/algebra/quat.hh | 24 ++++----- mln/algebra/vec.hh | 12 ++++ sandbox/jardonnet/registration/cloud.hh | 37 ++++++++------ sandbox/jardonnet/registration/icp.hh | 35 ++++++++------ sandbox/jardonnet/registration/jacobi.hh | 10 ++-- sandbox/jardonnet/registration/projection.hh | 33 ++++++------- sandbox/jardonnet/registration/quat/all.hh | 1 sandbox/jardonnet/registration/quat/rotation.hh | 21 +++++--- sandbox/jardonnet/registration/quat7.hh | 60 ++++++++++++++---------- sandbox/jardonnet/test/icp.cc | 4 - 10 files changed, 136 insertions(+), 101 deletions(-) Index: mln/core/point.hh Index: mln/algebra/quat.hh --- mln/algebra/quat.hh (revision 1791) +++ mln/algebra/quat.hh (working copy) @@ -30,7 +30,7 @@ /*! \file mln/algebra/quat.hh * - * \brief Define a class for quaternion values. + * \brief Define a class for quaternion algebra values. */ # include <cmath> @@ -44,12 +44,13 @@ # include <mln/algebra/vec.hh> # include <mln/norm/l2.hh> +//FIXME: pow, exp etc... are def here and in value::... namespace mln { // Fwd decls. - namespace value { class quat; } + namespace algebra { class quat; } namespace literal { struct zero_t; struct one_t; } @@ -114,16 +115,15 @@ - namespace value + namespace algebra { - // FIXME doesn't compile - + // FIXME value::Vectorial ??? value ??? class quat : - public Vectorial< quat > + public value::Vectorial< quat > , - public internal::value_like_< algebra::vec<4, float>, // Equivalent. + public value::internal::value_like_< algebra::vec<4, float>, // Equivalent. algebra::vec<4, float>, // Encoding. algebra::vec<4, float>, // Interoperation. quat > // Exact. @@ -606,7 +606,7 @@ quat slerp_2(const quat& p, const quat& q, float h) { assert(interpol_ok(p, q, h)); - quat tmp = p * value::pow(p.conj() * q, h); + quat tmp = p * pow(p.conj() * q, h); assert(about_equal(tmp, slerp(p, q, h))); return tmp; } @@ -615,7 +615,7 @@ quat slerp_3(const quat& p, const quat& q, float h) { assert(interpol_ok(p, q, h)); - quat tmp = value::pow(p * q.conj(), 1 - h) * q; + quat tmp = pow(p * q.conj(), 1 - h) * q; assert(about_equal(tmp, slerp(p, q, h))); return tmp; } @@ -624,7 +624,7 @@ quat slerp_4(const quat& p, const quat& q, float h) { assert(interpol_ok(p, q, h)); - quat tmp = value::pow(q * p.conj(), h) * p; + quat tmp = pow(q * p.conj(), h) * p; assert(about_equal(tmp, slerp(p, q, h))); return tmp; } @@ -633,7 +633,7 @@ quat slerp_5(const quat& p, const quat& q, float h) { assert(interpol_ok(p, q, h)); - quat tmp = q * value::pow(q.conj() * p, 1 - h); + quat tmp = q * pow(q.conj() * p, 1 - h); assert(about_equal(tmp, slerp(p, q, h))); return tmp; } @@ -641,7 +641,7 @@ # endif // ! MLN_INCLUDE_ONLY - } // end of namespace mln::value + } // end of namespace mln::algebra } // end of namespace mln Index: mln/algebra/vec.hh --- mln/algebra/vec.hh (revision 1791) +++ mln/algebra/vec.hh (working copy) @@ -549,6 +549,18 @@ return tmp; } + + template <typename P, unsigned n> + inline + P + to_point(const vec<n,float>& v) + { + P tmp; + for (unsigned i = 0; i < P::dim; ++i) + tmp[i] = round(v[i]); + return tmp; + } + # endif // MLN_INCLUDE_ONLY } // end of namespace mln::algebra Index: sandbox/jardonnet/test/icp.cc --- sandbox/jardonnet/test/icp.cc (revision 1791) +++ sandbox/jardonnet/test/icp.cc (working copy) @@ -1,4 +1,4 @@ -#include <mln/core/image2d.hh> +#include <mln/core/image3d.hh> #include <mln/io/ppm/load.hh> #include <mln/io/ppm/save.hh> @@ -9,7 +9,7 @@ { using namespace mln; - image2d< value::rgb8 > img; + image3d< value::rgb8 > img; registration::icp(img,img); } Index: sandbox/jardonnet/registration/quat7.hh --- sandbox/jardonnet/registration/quat7.hh (revision 1791) +++ sandbox/jardonnet/registration/quat7.hh (working copy) @@ -6,6 +6,7 @@ # include <algorithm> # include <mln/algebra/mat.hh> +# include <mln/core/p_array.hh> # include "quat/all.hh" # include "jacobi.hh" @@ -49,16 +50,17 @@ namespace mln { + template <unsigned n> struct quat7 { - value::quat _qR; - vec3f _qT; + algebra::quat _qR; + algebra::vec<n,float> _qT; quat7() { } - quat7(const value::quat& qR, const vec3f& qT) : + quat7(const algebra::quat& qR, const algebra::vec<n,float>& qT) : _qR(qR), _qT(qT) { @@ -76,19 +78,21 @@ // quat7 is an object-function - vec3f operator()(const vec3f& v) const + algebra::vec<n,float> operator()(const algebra::vec<n,float>& v) const { return rotate(_qR, v) + _qT; } - void apply_on(const std::vector< vec3f >& input, std::vector< vec3f >& output) const + template <typename P> + void apply_on(const p_array<P>& input, p_array<P>& output) const { - assert(input.size() == output.size()); + assert(input.npoints() == output.npoints()); assert(_qR.is_unit()); - std::transform(input.begin(), input.end(), - output.begin(), - *this); + //FIXME utiliser equivalent pour p_array + //std::transform(input.begin(), input.end(), + // output.begin(), + // *this); } }; @@ -107,42 +111,48 @@ } - quat7 match(const vecs_t& P, - const vec3f& mu_P, - const vecs_t& Xk, - const vec3f& mu_Xk) + template <typename P> + quat7<P::dim> match(const p_array<P>& C, + const algebra::vec<P::dim,float>& mu_C, + const p_array<P>& Xk, + const algebra::vec<P::dim,float>& mu_Xk) { - assert(P.size() == Xk.size()); + assert(C.npoints() == Xk.npoints()); // qR - algebra::mat<3,3,float> Ck; - for (unsigned i = 0; i < P.size(); ++i) - Ck += make::mat(P[i] - mu_P) * trans(make::mat(Xk[i] - mu_Xk)); - Ck /= P.size(); + //FIXME : use P::dim ? + algebra::mat<P::dim,P::dim,float> Mk; + for (unsigned i = 0; i < C.npoints(); ++i) + { + algebra::vec<P::dim,float> Ci = C[i]; + algebra::vec<P::dim,float> Xki = Xki; + Mk += make::mat(Ci - mu_C) * trans(make::mat(Xki - mu_Xk)); + } + Mk /= C.npoints(); - const algebra::mat<3,3,float> Ak = Ck - trans(Ck); + 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 <...> algebra::mat<4,4,float> Qk; - Qk(0,0) = tr(Ck); + Qk(0,0) = tr(Mk); put(trans(D), 0,1, Qk); put(D, 1,0, Qk); - put(Ck + trans(Ck) - algebra::mat<3,3,float>::identity() * tr(Ck), 1,1, Qk); + put(Mk + trans(Mk) - algebra::mat<P::dim,P::dim,float>::identity() * tr(Mk), 1,1, Qk); - value::quat qR; + algebra::quat qR; jacobi(Qk, qR); // qT - const vec3f qT = mu_Xk - rotate(qR, mu_P); + const algebra::vec<P::dim,float> qT = mu_Xk - rotate(qR, mu_C); - return quat7(qR, qT); + return quat7<P::dim>(qR, qT); } -} +} //end of namespace mln #endif // ndef QUAT7_HH Index: sandbox/jardonnet/registration/cloud.hh --- sandbox/jardonnet/registration/cloud.hh (revision 1791) +++ sandbox/jardonnet/registration/cloud.hh (working copy) @@ -8,6 +8,7 @@ # include <sstream> # include <mln/algebra/vec.hh> +# include <mln/core/p_array.hh> namespace mln { @@ -15,32 +16,36 @@ namespace registration { - typedef algebra::vec<3, float> vec3f; - - - vec3f center(const std::vector< vec3f >& vecs) + template <typename P> + P center(const p_array<P>& a) + { + algebra::vec<P::dim,float> c; + for (size_t i = 0; i < a.npoints(); ++i) { - vec3f c; - for (size_t i = 0; i < vecs.size(); ++i) - c += vecs[i]; - return c / vecs.size(); + algebra::vec<P::dim,float> ai = a[i]; + c += ai; + } + + return algebra::to_point<P>(c / a.npoints()); } - // FIXME : move - float sqr_norm(const vec3f& v) + // FIXME : move //exist for P? + template <typename P> + float sqr_norm(const P& v) { return v[1] * v[1] + v[2] * v[2] + v[3] * v[3]; } - float rms(const std::vector< vec3f >& vecs1, - const std::vector< vec3f >& vecs2) + template <typename P> + float rms(const p_array<P>& a1, + const p_array<P>& a2) { - assert(vecs1.size() == vecs2.size()); + assert(a1.npoints() == a2.npoints()); float f = 0.f; - for (size_t i = 0; i < vecs1.size(); ++i) - f += sqr_norm(vecs1[i] - vecs2[i]); - return f / vecs1.size(); + for (size_t i = 0; i < a1.npoints(); ++i) + f += sqr_norm(a1[i] - a2[i]); + return f / a1.npoints(); } } Index: sandbox/jardonnet/registration/jacobi.hh --- sandbox/jardonnet/registration/jacobi.hh (revision 1791) +++ sandbox/jardonnet/registration/jacobi.hh (working copy) @@ -7,14 +7,16 @@ // from num. rec. in C +namespace mln +{ #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); -void jacobi(mln::algebra::mat<4,4,float> a, mln::value::quat& q) + void jacobi(algebra::mat<4,4,float> a, algebra::quat& q) { float dd, d[4]; - mln::algebra::mat<4,4,float> v; + algebra::mat<4,4,float> v; int j,iq,ip,i = 0; float tresh,theta,tau,t,sm,s,h,g,c,b[4],z[4]; for (ip=0;ip<4;ip++) { @@ -39,7 +41,7 @@ iq = ip; dd = d[ip]; } - q = mln::value::quat(v(0,iq), + q = algebra::quat(v(0,iq), v(1,iq), v(2,iq), v(3,iq)); @@ -103,6 +105,6 @@ } } - +} #endif // ndef JACOBI_HH Index: sandbox/jardonnet/registration/icp.hh --- sandbox/jardonnet/registration/icp.hh (revision 1791) +++ sandbox/jardonnet/registration/icp.hh (working copy) @@ -33,12 +33,12 @@ * \brief image registration */ -# include <mln/value/quat.hh> +# include <mln/algebra/quat.hh> # include <mln/algebra/vec.hh> -typedef mln::algebra::vec<3, float> vec3f; -typedef std::vector< vec3f > vecs_t; +//typedef mln::algebra::vec<3, float> vec3f; +//typedef mln::p_array< vec3f > vecs_t; #include "cloud.hh" #include "quat7.hh" @@ -65,39 +65,44 @@ namespace impl { + template <typename P> inline void - icp_(const vecs_t& P, - const vecs_t& X) + icp_(const p_array<P>& C, + const p_array<P>& X) { trace::entering("registration::impl::icp_"); unsigned int k; - quat7 old_qk, qk; + quat7<P::dim> old_qk, qk; float err, err_bis; - vecs_t Pk(P.size()), Xk(Pk.size()); - vec3f mu_P = center(P), mu_Xk; + p_array<P> Ck, Xk; + Ck.reserve(C.npoints()); + Xk.reserve(Ck.npoints()); + algebra::vec<P::dim,float> mu_C = center(C), mu_Xk; const float epsilon = 1e-3; //step 1 k = 0; - Pk = P; + Ck = C; do { //step 2 FIXME : etienne - projection::de_base(Pk, X, Xk, mu_Xk, err_bis); + projection::de_base(Ck, X, Xk, err_bis); + + mu_Xk = center(Xk); // step 3 old_qk = qk; - qk = match(P, mu_P, Xk, mu_Xk); + qk = match(C, mu_C, Xk, mu_Xk); // step 4 - qk.apply_on(P, Pk); // Pk+1 = qk(P) + qk.apply_on(C, Ck); // Ck+1 = qk(C) - // err = d(Pk+1,Xk) - err = rms(Pk, Xk); + // err = d(Ck+1,Xk) + err = rms(Ck, Xk); ++k; } while (k < 3 || (qk - old_qk).sqr_norm() > epsilon); @@ -119,7 +124,7 @@ mln_precondition(exact(cloud).has_data()); mln_precondition(exact(surface).has_data()); - vecs_t a,b; // FIXME : to built. + p_array<mln_point(I)> a,b; // FIXME : to built. impl::icp_(a, b); Index: sandbox/jardonnet/registration/projection.hh --- sandbox/jardonnet/registration/projection.hh (revision 1791) +++ sandbox/jardonnet/registration/projection.hh (working copy) @@ -10,40 +10,37 @@ namespace projection { - template <class Pk_t, class X_t, class Xk_t> + template <typename P> void de_base(// input - const Pk_t& Pk, - const X_t& X, + const p_array<P>& Ck, + const p_array<P>& X, // inout - Xk_t& Xk, - // output - algebra::vec<3, float>& mu_Xk, + p_array<P>& Xk, float& err) { - assert(Pk.size() == Xk.size()); + assert(Ck.npoints() == Xk.npoints()); err = 0.f; - mu_Xk = make::vec(0,0,0); - for (size_t i = 0; i < Pk.size(); ++i) + for (size_t i = 0; i < Ck.npoints(); ++i) { - algebra::vec<3,float> best_x = X[0]; - float best_d = norm::l2(Pk[i] - best_x); - for (size_t j = 1; j < X.size(); ++j) + algebra::vec<P::dim,float> Cki = Ck[i]; + algebra::vec<P::dim,float> best_x = X[0]; + float best_d = norm::l2(Cki - best_x); + for (size_t j = 1; j < X.npoints(); ++j) { - float d = norm::l2(Pk[i] - X[j]); + algebra::vec<P::dim,float> Xj = X[j]; + float d = norm::l2(Cki - Xj); if (d < best_d) { best_d = d; - best_x = X[j]; + best_x = Xj; } } - Xk[i] = best_x; - mu_Xk += Xk[i]; + Xk.hook_()[i] = algebra::to_point<P>(best_x); err += best_d; } - mu_Xk /= Pk.size(); - err /= Pk.size(); + err /= Ck.npoints(); } } Index: sandbox/jardonnet/registration/quat/all.hh --- sandbox/jardonnet/registration/quat/all.hh (revision 1791) +++ sandbox/jardonnet/registration/quat/all.hh (working copy) @@ -2,7 +2,6 @@ # define QUAT_ALL_HH -# include "interpol.hh" # include "rotation.hh" Index: sandbox/jardonnet/registration/quat/rotation.hh --- sandbox/jardonnet/registration/quat/rotation.hh (revision 1791) +++ sandbox/jardonnet/registration/quat/rotation.hh (working copy) @@ -10,26 +10,30 @@ # include <mln/algebra/vec.hh> # include <mln/make/vec.hh> # include <mln/make/mat.hh> -# include <mln/value/quat.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 { - vec3f rotate(const value::quat& q, const vec3f& p) + // 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 * value::quat(0. ,p) * q.inv()).v(); + return (q * algebra::quat(0. ,p) * q.inv()).v(); } - - bool check_rotation(const algebra::mat<3,3,float>& mat, - const value::quat& q) + //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()); - vec3f + algebra::vec<n,float> tmp = make::vec(rand(), rand(), rand()), p = tmp / norm::l2(tmp), p_rot_1 = rotate(q, p), @@ -38,7 +42,8 @@ } - algebra::mat<3,3,float> quat2mat(const value::quat& q) + //FIXME : switch to n dim. + algebra::mat<3,3,float> quat2mat(const algebra::quat& q) { assert(q.is_unit()); float
participants (1)
-
Ugo Jardonnet