contrib/gel/mrc/vpgl/algo/vpgl_interpolate.cxx
Go to the documentation of this file.
00001 #include "vpgl_interpolate.h"
00002 #include <vnl/vnl_math.h>
00003 #include <vnl/algo/vnl_complex_eigensystem.h>
00004 #include <vcl_cmath.h>
00005 #include <vcl_complex.h>
00006 #include <vgl/vgl_point_3d.h>
00007 #if 0
00008 #include <vgl/vgl_vector_3d.h>
00009 #endif
00010 #include <vgl/algo/vgl_rotation_3d.h>
00011 
00012 vnl_double_3x3 vpgl_interpolate::logR(vnl_double_3x3 const& R)
00013 {
00014   vnl_double_3x3 log_r;
00015   log_r.fill(0.0);
00016   double pi = vnl_math::pi;
00017   double trace = R[0][0]+R[1][1]+R[2][2];
00018   double tol = 1.0e-10;
00019   //special case when the rotation is pi
00020   //In this case, the normal log formula is singular and there are two
00021   //solutions given by r = +-pi[v], where v is a unit length eigenvector of R
00022   //associated with the eigenvalue +1.
00023   if (vcl_fabs(trace + 1.0)<tol)
00024   {
00025     vnl_double_3x3 I; I.fill(0.0);
00026     vnl_complex_eigensystem ce(R, I);
00027     for (unsigned i = 0; i<3; ++i){
00028       vcl_complex<double> eigenv = ce.eigen_value(i);
00029 
00030       if (vcl_fabs(eigenv.imag())<tol&&vcl_fabs(eigenv.real()-1.0)<tol)
00031       {
00032         vnl_vector<vcl_complex<double> > vr =
00033           ce.right_eigen_vector(i);
00034         log_r[0][1] = -pi*vr[2].real(); log_r[0][2] =  pi*vr[1].real();
00035         log_r[1][0] =  pi*vr[2].real(); log_r[1][2] = -pi*vr[0].real();
00036         log_r[2][0] = -pi*vr[1].real(); log_r[2][1] =  pi*vr[0].real();
00037         return log_r;
00038       }
00039     }
00040     vcl_cerr << "In vpgl_interpolate::log_r - shouldn't happen! FIX!!!!\n";
00041     return log_r;
00042   }
00043   //The usual case where a unique solution exists
00044   double cos_phi = 0.5*(trace -1);
00045   double sin_phi = vcl_sqrt(1.0 - cos_phi*cos_phi);
00046   double phi = vcl_asin(sin_phi);
00047   log_r = R - R.transpose();
00048   if (vcl_fabs(sin_phi)>tol)
00049     log_r *= (0.5*phi)/sin_phi;
00050   else log_r *= 0.5;
00051   return log_r;
00052 }
00053 
00054 vnl_double_3x3 vpgl_interpolate::expr(vnl_double_3x3 const& r)
00055 {
00056   vnl_double_3x3 ex;
00057   double tol = 1.0e-10;
00058   double norm_r = vcl_sqrt(r[0][1]*r[0][1]+r[0][2]*r[0][2]+r[1][2]*r[1][2]);
00059   if (norm_r<tol)//the case of an identity rotation
00060   {
00061     ex.set_identity();
00062     return ex;
00063   }
00064   double sin_r = vcl_sin(norm_r), cos_r = vcl_cos(norm_r);
00065   vnl_double_3x3 I, rsq = r*r;
00066   I.set_identity();
00067   ex = I + (sin_r/norm_r)*r + ((1-cos_r)/(norm_r*norm_r))*rsq;
00068   return ex;
00069 }
00070 
00071 vnl_double_3x3 vpgl_interpolate::A(vnl_double_3x3 const& r)
00072 {
00073   vnl_double_3x3 a;
00074   double tol = 1.0e-10;
00075   double norm_r = vcl_sqrt(r[0][1]*r[0][1]+r[0][2]*r[0][2]+r[1][2]*r[1][2]);
00076   double norm_r_sq = norm_r*norm_r;
00077   double norm_r_cu = norm_r*norm_r_sq;
00078   if (norm_r<tol)//the case of an identity rotation
00079   {
00080     a.set_identity();
00081     return a;
00082   }
00083   double sin_r = vcl_sin(norm_r), cos_r = vcl_cos(norm_r);
00084   vnl_double_3x3 I, rsq = r*r;
00085   I.set_identity();
00086   a = I + ((1-cos_r)/norm_r_sq)*r + ((norm_r - sin_r)/norm_r_cu)*rsq;
00087   return a;
00088 }
00089 
00090 vnl_double_3x3 vpgl_interpolate::Ainv(vnl_double_3x3 const& r)
00091 {
00092   vnl_double_3x3 ainv;
00093   double tol = 1.0e-10;
00094   double norm_r = vcl_sqrt(r[0][1]*r[0][1]+r[0][2]*r[0][2]+r[1][2]*r[1][2]);
00095   double norm_r_sq = norm_r*norm_r;
00096   if (norm_r<tol)//the case of an identity rotation
00097   {
00098     ainv.set_identity();
00099     return ainv;
00100   }
00101   double sin_r = vcl_sin(norm_r), cos_r = vcl_cos(norm_r);
00102   vnl_double_3x3 I, rsq = r*r;
00103   I.set_identity();
00104   ainv = I + 0.5*r + ((2.0*sin_r-norm_r*(1+cos_r))/(2*norm_r_sq*sin_r))*rsq;
00105   return ainv;
00106 }
00107 
00108 vcl_vector<vnl_double_3x3> vpgl_interpolate::interpolateR(vnl_double_3x3 R0,
00109                                                           vnl_double_3x3 R1,
00110                                                           unsigned n_between)
00111 {
00112   vnl_double_3x3 r = R0.transpose()*R1;
00113   vnl_double_3x3 log_r = vpgl_interpolate::logR(r);
00114   //the rotation interpolation parameter, s, step spacing
00115   double s_interval = 1.0/(n_between+1);
00116   vcl_vector<vnl_double_3x3> temp;
00117   for (double s = s_interval; s<1.0; s+=s_interval)
00118   {
00119     vnl_double_3x3 R = vpgl_interpolate::expr(log_r*s);
00120     temp.push_back(R0*R);
00121   }
00122   return temp;
00123 }
00124 
00125 
00126 vnl_double_3x3 vpgl_interpolate::interpolateR(double alpha, vnl_double_3x3 R0, vnl_double_3x3 R1)
00127 {
00128   vnl_double_3x3 r = R0.transpose()*R1;
00129   vnl_double_3x3 log_r = vpgl_interpolate::logR(r);
00130 
00131   vnl_double_3x3 R = vpgl_interpolate::expr(log_r*alpha);
00132 
00133   return R0*R;
00134 }
00135 
00136 
00137 void vpgl_interpolate::interpolateRt(vnl_double_3x3 R0,
00138                                      vnl_double_3 t0,
00139                                      vnl_double_3x3 R1,
00140                                      vnl_double_3 t1,
00141                                      unsigned n_between,
00142                                      vcl_vector<vnl_double_3x3>& Rintrp,
00143                                      vcl_vector<vnl_double_3>& tintrp)
00144 {
00145   Rintrp.clear();
00146   tintrp.clear();
00147   vnl_double_3x3 r = R0.transpose()*R1;
00148   vnl_double_3 dt = t1 - t0;
00149   vnl_double_3x3 log_r = vpgl_interpolate::logR(r);
00150   //the rotation interpolation parameter, s, step spacing
00151   double s_interval = 1.0/(n_between+1);
00152   vcl_vector<vnl_double_3x3> temp;
00153   for (double s = s_interval; s<1.0; s+=s_interval)
00154   {
00155     vnl_double_3x3 d_log_r = log_r*s;
00156     vnl_double_3x3 R = vpgl_interpolate::expr(log_r*s);
00157     Rintrp.push_back(R0*R);
00158      vnl_double_3x3 a = vpgl_interpolate::A(d_log_r);
00159      vnl_double_3x3 ainv = vpgl_interpolate::Ainv(d_log_r);
00160      vnl_double_3 sadt = ainv*(s*dt);
00161      vnl_double_3 dlt = a*sadt;
00162      tintrp.push_back(t0+dlt);
00163   }
00164 }
00165 
00166 bool vpgl_interpolate::
00167 interpolate(vpgl_perspective_camera<double> const& cam0,
00168             vpgl_perspective_camera<double> const& cam1,
00169             unsigned n_between,
00170             vcl_vector<vpgl_perspective_camera<double> >& cams)
00171 {
00172   cams.clear();
00173   if (!n_between)
00174     return false;
00175   vpgl_calibration_matrix<double> K0 = cam0.get_calibration();
00176   vpgl_calibration_matrix<double> K1 = cam1.get_calibration();
00177   if (K0 != K1)
00178     return false;
00179   //interpolate camera center
00180   vgl_point_3d<double> c0 = cam0.get_camera_center();
00181   vgl_point_3d<double> c1 = cam1.get_camera_center();
00182   vnl_double_3 t0(c0.x(), c0.y(), c0.z());
00183   vnl_double_3 t1(c1.x(), c1.y(), c1.z());
00184 #if 0
00185   vgl_vector_3d<double> v = (c1 - c0)/(1 + n_between);
00186   vcl_vector<vgl_point_3d<double> > centers;
00187   for (unsigned i = 0; i<n_between; ++i)
00188   {
00189     vgl_point_3d<double> cs = c0 + (i+1)*v;
00190     centers.push_back(cs);
00191   }
00192 #endif
00193   //interpolate rotation
00194   vgl_rotation_3d<double> rot0 = cam0.get_rotation();
00195   vgl_rotation_3d<double> rot1 = cam1.get_rotation();
00196   vnl_double_3x3 R0 = rot0.as_matrix();
00197   vnl_double_3x3 R1 = rot1.as_matrix();
00198   vcl_vector<vnl_double_3x3> Rmats;
00199   vcl_vector<vnl_double_3> tvecs;
00200   vpgl_interpolate::interpolateRt(R0, t0, R1, t1, n_between, Rmats, tvecs);
00201   //  Rmats = vpgl_interpolate::interpolateR(R0,R1,n_between);
00202   // return the interpolated cameras
00203   for (unsigned i = 0; i<n_between; ++i)
00204   {
00205     vgl_rotation_3d<double> rot(Rmats[i]);
00206     vnl_double_3 t = tvecs[i];
00207     vgl_point_3d<double> p(t[0],t[1],t[2]);
00208     vpgl_perspective_camera<double> cam(K0, p, rot);
00209     cams.push_back(cam);
00210   }
00211   return true;
00212 }
00213 
00214 bool vpgl_interpolate::
00215 interpolate_next(vpgl_perspective_camera<double> const& cam_prev,
00216                  vpgl_perspective_camera<double> const& cam_curr,
00217                  double const& rel_step_size,
00218                  vpgl_perspective_camera<double>& cam_next)
00219 {
00220   vpgl_calibration_matrix<double> K_prev = cam_prev.get_calibration();
00221   vpgl_calibration_matrix<double> K_curr = cam_curr.get_calibration();
00222   if (K_prev != K_curr)
00223     return false;
00224     
00225   vgl_point_3d<double> c_prev = cam_prev.get_camera_center();
00226   vgl_point_3d<double> c_curr = cam_curr.get_camera_center();
00227 
00228   vnl_double_3 t_prev(c_prev.x(), c_prev.y(), c_prev.z());
00229   vnl_double_3 t_curr(c_curr.x(), c_curr.y(), c_curr.z());
00230 
00231   vnl_double_3x3 R_prev = cam_prev.get_rotation().as_matrix();
00232   vnl_double_3x3 R_curr = cam_curr.get_rotation().as_matrix();
00233 
00234   // change in rotation
00235   vnl_double_3x3 dR = R_prev.transpose()*R_curr;
00236   // change in translation
00237   vnl_double_3 dt = t_curr - t_prev;
00238 
00239   vnl_double_3x3 log_dR = vpgl_interpolate::logR(dR);
00240   vnl_double_3x3 dR_step = vpgl_interpolate::expr(log_dR*rel_step_size);
00241   
00242   vnl_double_3x3 R_next = R_curr*dR_step;
00243   
00244   vnl_double_3x3 a = vpgl_interpolate::A(log_dR*rel_step_size);
00245   vnl_double_3x3 ainv = vpgl_interpolate::Ainv(log_dR*rel_step_size);
00246   vnl_double_3 sadt = ainv*(rel_step_size*dt);
00247   vnl_double_3 dlt = a*sadt;
00248   vnl_double_3 t_next = t_curr + dlt;
00249   
00250   vgl_rotation_3d<double> rot_next(R_next);
00251   vgl_point_3d<double> p_next(t_next[0],t_next[1],t_next[2]);
00252   
00253   cam_next.set_calibration(K_curr);
00254   cam_next.set_camera_center(p_next);
00255   cam_next.set_rotation(rot_next);
00256 
00257   return true;
00258 }