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
00020
00021
00022
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
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)
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)
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)
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
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
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
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
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
00202
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
00235 vnl_double_3x3 dR = R_prev.transpose()*R_curr;
00236
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 }