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