00001
00002 #include "vpgl_optimize_camera.h"
00003
00004
00005 #include <vnl/vnl_rotation_matrix.h>
00006 #include <vnl/vnl_double_3.h>
00007 #include <vnl/vnl_double_3x3.h>
00008 #include <vnl/algo/vnl_levenberg_marquardt.h>
00009 #include <vgl/vgl_homg_point_2d.h>
00010 #if 0
00011 #include <vgl/algo/vgl_h_matrix_3d.h>
00012 #endif
00013 #include <vgl/algo/vgl_rotation_3d.h>
00014 #include <vcl_cassert.h>
00015
00016
00017 vpgl_orientation_lsqr::
00018 vpgl_orientation_lsqr(const vpgl_calibration_matrix<double>& K,
00019 const vgl_point_3d<double>& c,
00020 const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00021 const vcl_vector<vgl_point_2d<double> >& image_points )
00022 : vnl_least_squares_function(3,2*world_points.size(),no_gradient),
00023 K_(K),
00024 c_(c),
00025 world_points_(world_points),
00026 image_points_(image_points)
00027 {
00028 assert(world_points_.size() == image_points_.size());
00029 }
00030
00031
00032
00033
00034
00035
00036
00037 void
00038 vpgl_orientation_lsqr::f(vnl_vector<double> const& x, vnl_vector<double>& fx)
00039 {
00040 vpgl_perspective_camera<double> cam(K_,c_,vgl_rotation_3d<double>(x));
00041 for (unsigned int i=0; i<world_points_.size(); ++i)
00042 {
00043 vgl_homg_point_2d<double> proj = cam(world_points_[i]);
00044 fx[2*i] = image_points_[i].x() - proj.x()/proj.w();
00045 fx[2*i+1] = image_points_[i].y() - proj.y()/proj.w();
00046 }
00047 }
00048
00049
00050
00051
00052 vpgl_orientation_position_lsqr::
00053 vpgl_orientation_position_lsqr(const vpgl_calibration_matrix<double>& K,
00054 const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00055 const vcl_vector<vgl_point_2d<double> >& image_points )
00056 : vnl_least_squares_function(6,2*world_points.size(),no_gradient),
00057 K_(K),
00058 world_points_(world_points),
00059 image_points_(image_points)
00060 {
00061 assert(world_points_.size() == image_points_.size());
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 void
00071 vpgl_orientation_position_lsqr::f(vnl_vector<double> const& x, vnl_vector<double>& fx)
00072 {
00073 assert(x.size() == 6);
00074 vnl_double_3 w(x[0], x[1], x[2]);
00075 vgl_homg_point_3d<double> t(x[3], x[4], x[5]);
00076 vpgl_perspective_camera<double> cam(K_,t,vgl_rotation_3d<double>(w));
00077 for (unsigned int i=0; i<world_points_.size(); ++i)
00078 {
00079 vgl_homg_point_2d<double> proj = cam(world_points_[i]);
00080 fx[2*i] = image_points_[i].x() - proj.x()/proj.w();
00081 fx[2*i+1] = image_points_[i].y() - proj.y()/proj.w();
00082 }
00083 }
00084
00085 #if 0
00086
00087 void
00088 vpgl_orientation_position_lsqr::trace(int iteration,
00089 vnl_vector<double> const& x,
00090 vnl_vector<double> const& fx)
00091 {
00092 assert(x.size() == 6);
00093 vnl_double_3 w(x[0], x[1], x[2]);
00094 vgl_homg_point_3d<double> t(x[3], x[4], x[5]);
00095 vgl_h_matrix_3d<double> R(vnl_rotation_matrix(w), vnl_double_3(0.0,0.0,0.0));
00096 vpgl_perspective_camera<double> cam(K_,t,R);
00097 #ifdef DEBUG
00098 vcl_cout << "camera =\n" << cam.get_matrix() << vcl_endl;
00099 #endif
00100 }
00101 #endif
00102
00103
00104
00105
00106 vpgl_orientation_position_calibration_lsqr::
00107 vpgl_orientation_position_calibration_lsqr(const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00108 const vcl_vector<vgl_point_2d<double> >& image_points )
00109 : vnl_least_squares_function(10,2*world_points.size(),no_gradient),
00110 world_points_(world_points),
00111 image_points_(image_points)
00112 {
00113 assert(world_points_.size() == image_points_.size());
00114 }
00115
00116
00117
00118
00119
00120
00121
00122 void
00123 vpgl_orientation_position_calibration_lsqr::f(vnl_vector<double> const& x, vnl_vector<double>& fx)
00124 {
00125 assert(x.size() == 10);
00126 vnl_double_3 w(x[0], x[1], x[2]);
00127 vgl_rotation_3d<double> R(w);
00128 vgl_homg_point_3d<double> t(x[3], x[4], x[5]);
00129 vnl_double_3x3 kk;
00130 kk.fill(0);
00131 kk[0][0]=x[6]; kk[0][2]=x[7];
00132 kk[1][1]=x[8]; kk[1][2]=x[9]; kk[2][2]=1.0;
00133
00134
00135 if ( !(kk[0][0]>0) || !(kk[1][1]>0) ) {
00136 for (unsigned int i=0; i<world_points_.size(); ++i) {
00137 fx[2*i] = 100000000;
00138 fx[2*i+1] = 100000000;
00139 }
00140 return;
00141 }
00142
00143 vpgl_calibration_matrix<double> K(kk);
00144 vpgl_perspective_camera<double> cam(K, t, R);
00145 for (unsigned int i=0; i<world_points_.size(); ++i)
00146 {
00147 vgl_homg_point_2d<double> proj = cam(world_points_[i]);
00148 fx[2*i] = image_points_[i].x() - proj.x()/proj.w();
00149 fx[2*i+1] = image_points_[i].y() - proj.y()/proj.w();
00150 }
00151 }
00152
00153
00154
00155
00156
00157
00158
00159 vpgl_perspective_camera<double>
00160 vpgl_optimize_camera::opt_orient(const vpgl_perspective_camera<double>& camera,
00161 const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00162 const vcl_vector<vgl_point_2d<double> >& image_points )
00163 {
00164 const vpgl_calibration_matrix<double>& K = camera.get_calibration();
00165 const vgl_point_3d<double>& c = camera.get_camera_center();
00166 const vgl_rotation_3d<double>& R = camera.get_rotation();
00167
00168
00169 vnl_double_3 w = R.as_rodrigues();
00170
00171 vpgl_orientation_lsqr lsqr_func(K,c,world_points,image_points);
00172 vnl_levenberg_marquardt lm(lsqr_func);
00173 lm.set_trace(true);
00174 lm.minimize(w);
00175
00176 return vpgl_perspective_camera<double>(K, c, vgl_rotation_3d<double>(w) );
00177 }
00178
00179
00180
00181 vpgl_perspective_camera<double>
00182 vpgl_optimize_camera::opt_orient_pos(const vpgl_perspective_camera<double>& camera,
00183 const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00184 const vcl_vector<vgl_point_2d<double> >& image_points )
00185 {
00186 const vpgl_calibration_matrix<double>& K = camera.get_calibration();
00187 vgl_point_3d<double> c = camera.get_camera_center();
00188 const vgl_rotation_3d<double>& R = camera.get_rotation();
00189
00190
00191 vnl_double_3 w = R.as_rodrigues();
00192
00193 vpgl_orientation_position_lsqr lsqr_func(K,world_points,image_points);
00194 vnl_levenberg_marquardt lm(lsqr_func);
00195 vnl_vector<double> params(6);
00196 params[0]=w[0]; params[1]=w[1]; params[2]=w[2];
00197 params[3]=c.x(); params[4]=c.y(); params[5]=c.z();
00198 lm.set_trace(true);
00199 lm.minimize(params);
00200 vnl_double_3 w_min(params[0],params[1],params[2]);
00201 vgl_homg_point_3d<double> c_min(params[3], params[4], params[5]);
00202
00203 return vpgl_perspective_camera<double>(K, c_min, vgl_rotation_3d<double>(w_min) );
00204 }
00205
00206 vpgl_perspective_camera<double>
00207 vpgl_optimize_camera::opt_orient_pos_cal(const vpgl_perspective_camera<double>& camera,
00208 const vcl_vector<vgl_homg_point_3d<double> >& world_points,
00209 const vcl_vector<vgl_point_2d<double> >& image_points,
00210 const double xtol, const unsigned nevals)
00211 {
00212 const vpgl_calibration_matrix<double>& K = camera.get_calibration();
00213 vgl_point_3d<double> c = camera.get_camera_center();
00214 const vgl_rotation_3d<double>& R = camera.get_rotation();
00215 vnl_double_3 w = R.as_rodrigues();
00216
00217 vnl_double_3x3 kk = K.get_matrix();
00218 vpgl_orientation_position_calibration_lsqr lsqr_func(world_points,image_points);
00219 vnl_levenberg_marquardt lm(lsqr_func);
00220 vnl_vector<double> params(10);
00221 params[0]=w[0]; params[1]=w[1]; params[2]=w[2];
00222 params[3]=c.x(); params[4]=c.y(); params[5]=c.z();
00223 params[6]=kk[0][0]; params[7]=kk[0][2];
00224 params[8]=kk[1][1]; params[9]=kk[1][2];
00225
00226 lm.set_x_tolerance(xtol);
00227 lm.set_max_function_evals(nevals);
00228 lm.minimize(params);
00229 vnl_double_3 w_min(params[0],params[1],params[2]);
00230 vgl_homg_point_3d<double> c_min(params[3], params[4], params[5]);
00231 vnl_double_3x3 kk_min;
00232 kk_min.fill(0); kk_min[2][2]=1.0;
00233 kk_min[0][0]=params[6]; kk_min[0][2]=params[7];
00234 kk_min[1][1]=params[8]; kk_min[1][2]=params[9];
00235 vpgl_calibration_matrix<double> K_min(kk_min);
00236 return vpgl_perspective_camera<double>(K_min, c_min, vgl_rotation_3d<double>(w_min));
00237 }