00001 #include "brct_plane_calibrator.h"
00002
00003
00004 #include <vcl_fstream.h>
00005 #include <vcl_cmath.h>
00006 #include <vnl/vnl_math.h>
00007 #include <vnl/vnl_numeric_traits.h>
00008 #include <vgl/algo/vgl_h_matrix_2d_compute_4point.h>
00009 #include <vgl/algo/vgl_h_matrix_2d_compute_linear.h>
00010
00011 brct_plane_calibrator::brct_plane_calibrator()
00012 {
00013 z_back_ = 0;
00014 z_front_ = 0;
00015 pts_3d_.resize(Z_FRONT+1);
00016 corrs_.resize(Z_FRONT+1);
00017 cam_width_.resize(RIGHT+1);
00018 cam_height_.resize(RIGHT+1);
00019 for (int i = 0; i<=RIGHT; i++)
00020 {
00021 cam_width_[i]=0;
00022 cam_height_[i]=0;
00023 }
00024 initial_homographies_.resize(Z_FRONT+1);
00025 current_homographies_.resize(Z_FRONT+1);
00026 for (int i = 0; i<=Z_FRONT; i++)
00027 {
00028 initial_homographies_[i].resize(RIGHT+1);
00029 current_homographies_[i].resize(RIGHT+1);
00030 }
00031 debug_ = false;
00032 points_3d_valid_ = false;
00033 initial_homographies_valid_ = false;
00034 }
00035
00036 brct_plane_calibrator::~brct_plane_calibrator()
00037 {
00038 }
00039
00040 void brct_plane_calibrator::init_corrs()
00041 {
00042 corrs_.clear();
00043 int n_cams = 2;
00044 for (int i = 0; i<=Z_FRONT; i++)
00045 {
00046 int n_pts = pts_3d_[i].size();
00047 vcl_vector<brct_plane_corr_sptr> corrs(n_pts);
00048 for (int j =0; j<n_pts; j++)
00049 corrs[j] = new brct_plane_corr(n_cams, i, j);
00050 corrs_[i]=corrs;
00051 }
00052 }
00053
00054 void brct_plane_calibrator::read_data(vcl_string const& point3d_file)
00055 {
00056 vcl_ifstream instr(point3d_file.c_str());
00057
00058 if (!instr)
00059 {
00060 vcl_cout<<"cannot open the file - "<< point3d_file <<'\n';
00061 return;
00062 }
00063 vcl_string label;
00064 instr >> label;
00065 if (!(label=="Z_BACK:"))
00066 {
00067 vcl_cout << "Bad file format\n";
00068 return;
00069 }
00070 instr >> z_back_;
00071 instr >> label;
00072 if (!(label=="NPOINTS:"))
00073 {
00074 vcl_cout << "Bad file format\n";
00075 return;
00076 }
00077 int npts=0;
00078 instr >> npts;
00079 instr >> label;
00080 if (!(label=="INDEX|X|Y|"))
00081 {
00082 vcl_cout << "Bad file format\n";
00083 return;
00084 }
00085 pts_3d_[Z_BACK].resize(npts);
00086 for (int i = 0; i<npts; i++)
00087 {
00088 int index=0;
00089 instr >> index;
00090 double x = 0, y=0;
00091 instr >> x; instr >> y;
00092 pts_3d_[Z_BACK][index]= vgl_homg_point_2d<double>(x, y);
00093 }
00094 instr >> label;
00095 if (!(label=="Z_FRONT:"))
00096 {
00097 vcl_cout << "Bad file format\n";
00098 return;
00099 }
00100 instr >> z_front_;
00101 instr >> label;
00102 if (!(label=="NPOINTS:"))
00103 {
00104 vcl_cout << "Bad file format\n";
00105 return;
00106 }
00107 instr >> npts;
00108 instr >> label;
00109 if (!(label=="INDEX|X|Y|"))
00110 {
00111 vcl_cout << "Bad file format\n";
00112 return;
00113 }
00114 pts_3d_[Z_FRONT].resize(npts);
00115 for (int i = 0; i<npts; i++)
00116 {
00117 int index=0;
00118 instr >> index;
00119 double x = 0, y=0;
00120 instr >> x; instr >> y;
00121 pts_3d_[Z_FRONT][index]= vgl_homg_point_2d<double>(x, y);
00122 }
00123
00124 this->init_corrs();
00125 points_3d_valid_ = true;
00126 initial_homographies_valid_ = false;
00127 }
00128
00129
00130 bool brct_plane_calibrator::set_image_size(const int cam,
00131 const int width,
00132 const int height)
00133 {
00134 if (cam>RIGHT)
00135 return false;
00136 cam_width_[cam]=width;
00137 cam_height_[cam]=height;
00138 return true;
00139 }
00140
00141 static bool four_image_corners(const int width, const int height,
00142 vcl_vector<vgl_homg_point_2d<double> >& corners)
00143 {
00144 if (!width || !height)
00145 return false;
00146 corners.clear();
00147 vgl_homg_point_2d<double> p00(0,0), p01(width,0);
00148 vgl_homg_point_2d<double> p10(width, height), p11(0, height);
00149 corners.push_back(p00); corners.push_back(p01);
00150 corners.push_back(p10); corners.push_back(p11);
00151 return true;
00152 }
00153
00154 static vgl_homg_point_2d<double>
00155 closest_point(double x0, double y0,
00156 vcl_vector<vgl_homg_point_2d<double> >& pts_3d)
00157 {
00158 double d_min = vnl_numeric_traits<double>::maxval;
00159 vgl_homg_point_2d<double> closest;
00160 unsigned int i_min = 0;
00161 for (unsigned int i = 0; i<pts_3d.size(); ++i)
00162 {
00163 double x=pts_3d[i].x()/pts_3d[i].w(), y=pts_3d[i].y()/pts_3d[i].w();
00164 double d = vcl_sqrt((x-x0)*(x-x0)+(y-y0)*(y-y0));
00165 if (d<d_min)
00166 {
00167 i_min = i;
00168 d_min = d;
00169 closest = pts_3d[i];
00170 }
00171 }
00172
00173
00174 pts_3d[i_min] = vgl_homg_point_2d<double>(1e8, 1e8);
00175 return closest;
00176 }
00177
00178
00179 static bool four_3d_corners(vcl_vector<vgl_homg_point_2d<double> > const& pts_3d,
00180 vcl_vector<vgl_homg_point_2d<double> >& corners)
00181 {
00182 int n = pts_3d.size();
00183 if (n<4)
00184 return false;
00185 corners.clear();
00186
00187 vcl_vector<vgl_homg_point_2d<double> > temp = pts_3d;
00188
00189 double x_min=vnl_numeric_traits<double>::maxval, x_max=-x_min;
00190 double y_min=x_min, y_max=x_max;
00191 for (int i=0; i<n; i++)
00192 if (pts_3d[i].w()<1e-08)
00193 return false;
00194 else
00195 {
00196 double x=pts_3d[i].x()/pts_3d[i].w(), y=pts_3d[i].y()/pts_3d[i].w();
00197 x_min = vnl_math_min(x_min, x);
00198 x_max = vnl_math_max(x_max, x);
00199 y_min = vnl_math_min(y_min, y);
00200 y_max = vnl_math_max(y_max, y);
00201 }
00202
00203 corners.push_back(closest_point(x_min, y_max, temp));
00204
00205 corners.push_back(closest_point(x_max, y_max, temp));
00206
00207 corners.push_back(closest_point(x_max, y_min, temp));
00208
00209 corners.push_back(closest_point(x_min, y_min, temp));
00210
00211 return true;
00212 }
00213
00214 static bool
00215 four_point_homography(vcl_vector<vgl_homg_point_2d<double> > const& points_3d,
00216 vcl_vector<vgl_homg_point_2d<double> > const& image_pts,
00217 vgl_h_matrix_2d<double>& H)
00218 {
00219 vgl_h_matrix_2d_compute_4point mapper;
00220 if (!mapper.compute(points_3d, image_pts, H))
00221 return false;
00222 return true;
00223 }
00224
00225 bool brct_plane_calibrator::compute_initial_homographies()
00226 {
00227 vcl_vector<vgl_homg_point_2d<double> > image_corners, corner_3d_points;
00228 vgl_h_matrix_2d<double> H;
00229
00230 for (int plane =0; plane<=Z_FRONT; plane++)
00231 if (!four_3d_corners(pts_3d_[plane], corner_3d_points))
00232 return false;
00233 else
00234 for (int cam = 0; cam<=RIGHT; cam++)
00235 if (!four_image_corners(cam_width_[cam], cam_height_[cam], image_corners))
00236 return false;
00237 else
00238 if (four_point_homography(corner_3d_points, image_corners, H))
00239 initial_homographies_[plane][cam] = H;
00240 initial_homographies_valid_ = true;
00241 return true;
00242 }
00243
00244 bool brct_plane_calibrator::write_corrs(vcl_string const& corrs_file)
00245 {
00246 vcl_ofstream os(corrs_file.c_str());
00247 if (!os)
00248 {
00249 vcl_cout << "In brct_plane_calibrator::write_corrs -"
00250 << " could not open file " << corrs_file << '\n';
00251 return false;
00252 }
00253 for (int plane = 0; plane <=Z_FRONT; plane++)
00254 {
00255 os << "PLANE: " << plane << '\n';
00256 int n_corrs = corrs_[plane].size();
00257 os << "NCORRS: " << n_corrs << '\n';
00258 for (int c = 0; c<n_corrs; c++)
00259 {
00260 brct_plane_corr_sptr corr = corrs_[plane][c];
00261 os << *corr << '\n';
00262 }
00263 }
00264 return true;
00265 }
00266
00267 bool brct_plane_calibrator::read_corrs(vcl_string const& corrs_file)
00268 {
00269 vcl_ifstream is(corrs_file.c_str());
00270 if (!is)
00271 {
00272 vcl_cout << "In brct_plane_calibrator::read_corrs -"
00273 << " could not open file " << corrs_file << '\n';
00274 return false;
00275 }
00276 vcl_vector<vcl_vector<brct_plane_corr_sptr> > corrs(Z_FRONT+1);
00277 for (int p = 0; p<=Z_FRONT; p++)
00278 {
00279 vcl_string s;
00280 is >> s;
00281 if (!(s=="PLANE:"))
00282 return false;
00283 int plane=0;
00284 is >> plane;
00285 is >> s;
00286 if (!(s=="NCORRS:"))
00287 return false;
00288 int n_corrs = 0;
00289 is >> n_corrs;
00290
00291 for (int i = 0; i<n_corrs; i++)
00292 {
00293 int n_cams = 0, plane = 0, index = 0;
00294 is>> s;
00295 if (!(s=="NCAMS:"))
00296 return false;
00297 is >> n_cams;
00298 is >> s;
00299 if (!(s=="P:"))
00300 return false;
00301 is >> plane;
00302
00303 is >> s;
00304 if (!(s=="I:"))
00305 return false;
00306 is >> index;
00307 brct_plane_corr_sptr corr = new brct_plane_corr(n_cams, plane, index);
00308 for (int cam = 0; cam<n_cams; cam++)
00309 {
00310 double x = 0, y = 0;
00311 is >> s;
00312 if (!(s=="X:"))
00313 return false;
00314 is >> x >> s;
00315 if (!(s=="Y:"))
00316 return false;
00317 is >> y;
00318 corr->set_match(cam, x, y);
00319 }
00320 corrs[plane].push_back(corr);
00321 }
00322
00323 corrs_ = corrs;
00324 }
00325 return true;
00326 }
00327
00328 bool brct_plane_calibrator::compute_homographies()
00329 {
00330 for (int plane = 0; plane<=Z_FRONT; plane++)
00331 for (int cam = 0; cam<=RIGHT; cam++)
00332 {
00333
00334 vcl_vector<brct_plane_corr_sptr>& corrs = corrs_[plane];
00335
00336 vcl_vector<vgl_homg_point_2d<double> > image_pts, pts_3d;
00337 for (vcl_vector<brct_plane_corr_sptr>::iterator cit = corrs.begin();
00338 cit != corrs.end(); cit++)
00339 if ((*cit)->valid(cam))
00340 {
00341 pts_3d.push_back(pts_3d_[plane][(*cit)->index()]);
00342 image_pts.push_back((*cit)->match(cam));
00343 }
00344 int n_3d = pts_3d.size(), n_img = image_pts.size();
00345 if (n_3d < 4 || n_img < 4)
00346 {
00347 vcl_cout << "In brct_plane_calibrator::compute_homographies()-"
00348 << " not enough correspondences\n";
00349 return false;
00350 }
00351 vgl_h_matrix_2d_compute_linear hcl;
00352 vgl_h_matrix_2d<double> H;
00353 if (!hcl.compute(pts_3d, image_pts, H))
00354 {
00355 vcl_cout << "In brct_plane_calibrator::compute_homographies()-"
00356 << " homography computation failed\n";
00357 return false;
00358 }
00359 current_homographies_[plane][cam]=H;
00360 }
00361 return true;
00362 }
00363
00364 bool
00365 brct_plane_calibrator::write_homographies(vcl_string const& homography_file)
00366 {
00367 vcl_ofstream os(homography_file.c_str());
00368 if (!os)
00369 {
00370 vcl_cout << "In brct_plane_calibrator::write_homographies -"
00371 << " could not open file " << homography_file << '\n';
00372 return false;
00373 }
00374 os << "N_PLANES: " << Z_FRONT+1 << '\n'
00375 << "N_CAMS: " << RIGHT+1 << '\n';
00376 for (int plane = 0; plane<=Z_FRONT; plane++)
00377 for (int cam = 0; cam<=RIGHT; cam++)
00378 {
00379 os << "PLANE: " << plane << '\n';
00380 if (!plane)
00381 os << "Z: " << z_back_ << '\n';
00382 else
00383 os << "Z: " << z_front_ << '\n';
00384 os << "CAM: " << cam << '\n'
00385 << current_homographies_[plane][cam].get_matrix();
00386 }
00387 return true;
00388 }
00389
00390 vcl_vector<vgl_point_2d<double> >
00391 brct_plane_calibrator::projected_3d_points_initial(const int plane,
00392 const int cam)
00393 {
00394 vcl_vector<vgl_point_2d<double> > temp;
00395 if (plane>Z_FRONT)
00396 return temp;
00397 if (cam>RIGHT)
00398 return temp;
00399 for (unsigned int i = 0; i<pts_3d_[plane].size(); ++i)
00400 {
00401 vgl_homg_point_2d<double> hp =
00402 initial_homographies_[plane][cam](pts_3d_[plane][i]);
00403 vgl_point_2d<double> p(hp);
00404 temp.push_back(p);
00405 }
00406 return temp;
00407 }
00408
00409 vcl_vector<vgl_point_2d<double> >
00410 brct_plane_calibrator::projected_3d_points(const int plane, const int cam)
00411 {
00412 vcl_vector<vgl_point_2d<double> > temp;
00413 if (plane>Z_FRONT)
00414 return temp;
00415 if (cam>RIGHT)
00416 return temp;
00417 for (unsigned int i = 0; i<pts_3d_[plane].size(); ++i)
00418 {
00419 vgl_homg_point_2d<double> hp =
00420 current_homographies_[plane][cam](pts_3d_[plane][i]);
00421 vgl_point_2d<double> p(hp);
00422 temp.push_back(p);
00423 }
00424 return temp;
00425 }