00001 #include "brct_plane_sweeper.h"
00002
00003
00004 #include <vcl_fstream.h>
00005 #include <vcl_cmath.h>
00006 #include <vbl/vbl_array_2d.h>
00007 #include <vnl/vnl_numeric_traits.h>
00008 #include <vnl/vnl_matrix_fixed.h>
00009 #include <vgl/vgl_homg_point_2d.h>
00010 #include <vgl/vgl_point_2d.h>
00011 #include <vsol/vsol_box_2d.h>
00012 #include <vsol/vsol_point_2d.h>
00013 #include <vsol/vsol_point_3d.h>
00014 #include <bsol/bsol_algs.h>
00015 #include <sdet/sdet_harris_detector.h>
00016 #include <brip/brip_vil1_float_ops.h>
00017 #include <brct/brct_algos.h>
00018
00019 brct_plane_sweeper::brct_plane_sweeper(brct_plane_sweeper_params const& sp)
00020 : brct_plane_sweeper_params(sp), n_planes_(0), n_cams_(0), del_(1.f),
00021 to_cam_(0), pindx_(192,256,vsol_box_2d_sptr(0))
00022 {
00023 }
00024
00025 brct_plane_sweeper::~brct_plane_sweeper()
00026 {
00027 }
00028
00029 static vgl_h_matrix_2d<double> translation_h(const double tx, const double ty)
00030 {
00031 vnl_matrix_fixed<double,3, 3> M;
00032 M.fill(0.0);
00033 M[0][0]=1.0; M[0][2]=tx;
00034 M[1][1]=1.0; M[1][2]=ty;
00035 M[2][2]=1.0;
00036 vgl_h_matrix_2d<double> H(M);
00037 return H;
00038 }
00039
00040
00041 static vgl_h_matrix_2d<double> normalize_h(vgl_h_matrix_2d<double> const& H)
00042 {
00043 vnl_matrix_fixed<double,3, 3> M = H.get_matrix();
00044 double s = M[2][2];
00045 if (vcl_fabs(s)<1e-06)
00046 {
00047 vcl_cout << "In brct_plane_sweeper - singular homography\n";
00048 return H;
00049 }
00050 for (int r = 0; r<3; r++)
00051 for (int c = 0; c<3; c++)
00052 M[r][c]/=s;
00053 vgl_h_matrix_2d<double> Hn(M);
00054 return Hn;
00055 }
00056
00057 static vgl_h_matrix_2d<double> translate_h(vgl_h_matrix_2d<double> const& H,
00058 const double tx, const double ty)
00059 {
00060 vnl_matrix_fixed<double,3, 3> M = H.get_matrix(), Mt;
00061 Mt.fill(0.0);
00062 Mt[0][0]=1; Mt[1][1]=1; Mt[2][2]=1;
00063 Mt[0][2] = tx;
00064 Mt[1][2] = ty;
00065 vgl_h_matrix_2d<double> Ht(Mt*M);
00066 return Ht;
00067 }
00068
00069 vcl_vector<vsol_point_2d_sptr> brct_plane_sweeper::
00070 project_corners(vgl_h_matrix_2d<double> const & H,
00071 vcl_vector<vsol_point_2d_sptr> const& corners)
00072 {
00073 vcl_vector<vsol_point_2d_sptr> out;
00074 for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = corners.begin();
00075 pit != corners.end(); pit++)
00076 {
00077 vgl_homg_point_2d<double> p((*pit)->x(), (*pit)->y()), hp;
00078 hp = H(p);
00079 vgl_point_2d<double> np(hp);
00080 vsol_point_2d_sptr temp = new vsol_point_2d(np);
00081 out.push_back(temp);
00082 }
00083 return out;
00084 }
00085
00086 bool brct_plane_sweeper::read_homographies(vcl_string const& homography_file)
00087 {
00088 vcl_ifstream is(homography_file.c_str());
00089 if (!is)
00090 {
00091 vcl_cout << "In brct_plane_calibrator::write_homographies -"
00092 << " could not open file " << homography_file << '\n';
00093 return false;
00094 }
00095 vcl_string s;
00096 is >> s;
00097 if (!(s=="N_PLANES:"))
00098 {
00099 vcl_cout << "Parse error\n";
00100 return false;
00101 }
00102 is >> n_planes_;
00103 is >> s;
00104 if (!(s=="N_CAMS:"))
00105 {
00106 vcl_cout << "Parse error\n";
00107 return false;
00108 }
00109 is >> n_cams_;
00110
00111 z_.resize(n_planes_);
00112 homographies_.resize(n_planes_);
00113 for (int i=0; i<n_planes_; i++)
00114 homographies_[i].resize(n_cams_);
00115 images_.resize(n_cams_);
00116 smooth_images_.resize(n_cams_);
00117 harris_corners_.resize(n_cams_);
00118
00119 int p = 0, c =0;
00120 double z=0;
00121 vnl_matrix_fixed<double, 3, 3> M;
00122 for (int plane = 0; plane < n_planes_; plane++)
00123 for (int cam = 0; cam < n_cams_; cam++)
00124 {
00125 is >> s;
00126 if (!(s=="PLANE:"))
00127 {
00128 vcl_cout << "Parse error\n";
00129 return false;
00130 }
00131 is >> p;
00132 is >> s;
00133 if (!(s=="Z:"))
00134 {
00135 vcl_cout << "Parse error\n";
00136 return false;
00137 }
00138 is >> z;
00139 z_[plane]=z;
00140 is >> s;
00141 if (!(s=="CAM:"))
00142 {
00143 vcl_cout << "Parse error\n";
00144 return false;
00145 }
00146 is >> c;
00147 is >> M;
00148 vgl_h_matrix_2d<double> H(M);
00149 vgl_h_matrix_2d<double> Hn = normalize_h(H);
00150 homographies_[plane][cam]=Hn;
00151 }
00152 homographies_valid_=true;
00153 return true;
00154 }
00155
00156 bool brct_plane_sweeper::set_image(const int cam, vil1_image const& image)
00157 {
00158 if (cam>=n_cams_)
00159 {
00160 vcl_cout << "In brct_plane_sweeper::set_image - "
00161 << " cam index out of bounds\n";
00162 return false;
00163 }
00164 if (!image)
00165 {
00166 vcl_cout << "In brct_plane_sweeper::set_image - "
00167 << " null image\n";
00168 return false;
00169 }
00170 images_[cam]=image;
00171 vil1_memory_image_of<float> flt_image =
00172 brip_vil1_float_ops::convert_to_float(image);
00173 vil1_memory_image_of<float> smooth =
00174 brip_vil1_float_ops::gaussian(flt_image, corr_sigma_);
00175 smooth_images_[cam]=smooth;
00176 return true;
00177 }
00178
00179
00180
00181 void brct_plane_sweeper::
00182 homographies_at_z(double z, vcl_vector<vgl_h_matrix_2d<double> >& homgs)
00183 {
00184 if (!homographies_valid_)
00185 return;
00186
00187 double zc = z_[1];
00188 if (!zc)
00189 return;
00190 homgs.clear();
00191 double f = z/zc;
00192 for (int cam = 0; cam<n_cams_; cam++)
00193 {
00194 vgl_h_matrix_2d<double> H0 = homographies_[0][cam];
00195 vgl_h_matrix_2d<double> H1 = homographies_[1][cam];
00196 vnl_matrix_fixed<double,3, 3> M0 = H0.get_matrix();
00197 vnl_matrix_fixed<double,3, 3> M1 = H1.get_matrix();
00198 vnl_matrix_fixed<double,3, 3> M;
00199
00200
00201 for (int r = 0; r<3; r++)
00202 for (int c =0; c<2; c++)
00203 M[r][c] = 0.5*(M0[r][c] + M1[r][c]);
00204
00205 for (int r = 0; r<3; r++)
00206 M[r][2] = f*(M1[r][2]-M0[r][2]) + M0[r][2];
00207 vgl_h_matrix_2d<double> H(M);
00208 homgs.push_back(H);
00209 }
00210 }
00211
00212
00213 vil1_memory_image_of<unsigned char>
00214 brct_plane_sweeper::project_image_to_plane(const int plane,
00215 const int cam)
00216 {
00217 vil1_memory_image_of<unsigned char> out;
00218 if (!homographies_valid_)
00219 {
00220 vcl_cout << "In brct_plane_sweeper::project_image_to_plane -"
00221 << " homographies not loaded yet\n";
00222 return out;
00223 }
00224 vgl_h_matrix_2d<double> H = homographies_[plane][cam];
00225 vgl_h_matrix_2d<double> Hinv = H.get_inverse();
00226 vil1_memory_image_of<float> image =smooth_images_[cam], temp;
00227 brip_vil1_float_ops::homography(image, Hinv, temp);
00228 out = brip_vil1_float_ops::convert_to_byte(temp, 0, 255);
00229 return out;
00230 }
00231
00232 static vsol_box_2d_sptr box_from_image(vil1_memory_image_of<float> const& img)
00233 {
00234 int w = img.width();
00235 int h = img.height();
00236 vsol_box_2d_sptr box = new vsol_box_2d();
00237 box->add_point(0,0);
00238 box->add_point(w,h);
00239 return box;
00240 }
00241
00242 bool brct_plane_sweeper::
00243 overlapping_box(vcl_vector<vgl_h_matrix_2d<double> > const& homgs,
00244 vsol_box_2d_sptr & box)
00245 {
00246 vsol_box_2d_sptr intersection = new vsol_box_2d();
00247 double maxd = vnl_numeric_traits<double>::maxval;
00248 intersection->add_point(-maxd, -maxd);
00249 intersection->add_point(+maxd, +maxd);
00250
00251 for (int cam =0; cam<n_cams_; cam++)
00252 {
00253 vgl_h_matrix_2d<double> H = homgs[cam];
00254 vgl_h_matrix_2d<double> Hinv = H.get_inverse();
00255 vil1_memory_image_of<float> image =smooth_images_[cam];
00256 vsol_box_2d_sptr b = box_from_image(image);
00257 vsol_box_2d_sptr Hinv_b;
00258 if (!bsol_algs::homography(b, Hinv, Hinv_b))
00259 return false;
00260 if (!bsol_algs::intersection(Hinv_b, intersection, intersection))
00261 return false;
00262 }
00263 box = intersection;
00264 return true;
00265 }
00266
00267 bool brct_plane_sweeper::
00268 overlapping_projections(vcl_vector<vgl_h_matrix_2d<double> > const& homgs,
00269 vcl_vector<vil1_memory_image_of<float> >& imgs,
00270 double& tx, double& ty)
00271 {
00272 if (!n_cams_)
00273 {
00274 vcl_cout << "In brct_plane_sweeper::overlapping_projections(.._)-"
00275 << " no cameras\n";
00276 return false;
00277 }
00278 imgs.clear();
00279
00280 vsol_box_2d_sptr intersection;
00281 if (!this->overlapping_box(homgs, intersection))
00282 {
00283 vcl_cout << "In brct_plane_sweeper::overlapping_projections(.._)-"
00284 << " no overlap\n";
00285 return false;
00286 }
00287
00288 tx = -(intersection->get_min_x()), ty = -(intersection->get_min_y());
00289 int w = (int)intersection->width(), h = (int)intersection->height();
00290 for (int cam =0; cam<n_cams_; cam++)
00291 {
00292 vgl_h_matrix_2d<double> H = homgs[cam];
00293
00294
00295
00296 vgl_h_matrix_2d<double> Hinv = H.get_inverse();
00297
00298 vgl_h_matrix_2d<double> Hinvt = translate_h(Hinv, tx, ty);
00299
00300 vil1_memory_image_of<float> image =smooth_images_[cam];
00301 vil1_memory_image_of<float> projection(w, h);
00302 if (!brip_vil1_float_ops::homography(image, Hinvt, projection, true))
00303 return false;
00304 imgs.push_back(projection);
00305 }
00306 return true;
00307 }
00308
00309
00310 bool brct_plane_sweeper::
00311 overlapping_projections(vcl_vector<vgl_h_matrix_2d<double> > const& homgs,
00312 vcl_vector<vil1_memory_image_of<float> >& imgs,
00313 vcl_vector<vcl_vector<vsol_point_2d_sptr> >& corners,
00314 double& tx, double& ty)
00315 {
00316 if (!overlapping_projections(homgs, imgs, tx, ty))
00317 return false;
00318 corners.clear();
00319
00320 for (int cam =0; cam<n_cams_; cam++)
00321 {
00322 vgl_h_matrix_2d<double> H = homgs[cam];
00323 vgl_h_matrix_2d<double> Hinv = H.get_inverse();
00324 vgl_h_matrix_2d<double> Hinvt = translate_h(Hinv, tx, ty);
00325 vcl_vector<vsol_point_2d_sptr> hc = harris_corners_[cam];
00326 vcl_vector<vsol_point_2d_sptr> pcs =
00327 this->project_corners(Hinvt, hc);
00328 corners.push_back(pcs);
00329 }
00330 return true;
00331 }
00332
00333
00334
00335 bool brct_plane_sweeper::
00336 overlapping_projections(const int plane,
00337 vcl_vector<vil1_memory_image_of<float> >& imgs)
00338 {
00339 vcl_vector<vgl_h_matrix_2d<double> > homgs = homographies_[plane];
00340 double tx=0, ty=0;
00341 return overlapping_projections(homgs, imgs, tx, ty);
00342 }
00343
00344
00345 bool brct_plane_sweeper::
00346 overlapping_projections(const double z,
00347 vcl_vector<vil1_memory_image_of<float> >& imgs)
00348 {
00349 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00350 this->homographies_at_z(z, homgs);
00351 double tx=0, ty=0;
00352 return overlapping_projections(homgs, imgs, tx, ty);
00353 }
00354
00355 bool brct_plane_sweeper::
00356 overlapping_projections(const double z,
00357 vcl_vector<vil1_memory_image_of<float> >& imgs,
00358 vcl_vector<vcl_vector<vsol_point_2d_sptr> >& corners)
00359 {
00360 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00361 this->homographies_at_z(z, homgs);
00362 double tx=0, ty=0;
00363 return overlapping_projections(homgs, imgs, corners, tx, ty);
00364 }
00365
00366
00367
00368
00369 vil1_memory_image_of<unsigned char>
00370 brct_plane_sweeper::cross_correlate_projections(const int plane)
00371 {
00372 vil1_memory_image_of<unsigned char> out;
00373 if (n_cams_<2)
00374 {
00375 vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00376 << "less than two images\n";
00377 return out;
00378 }
00379 vcl_vector<vil1_memory_image_of<float> > imgs;
00380 this->overlapping_projections(plane, imgs);
00381 vil1_memory_image_of<float> cc;
00382 if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], cc,
00383 corr_radius_, intensity_thresh_))
00384 return out;
00385 out = brip_vil1_float_ops::convert_to_byte(cc, corr_min_, corr_max_);
00386 return out;
00387 }
00388
00389
00390
00391
00392 vil1_memory_image_of<unsigned char>
00393 brct_plane_sweeper::cross_correlate_projections(const double z)
00394 {
00395 vil1_memory_image_of<unsigned char> out;
00396 if (n_cams_<2)
00397 {
00398 vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00399 << "less than two images\n";
00400 return out;
00401 }
00402 vcl_vector<vil1_memory_image_of<float> > imgs;
00403 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00404 this->homographies_at_z(z, homgs);
00405 double tx=0, ty=0;
00406 this->overlapping_projections(homgs, imgs, tx, ty);
00407 vil1_memory_image_of<float> cc;
00408 if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], cc,
00409 corr_radius_, intensity_thresh_))
00410 return out;
00411 out = brip_vil1_float_ops::convert_to_byte(cc, corr_min_, corr_max_);
00412 return out;
00413 }
00414
00415 bool
00416 brct_plane_sweeper::
00417 cross_correlate_proj_corners(const double z,
00418 vil1_image& back,
00419 vcl_vector<vsol_point_2d_sptr>& matched_corners,
00420 vcl_vector<vsol_point_2d_sptr>& back_proj_cnrs,
00421 vcl_vector<vsol_point_2d_sptr>& orig_cnrs0)
00422 {
00423 if (n_cams_<2)
00424 {
00425 vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00426 << "less than two images\n";
00427 return false;
00428 }
00429
00430 vcl_vector<vil1_memory_image_of<float> > imgs;
00431 vcl_vector<vsol_point_2d_sptr> temp;
00432 vcl_vector<vcl_vector<vsol_point_2d_sptr> > proj_corners;
00433 if (!overlapping_projections(z, imgs, proj_corners))
00434 return false;
00435 vcl_cout << "Correlating corners at z" << z << vcl_endl;
00436
00437 if (!this->correlate_corners(imgs, proj_corners, matched_corners))
00438 return false;
00439
00440 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00441 this->homographies_at_z(z, homgs);
00442 vgl_h_matrix_2d<double> H0=homgs[0], H1 = homgs[1];
00443 vgl_h_matrix_2d<double> H1inv = H1.get_inverse();
00444 vcl_vector<vsol_point_2d_sptr> world_pts =
00445 this->project_corners(H1inv, matched_corners);
00446 back_proj_cnrs = this->project_corners(H0, world_pts);
00447 orig_cnrs0 = harris_corners_[0];
00448 vcl_cout << "World Points/BackProj\n";
00449 int n = world_pts.size();
00450 for (int i = 0; i<n; i++)
00451 {
00452 bsol_algs::print(world_pts[i]);
00453 bsol_algs::print(back_proj_cnrs[i]);
00454 vcl_cout << vcl_endl;
00455 }
00456
00457
00458 back = images_[1];
00459 return true;
00460 }
00461
00462 vsol_box_2d_sptr brct_plane_sweeper::
00463 depth_image_box(const double zmin, const double zmax)
00464 {
00465 vsol_box_2d_sptr un = new vsol_box_2d();
00466 un->add_point(0, 0);
00467 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00468 for (double z = zmin; z<=zmax; z+=del_)
00469 {
00470 this->homographies_at_z(zmin, homgs);
00471 vsol_box_2d_sptr bb;
00472 this->overlapping_box(homgs, bb);
00473 if (!bsol_algs::box_union(un, bb, un))
00474 continue;
00475 }
00476 return un;
00477 }
00478
00479 #if 0 // unused static function
00480 static void debug_print(const int c0, const int r0, const int dr,
00481 const int c, const int r,
00482 const float cc_val)
00483 {
00484 int cmin = c0-dr, rmin = r0-dr;
00485 int cmax = c0+dr, rmax = r0+dr;
00486 if (c<cmin||c>cmax||r<rmin||r>rmax)
00487 return;
00488 vcl_cout << "C[" << r << "][" << c << "]= " << cc_val << vcl_endl;
00489 }
00490 #endif // 0
00491
00492
00493 bool brct_plane_sweeper::
00494 depth_image(vil1_memory_image_of<unsigned char>& depth_out,
00495 vil1_memory_image_of<unsigned char>& corr_out)
00496 {
00497 if (n_cams_<2)
00498 {
00499 vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00500 << "less than two images\n";
00501 return false;
00502 }
00503 z_corr_images_.clear();
00504 int n_zvals = nz_;
00505 if (n_zvals>256)
00506 n_zvals = 256;
00507 if (n_zvals<=0)
00508 n_zvals = 1;
00509 del_ = (zmax_-zmin_)/n_zvals;
00510
00511
00512 vsol_box_2d_sptr un = this->depth_image_box(zmin_, zmax_);
00513 double Tx = -(un->get_min_x()), Ty = -(un->get_min_y());
00514 int w = (int)(un->width()), h = (int)(un->height());
00515
00516
00517
00518 vil1_memory_image_of<float> max_corr(w, h);
00519 float maxv = vnl_numeric_traits<float>::maxval;
00520 max_corr.fill(-maxv);
00521
00522 vil1_memory_image_of<float> depth(w, h);
00523 float null_depth = -10;
00524 depth.fill(null_depth);
00525 float null_corr = -1.0;
00526
00527
00528 vcl_vector<vil1_memory_image_of<float> > imgs;
00529 vcl_vector<vgl_h_matrix_2d<double> > homgs, trans_homgs;
00530 for (double z = zmin_; z<=zmax_; z+=del_)
00531 {
00532
00533 this->homographies_at_z(z, homgs);
00534 double tx=0, ty=0;
00535 this->overlapping_projections(homgs, imgs, tx, ty);
00536
00537
00538
00539
00540 vil1_memory_image_of<float> cc;
00541 if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1],
00542 cc, corr_radius_,
00543 intensity_thresh_))
00544 return false;
00545
00546 double dtx = 2*Tx-tx, dty = 2*Ty-ty;
00547 vgl_h_matrix_2d<double> Htrans = translation_h(dtx, dty);
00548
00549 vil1_memory_image_of<float> base(w, h);
00550 if (!brip_vil1_float_ops::homography(cc, Htrans, base, true, null_corr))
00551 continue;
00552 z_corr_images_.push_back(base);
00553 vcl_cout << "corr for depth " << z << vcl_endl;
00554 for (int r = 0; r<h; r++)
00555 for (int c=0; c<w; c++)
00556 {
00557 float cc_val = base(c, r);
00558 if (cc_val<corr_thresh_)
00559 continue;
00560 if (cc_val > max_corr(c, r))
00561 {
00562 max_corr(c, r) = cc_val;
00563 depth(c, r) = float(z);
00564 }
00565 }
00566 }
00567 depth_out = brip_vil1_float_ops::convert_to_byte(depth, null_depth, zmax_);
00568 corr_out = brip_vil1_float_ops::convert_to_byte(max_corr, corr_min_,
00569 corr_max_);
00570 return true;
00571 }
00572
00573
00574 bool brct_plane_sweeper::
00575 harris_depth_match(vcl_vector<vsol_point_3d_sptr>& points_3d,
00576 vcl_vector<vsol_point_2d_sptr>& proj_points)
00577 {
00578 if (n_cams_<2)
00579 {
00580 vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00581 << "less than two images\n";
00582 return false;
00583 }
00584 points_3d.clear();
00585 proj_points.clear();
00586
00587 int n_zvals = nz_;
00588 if (n_zvals>256)
00589 n_zvals = 256;
00590 if (n_zvals<=0)
00591 n_zvals = 1;
00592 del_ = (zmax_-zmin_)/n_zvals;
00593
00594
00595 vsol_box_2d_sptr un = this->depth_image_box(zmin_, zmax_);
00596 int w = (int)(un->width()), h = (int)(un->height());
00597
00598
00599
00600 vil1_memory_image_of<float> max_corr(w, h);
00601 float maxv = vnl_numeric_traits<float>::maxval;
00602 max_corr.fill(-maxv);
00603
00604 vil1_memory_image_of<float> depth(w, h);
00605 float null_depth = -10;
00606 depth.fill(null_depth);
00607
00608 vil1_memory_image_of<float> back;
00609 vcl_vector<vil1_memory_image_of<float> > imgs;
00610 vcl_vector<vgl_h_matrix_2d<double> > homgs, trans_homgs;
00611 vcl_vector<vcl_vector<vsol_point_2d_sptr> > proj_corners;
00612
00613 for (double z = zmin_; z<=zmax_; z+=del_)
00614 {
00615
00616 this->homographies_at_z(z, homgs);
00617 double tx=0, ty=0;
00618 this->overlapping_projections(homgs, imgs, proj_corners, tx, ty);
00619 vcl_vector<vsol_point_2d_sptr> matched_corners;
00620 if (!this->correlate_corners(imgs, proj_corners, matched_corners))
00621 return false;
00622 vcl_cout << "Matched " << matched_corners.size() << " corners at z = "
00623 << z << vcl_endl;
00624 for (vcl_vector<vsol_point_2d_sptr>::iterator pit = matched_corners.begin();
00625 pit != matched_corners.end(); pit++)
00626 {
00627 proj_points.push_back(*pit);
00628
00629 }
00630
00631
00632 vcl_vector<vsol_point_2d_sptr> trans_pts =
00633 this->project_corners(homgs[1], matched_corners);
00634
00635 for (vcl_vector<vsol_point_2d_sptr>::iterator pit = trans_pts.begin();
00636 pit != trans_pts.end(); pit++)
00637 {
00638 double x = (*pit)->x(), y = (*pit)->y();
00639 vsol_point_3d_sptr p3d = new vsol_point_3d(x, y, z);
00640 points_3d.push_back(p3d);
00641 bsol_algs::print(p3d);
00642 }
00643 vcl_cout << vcl_endl;
00644 }
00645 return true;
00646 }
00647
00648 bool brct_plane_sweeper::compute_harris()
00649 {
00650 int n_images = images_.size();
00651 if (n_images!=n_cams_)
00652 {
00653 vcl_cout << "In brct_plane_sweeper::compute_harris() - "
00654 << "images not matched to cameras\n";
00655 return false;
00656 }
00657 vcl_cout << hdp_ << vcl_endl;
00658 sdet_harris_detector hd(hdp_);
00659 for (int cam = 0; cam<n_cams_; cam++)
00660 {
00661 hd.clear();
00662 hd.set_image(images_[cam]);
00663 hd.extract_corners();
00664 vcl_vector<vsol_point_2d_sptr> points = hd.get_points();
00665 harris_corners_[cam]=points;
00666 }
00667 harris_valid_ = true;
00668 return true;
00669 }
00670
00671
00672 static bool has_neighbor(const int r, const int c , const int radius,
00673 const int h, const int w,
00674 vbl_array_2d<bool> const& cnr_array)
00675 {
00676
00677 int rmin = radius, rmax = h-radius-1, cmin = radius, cmax = w-radius-1;
00678 if (r<rmin||r>rmax||c<cmin||c>cmax)
00679 return false;
00680 for (int r0 = -radius; r0<=radius; r0++)
00681 for (int c0 = -radius; c0<=radius; c0++)
00682 if (cnr_array[r+r0][c+c0])
00683 return true;
00684 return false;
00685 }
00686
00687
00688 bool brct_plane_sweeper::
00689 correlate_corners(vcl_vector<vil1_memory_image_of<float> > const& imgs,
00690 vcl_vector<vcl_vector<vsol_point_2d_sptr> > const& corners,
00691 vcl_vector<vsol_point_2d_sptr>& matched_corners)
00692 {
00693 int n_imgs=imgs.size();
00694 int n_corn=corners.size();
00695 if (n_imgs!=2||n_imgs!=n_corn)
00696 return false;
00697 matched_corners.clear();
00698 int w = imgs[0].width(), h = imgs[0].height();
00699 vbl_array_2d<bool> pt_index(h, w);
00700 pt_index.fill(false);
00701 vcl_vector<vsol_point_2d_sptr> const& pts0 = corners[0],
00702 pts1 = corners[1];
00703
00704 vcl_vector<vsol_point_2d_sptr> h1 = harris_corners_[1];
00705
00706 for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = pts0.begin();
00707 pit != pts0.end(); pit++)
00708 {
00709 int r = (int)((*pit)->y()), c = (int)((*pit)->x());
00710 if (r<0||r>=h||c<0||c>=w)
00711 continue;
00712 pt_index[r][c] = true;
00713 }
00714
00715 int n1 = pts1.size();
00716 for (int i = 0; i< n1; i++)
00717 {
00718
00719 double x0 = pts1[i]->x(), y0 = pts1[i]->y();
00720
00721 int r = (int)y0, c = (int)x0;
00722 if (r<0||r>=h||c<0||c>=w)
00723 continue;
00724 int pr = (int)point_radius_;
00725 if (has_neighbor(r, c, pr, h, w, pt_index))
00726 {
00727 float val =
00728 brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1],
00729 float(x0), float(y0),
00730 corr_radius_,
00731 intensity_thresh_);
00732
00733 if (val > corr_thresh_)
00734 {
00735 vsol_point_2d_sptr p = h1[i];
00736 matched_corners.push_back(p);
00737 vcl_cout << "C(" << p->x() << ' ' << p->y()
00738 << ")=" << val << vcl_endl;
00739 }
00740 }
00741 }
00742 return true;
00743 }
00744
00745 vcl_vector<vsol_point_2d_sptr>
00746 brct_plane_sweeper::harris_corners(const int cam)
00747 {
00748 vcl_vector<vsol_point_2d_sptr> points;
00749 if (cam>=n_cams_||!harris_valid_)
00750 return points;
00751 return harris_corners_[cam];
00752 }
00753
00754
00755 vil1_memory_image_of<unsigned char>
00756 brct_plane_sweeper::z_corr_image(const int i)
00757 {
00758 vil1_memory_image_of<unsigned char> temp;
00759 int li = i;
00760 int n = z_corr_images_.size();
00761 if (!n)
00762 return temp;
00763 if (i>=n)
00764 li = n-1;
00765 temp = brip_vil1_float_ops::convert_to_byte(z_corr_images_[li],
00766 corr_min_, corr_max_);
00767 return temp;
00768 }
00769
00770 void brct_plane_sweeper::corr_vals(const int col, const int row,
00771 vcl_vector<float>& z,
00772 vcl_vector<float>& corr)
00773 {
00774 z.clear();
00775 corr.clear();
00776 int i = 0, n = z_corr_images_.size();
00777 for (float zi = zmin_; zi<=zmax_; zi+=del_, i++)
00778 {
00779 z.push_back(zi);
00780 if (i<n)
00781 corr.push_back(z_corr_images_[i](col, row));
00782 }
00783 }
00784
00785 vsol_point_2d_sptr brct_plane_sweeper::
00786 map_point(vsol_point_2d_sptr const& p, vgl_h_matrix_2d<double> const& Hcomp)
00787 {
00788 vgl_homg_point_2d<double> hp(p->x(), p->y()), hp_to;
00789
00790 hp_to = Hcomp(hp);
00791 vgl_point_2d<double> p_to(hp_to);
00792 return new vsol_point_2d(p_to);
00793 }
00794
00795 vsol_point_2d_sptr brct_plane_sweeper::
00796 map_point(vsol_point_2d_sptr const& p, const int cam, const double z)
00797 {
00798 vsol_point_2d_sptr q;
00799 if (!p)
00800 return q;
00801 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00802 this->homographies_at_z(z, homgs);
00803
00804 int nc = homgs.size();
00805 if (nc!=2||cam>=nc)
00806 return q;
00807 vgl_h_matrix_2d<double> H_from = homgs[cam], H_to =homgs[1-cam];
00808
00809 vgl_h_matrix_2d<double> H_from_inv = H_from.get_inverse();
00810 vgl_h_matrix_2d<double> Hcomp = H_to*H_from_inv;
00811 return this->map_point(p, Hcomp);
00812 }
00813
00814
00815 bool brct_plane_sweeper::
00816 map_points(const int from_cam, const double z,
00817 vcl_vector<vsol_point_2d_sptr> const& from_points,
00818 vcl_vector<vsol_point_2d_sptr>& to_points)
00819 {
00820
00821 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00822 this->homographies_at_z(z, homgs);
00823 int nc = homgs.size();
00824 if (nc!=2||from_cam>=nc)
00825 return false;
00826 to_points.clear();
00827 int to_cam = 1-from_cam;
00828 vgl_h_matrix_2d<double> H_from = homgs[from_cam], H_to =homgs[to_cam];
00829
00830 vgl_h_matrix_2d<double> H_from_inv = H_from.get_inverse();
00831 vgl_h_matrix_2d<double> Hcomp = H_to*H_from_inv;
00832
00833 for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = from_points.begin();
00834 pit != from_points.end(); pit++)
00835 to_points.push_back(this->map_point(*pit, Hcomp));
00836
00837 return true;
00838 }
00839
00840
00841
00842 bool brct_plane_sweeper::map_image(const int from_cam, const double z,
00843 vil1_memory_image_of<float>& mapped_image)
00844 {
00845
00846 vcl_vector<vgl_h_matrix_2d<double> > homgs;
00847 this->homographies_at_z(z, homgs);
00848 int nc = homgs.size();
00849 if (nc!=2||from_cam>=nc)
00850 return false;
00851 int to_cam = 1-from_cam;
00852
00853 vgl_h_matrix_2d<double> Ha = homgs[from_cam], Hb =homgs[to_cam];
00854 vgl_h_matrix_2d<double> Hainv = Ha.get_inverse();
00855 vgl_h_matrix_2d<double> Hcomp = Hb*Hainv;
00856 vil1_memory_image_of<float> temp = smooth_images_[from_cam],
00857 to = smooth_images_[to_cam];
00858 vsol_box_2d_sptr from_box =box_from_image(temp), to_box = box_from_image(to),
00859 inter_box;
00860 vcl_cout << "Intersecting Mapped Box\n";
00861 if (this->intersecting_bounding_box(Hcomp, from_box, to_box, inter_box))
00862 bsol_algs::print(inter_box);
00863
00864 mapped_image.resize(temp.width(), temp.height());
00865 return brip_vil1_float_ops::homography(temp, Hcomp, mapped_image, true, 0);
00866 }
00867
00868
00869
00870 bool brct_plane_sweeper::map_image_to_image(const int from_cam, const double z,
00871 vil1_memory_image_of<unsigned char>& mapped_to_image,
00872 vil1_memory_image_of<unsigned char>& orig_to_image)
00873 {
00874 vil1_memory_image_of<float> temp;
00875 if (!this->map_image(from_cam, z, temp))
00876 return false;
00877 int to_cam = 1-from_cam;
00878 mapped_to_image = brip_vil1_float_ops::convert_to_byte(temp, 0, 255);
00879 orig_to_image =
00880 brip_vil1_float_ops::convert_to_byte(smooth_images_[to_cam], 0, 255);
00881 return true;
00882 }
00883
00884 bool brct_plane_sweeper::
00885 intersecting_bounding_box(vgl_h_matrix_2d<double> const& Hcomp,
00886 vsol_box_2d_sptr const& from_box,
00887 vsol_box_2d_sptr const& to_box,
00888 vsol_box_2d_sptr & box)
00889 {
00890 vsol_box_2d_sptr intersection = new vsol_box_2d();
00891 vsol_box_2d_sptr mapped_box;
00892 return bsol_algs::homography(from_box, Hcomp, mapped_box)
00893 && bsol_algs::intersection(mapped_box, to_box, box);
00894 }
00895
00896 bool brct_plane_sweeper::
00897 map_harris_corners(const int from_cam, const double z,
00898 vcl_vector<vsol_point_2d_sptr>& mapped_to_points,
00899 vcl_vector<vsol_point_2d_sptr>& orig_to_points)
00900 {
00901 if (from_cam<0||from_cam>=2)
00902 return false;
00903 if (!harris_valid_)
00904 return false;
00905 int to_cam = 1-from_cam;
00906 vcl_vector<vsol_point_2d_sptr> harris_from = harris_corners_[from_cam];
00907 orig_to_points = harris_corners_[to_cam];
00908 this->map_points(from_cam, z, harris_from, mapped_to_points);
00909 return true;
00910 }
00911
00912
00913 void brct_plane_sweeper::init_harris_match(const int from_cam)
00914 {
00915
00916 int nrows = 192, ncols = 256;
00917 int to_cam = 1-from_cam;
00918 vcl_vector<vsol_point_2d_sptr> to_points = harris_corners_[to_cam];
00919 pindx_ = bsol_point_index_2d(nrows, ncols, to_points);
00920 vcl_vector<vsol_point_2d_sptr> temp = pindx_.points();
00921 vcl_cout << "\nTotal points in point index = " << temp.size() << vcl_endl;
00922 pindx_.clear_marks();
00923 matched_corners_.clear();
00924 del_ = (zmax_-zmin_)/nz_;
00925 }
00926
00927
00928 bool brct_plane_sweeper::
00929 match_harris_corners(const int from_cam, const double z,
00930 vcl_vector<vsol_point_2d_sptr>& matched_points,
00931 vcl_vector<vsol_point_2d_sptr>& orig_to_points)
00932 {
00933 if (from_cam<0||from_cam>=2)
00934 return false;
00935 if (!harris_valid_)
00936 return false;
00937 matched_points.clear();
00938 orig_to_points.clear();
00939 float rad = point_radius_;
00940 int to_cam = 1-from_cam;
00941 vcl_vector<vsol_point_2d_sptr> harris_from = harris_corners_[from_cam];
00942 vcl_vector<vsol_point_2d_sptr> to_points = harris_corners_[to_cam];
00943 vcl_vector<vsol_point_2d_sptr> mapped_to_points;
00944 if (!this->map_points(from_cam, z, harris_from, mapped_to_points))
00945 return false;
00946 vsol_point_2d_sptr mp;
00947 for (vcl_vector<vsol_point_2d_sptr>::iterator pit = mapped_to_points.begin();
00948 pit != mapped_to_points.end(); pit++)
00949 if (pindx_.closest_in_radius(rad, *pit, mp))
00950 {
00951 matched_points.push_back(*pit);
00952 pindx_.mark_point(mp);
00953 orig_to_points.push_back(mp);
00954 }
00955 return true;
00956 }
00957
00958 bool brct_plane_sweeper::harris_sweep(const int from_cam)
00959 {
00960 if (from_cam<0||from_cam>=2)
00961 return false;
00962 if (!harris_valid_)
00963 return false;
00964 this->init_harris_match(from_cam);
00965 vcl_vector<vsol_point_2d_sptr> harris_from = harris_corners_[from_cam];
00966 to_cam_ = 1-from_cam;
00967 vil1_memory_image_of<float> orig_to_image = smooth_images_[to_cam_];
00968 int n_matched = 0;
00969 int nh = harris_from.size();
00970
00971 vcl_vector<bool> match_index(nh, false);
00972 for (double z = zmin_; z<=zmax_; z+=del_)
00973 {
00974 vcl_vector<vsol_point_2d_sptr> matched_points, mapped_points;
00975 if (!this->map_points(from_cam, z, harris_from, mapped_points))
00976 continue;
00977
00978 vsol_point_2d_sptr mp;
00979
00980 for (int i = 0; i<nh; i++)
00981 {
00982 if (!match_index[i])
00983 if (pindx_.closest_in_radius(point_radius_, mapped_points[i], mp))
00984 {
00985 matched_points.push_back(mapped_points[i]);
00986 match_index[i]=true;
00987 }
00988 }
00989 int n = matched_points.size();
00990
00991
00992 vcl_vector<vsol_point_2d_sptr> correlated_points;
00993 if (n)
00994 {
00995 vil1_memory_image_of<float> mapped_to_image;
00996 this->map_image(from_cam, z, mapped_to_image);
00997 for (vcl_vector<vsol_point_2d_sptr>::iterator pit=matched_points.begin();
00998 pit != matched_points.end(); pit++)
00999 {
01000 float x = (float)(*pit)->x(), y = (float)(*pit)->y();
01001 float cc =
01002 brip_vil1_float_ops::cross_correlate(mapped_to_image,
01003 orig_to_image,
01004 x, y, corr_radius_,
01005 intensity_thresh_);
01006 if (cc>corr_thresh_)
01007 {
01008 pindx_.mark_point(mp);
01009 correlated_points.push_back(*pit);
01010 }
01011 }
01012 int nc = correlated_points.size();
01013 n_matched += nc;
01014 vcl_cout << "N(" << z << ")=" << nc << " total matched = "
01015 << n_matched << vcl_endl;
01016 matched_corners_.push_back(correlated_points);
01017 }
01018 }
01019 return true;
01020 }
01021
01022 vcl_vector<vsol_point_2d_sptr>
01023 brct_plane_sweeper::matched_points_at_z_index(const int z_index)
01024 {
01025 int n = matched_corners_.size();
01026 int zi = z_index;
01027 if (z_index>=n)
01028 zi = n-1;
01029 return matched_corners_[zi];
01030 }
01031
01032
01033 vcl_vector<vsol_point_3d_sptr>
01034 brct_plane_sweeper::proj_points_3d()
01035 {
01036 vcl_vector<vsol_point_3d_sptr> out;
01037 double z = zmin_;
01038 int n_z = matched_corners_.size();
01039 if (!n_z)
01040 return out;
01041 for (int i = 0; i<n_z; i++, z+=del_)
01042 {
01043 vcl_vector<vsol_point_2d_sptr> pts = matched_corners_[i];
01044 for (vcl_vector<vsol_point_2d_sptr>::iterator pit = pts.begin();
01045 pit != pts.end(); pit++)
01046 {
01047 double x = (*pit)->x(), y = (*pit)->y();
01048 vsol_point_3d_sptr p3d = new vsol_point_3d(x, y, z);
01049 out.push_back(p3d);
01050 }
01051 }
01052 return out;
01053 }
01054
01055
01056 vcl_vector<vsol_point_3d_sptr>
01057 brct_plane_sweeper::world_points_3d()
01058 {
01059 vcl_vector<vsol_point_3d_sptr> out, temp;
01060 temp = this->proj_points_3d();
01061 int n = temp.size();
01062 if (!n)
01063 return out;
01064
01065 int h = 0;
01066 if (smooth_images_[0])
01067 h = smooth_images_[0].height();
01068 if (!h)
01069 return out;
01070 for (int i=0; i<n; i++)
01071 {
01072 vsol_point_3d_sptr p = temp[i];
01073 double x = p->x(), y = p->y(), z = p->z();
01074 vsol_point_3d_sptr pw = new vsol_point_3d(x, h-y, z);
01075 out.push_back(pw);
01076 }
01077 return out;
01078 }
01079
01080 bool brct_plane_sweeper::save_world_points(vcl_string const& out_file)
01081 {
01082 vcl_ofstream out(out_file.c_str());
01083 if (!out)
01084 return false;
01085 vcl_vector<vsol_point_3d_sptr> pts3d =
01086 this->world_points_3d();
01087 int n = pts3d.size();
01088 if (!n)
01089 return false;
01090 brct_algos::write_vrml_header(out);
01091 brct_algos::write_vrml_points(out, pts3d);
01092 brct_algos::write_vrml_trailer(out);
01093 out.close();
01094 return true;
01095 }