contrib/brl/bmvl/brct/brct_plane_sweeper.cxx
Go to the documentation of this file.
00001 #include "brct_plane_sweeper.h"
00002 //:
00003 // \file
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 //: normalize to make H[2][2]=1
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);//to normalize
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   //resize the arrays
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   //read the homography data
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 //: compute homographies for each camera that project to the specified z plane.
00180 //  For now assume two cameras.
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   //we assume z_[0] is defined as zero
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     //set the homgraphy columns 0 and 1 to the average of M0 and M1
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     //interpolate the third column with respect to depth
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   //intersect with each image projection
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   //get the bounding box of the overlapping region
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   //The min corner must be mapped to (0,0) to form an image
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     //JLM Debug
00294     //      vcl_cout << "H(" << cam << ")\n" << H << "\n\n";
00295     //end debug
00296     vgl_h_matrix_2d<double> Hinv = H.get_inverse();
00297     //modify the homography to map the corner to (0, 0)
00298     vgl_h_matrix_2d<double> Hinvt = translate_h(Hinv, tx, ty);
00299     //project the image
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 //: compute overlapping projections of images and Harris corners
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   //project the harris corners
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 //:compute the projections of left and right images that overlap on the specified plane
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 //:compute the projections of left and right images that overlap on the plane at depth z
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 // perform the cross-correlation of each pixel of the overlapping projection
00368 // of the left and right images onto the specified plane.
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 // perform the cross-correlation of each pixel of the overlapping projection
00391 // of the left and right images onto the specified world Z value.
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   //reset match flags
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   //matched corners are in original image1 coordinates
00437   if (!this->correlate_corners(imgs, proj_corners, matched_corners))
00438     return false;
00439   //JLM DEBUG
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   //END JLM DEBUG
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);//initialize the empty box
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 //: sweep the z plane and find positions of max cross-correlation
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   //get the size of the depth image
00511   //scan over the required z planes and get the union of all overlapping boxes
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   //data processing images
00517   //an image of maximum correlation value over the depth range
00518   vil1_memory_image_of<float> max_corr(w, h);
00519   float maxv = vnl_numeric_traits<float>::maxval;
00520   max_corr.fill(-maxv);
00521   //the depth image
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   //iterate through the depth planes
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     //get the overlap of the left and right images at the specified depth
00533     this->homographies_at_z(z, homgs);
00534     double tx=0, ty=0;
00535     this->overlapping_projections(homgs, imgs, tx, ty);
00536     //correlate the two images
00537 //     vil1_memory_image_of<float> cc =
00538 //       brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], radius_, intensity_thresh_);
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     //translate the correlation image to the base image
00546     double dtx = 2*Tx-tx, dty = 2*Ty-ty;
00547     vgl_h_matrix_2d<double> Htrans = translation_h(dtx, dty);
00548     // the base image space for registering each cc image
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 //: sweep the z plane and find positions of max cross-correlation
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   //reset flags
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   //get the size of the depth image
00594   //scan over the required z planes and get the union of all overlapping boxes
00595   vsol_box_2d_sptr un = this->depth_image_box(zmin_, zmax_);
00596   int w = (int)(un->width()), h = (int)(un->height());
00597 
00598   //data processing images
00599   //an image of maximum correlation value over the depth range
00600   vil1_memory_image_of<float> max_corr(w, h);
00601   float maxv = vnl_numeric_traits<float>::maxval;
00602   max_corr.fill(-maxv);
00603   //the depth image
00604   vil1_memory_image_of<float> depth(w, h);
00605   float null_depth = -10;
00606   depth.fill(null_depth);
00607   //iterate through the depth planes
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     //get the overlap of the left and right images at the specified depth
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       //          bsol_algs::print(*pit);
00629     }
00630 
00631     //back project the matched corners (cam 1) onto the world x-y-z plane
00632     vcl_vector<vsol_point_2d_sptr> trans_pts =
00633       this->project_corners(homgs[1], matched_corners);
00634     //convert to 3-d points
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 //return true if (r, c) has a neighbor within the radius
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   //check bounds
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 //: match harris corners from image 1 to image 0 and return matches
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   //for marking
00704   vcl_vector<vsol_point_2d_sptr> h1 = harris_corners_[1];
00705   //set the image 0 point_index array at Harris corner locations
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   //test each Harris corner in image 1 for a neighbor
00715   int n1 = pts1.size();
00716   for (int i = 0; i< n1; i++)
00717   {
00718     //sub-pixel locations
00719     double x0 = pts1[i]->x(), y0 = pts1[i]->y();
00720     //integer locations
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);//cache original Harris point
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   //map the point
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   //assume two cameras for now
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   //form the composite homography
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 //Map points from one image to the other assuming that they lie on plane z
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   //get the homographies interpolated at plane z
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   //map the point to the plane at z
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 //: Map an image from one camera to the other, assuming all the pixels lie on the plane at z.
00841 //  Put the result into the coordinate frame of the target camera (to camera).
00842 bool brct_plane_sweeper::map_image(const int from_cam, const double z,
00843                                    vil1_memory_image_of<float>& mapped_image)
00844 {
00845   //get the homographies interpolated at plane z
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   //Form the composed map
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 //: Map the image of the from_cam to the image space of the to_cam.
00869 //  Assumes that the world is a plane at z.
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 //:initialize the harris corner matching index
00913 void brct_plane_sweeper::init_harris_match(const int from_cam)
00914 {
00915   //make the grid 1/4 the size of the image
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 //:for debugging testing
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   //mark the harris corners in the from_cam that are matched
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;//removed even if correlation fails
00987         }
00988     }
00989     int n = matched_points.size();
00990 
00991     //now confirm with correlation
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 //:get the matched corners as 3-d points with x-y in the matched image
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 //:get the matched corners as 3-d points with world x-y coordinates
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   //need h in order to flip y for a right-handed world coordinate system
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);//flipped y
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 }