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 <bbas/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   if (!overlapping_projections(homgs, imgs, tx, ty))
00342     return false;
00343   return true;
00344 }
00345 
00346 //:compute the projections of left and right images that overlap on the plane at depth z
00347 bool brct_plane_sweeper::
00348 overlapping_projections(const double z,
00349                         vcl_vector<vil1_memory_image_of<float> >& imgs)
00350 {
00351   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00352   this->homographies_at_z(z, homgs);
00353   double tx=0, ty=0;
00354   if (!overlapping_projections(homgs, imgs, tx, ty))
00355     return false;
00356   return true;
00357 }
00358 
00359 bool brct_plane_sweeper::
00360 overlapping_projections(const double z,
00361                         vcl_vector<vil1_memory_image_of<float> >& imgs,
00362                         vcl_vector<vcl_vector<vsol_point_2d_sptr> >& corners)
00363 {
00364   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00365   this->homographies_at_z(z, homgs);
00366   double tx=0, ty=0;
00367   if (!overlapping_projections(homgs, imgs, corners, tx, ty))
00368     return false;
00369   return true;
00370 }
00371 
00372 //:
00373 // perform the cross-correlation of each pixel of the overlapping projection
00374 // of the left and right images onto the specified plane.
00375 vil1_memory_image_of<unsigned char>
00376 brct_plane_sweeper::cross_correlate_projections(const int plane)
00377 {
00378   vil1_memory_image_of<unsigned char> out;
00379   if (n_cams_<2)
00380   {
00381     vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00382              << "less than two images\n";
00383     return out;
00384   }
00385   vcl_vector<vil1_memory_image_of<float> > imgs;
00386   this->overlapping_projections(plane, imgs);
00387   vil1_memory_image_of<float> cc;
00388   if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], cc,
00389                                            corr_radius_, intensity_thresh_))
00390     return out;
00391   out = brip_vil1_float_ops::convert_to_byte(cc, corr_min_, corr_max_);
00392   return out;
00393 }
00394 
00395 //:
00396 // perform the cross-correlation of each pixel of the overlapping projection
00397 // of the left and right images onto the specified world Z value.
00398 vil1_memory_image_of<unsigned char>
00399 brct_plane_sweeper::cross_correlate_projections(const double z)
00400 {
00401   vil1_memory_image_of<unsigned char> out;
00402   if (n_cams_<2)
00403   {
00404     vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00405              << "less than two images\n";
00406     return out;
00407   }
00408   vcl_vector<vil1_memory_image_of<float> > imgs;
00409   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00410   this->homographies_at_z(z, homgs);
00411   double tx=0, ty=0;
00412   this->overlapping_projections(homgs, imgs, tx, ty);
00413   vil1_memory_image_of<float> cc;
00414   if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], cc,
00415                                            corr_radius_, intensity_thresh_))
00416     return out;
00417   out = brip_vil1_float_ops::convert_to_byte(cc, corr_min_, corr_max_);
00418   return out;
00419 }
00420 
00421 bool
00422 brct_plane_sweeper::
00423 cross_correlate_proj_corners(const double z,
00424                              vil1_image& back,
00425                              vcl_vector<vsol_point_2d_sptr>& matched_corners,
00426                              vcl_vector<vsol_point_2d_sptr>& back_proj_cnrs,
00427                              vcl_vector<vsol_point_2d_sptr>& orig_cnrs0)
00428 {
00429   if (n_cams_<2)
00430   {
00431     vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00432              << "less than two images\n";
00433     return false;
00434   }
00435   //reset match flags
00436   vcl_vector<vil1_memory_image_of<float> > imgs;
00437   vcl_vector<vsol_point_2d_sptr> temp;
00438   vcl_vector<vcl_vector<vsol_point_2d_sptr> > proj_corners;
00439   if (!overlapping_projections(z, imgs, proj_corners))
00440     return false;
00441   vcl_cout << "Correlating corners at z"  << z << vcl_endl;
00442   //matched corners are in original image1 coordinates
00443   if (!this->correlate_corners(imgs, proj_corners, matched_corners))
00444     return false;
00445   //JLM DEBUG
00446   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00447   this->homographies_at_z(z, homgs);
00448   vgl_h_matrix_2d<double> H0=homgs[0], H1 = homgs[1];
00449   vgl_h_matrix_2d<double> H1inv = H1.get_inverse();
00450   vcl_vector<vsol_point_2d_sptr> world_pts =
00451     this->project_corners(H1inv, matched_corners);
00452   back_proj_cnrs = this->project_corners(H0, world_pts);
00453   orig_cnrs0 = harris_corners_[0];
00454   vcl_cout << "World Points/BackProj\n";
00455   int n = world_pts.size();
00456   for (int i = 0; i<n; i++)
00457   {
00458     bsol_algs::print(world_pts[i]);
00459     bsol_algs::print(back_proj_cnrs[i]);
00460     vcl_cout << vcl_endl;
00461   }
00462 
00463   //END JLM DEBUG
00464   back = images_[1];
00465   return true;
00466 }
00467 
00468 vsol_box_2d_sptr brct_plane_sweeper::
00469 depth_image_box(const double zmin, const double zmax)
00470 {
00471   vsol_box_2d_sptr un = new vsol_box_2d();
00472   un->add_point(0, 0);//initialize the empty box
00473   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00474   for (double z = zmin; z<=zmax; z+=del_)
00475   {
00476     this->homographies_at_z(zmin, homgs);
00477     vsol_box_2d_sptr bb;
00478     this->overlapping_box(homgs, bb);
00479    if (!bsol_algs::box_union(un, bb, un))
00480      continue;
00481   }
00482   return un;
00483 }
00484 
00485 #if 0 // unused static function
00486 static void debug_print(const int c0, const int r0, const int dr,
00487                         const int c, const int r,
00488                         const float cc_val)
00489 {
00490   int cmin = c0-dr, rmin = r0-dr;
00491   int cmax = c0+dr, rmax = r0+dr;
00492   if (c<cmin||c>cmax||r<rmin||r>rmax)
00493     return;
00494   vcl_cout << "C[" << r << "][" << c << "]= " << cc_val << vcl_endl;
00495 }
00496 #endif // 0
00497 
00498 //: sweep the z plane and find positions of max cross-correlation
00499 bool brct_plane_sweeper::
00500 depth_image(vil1_memory_image_of<unsigned char>& depth_out,
00501             vil1_memory_image_of<unsigned char>& corr_out)
00502 {
00503   if (n_cams_<2)
00504   {
00505     vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00506              << "less than two images\n";
00507     return false;
00508   }
00509   z_corr_images_.clear();
00510   int n_zvals = nz_;
00511   if (n_zvals>256)
00512     n_zvals = 256;
00513   if (n_zvals<=0)
00514     n_zvals = 1;
00515   del_ = (zmax_-zmin_)/n_zvals;
00516   //get the size of the depth image
00517   //scan over the required z planes and get the union of all overlapping boxes
00518   vsol_box_2d_sptr un = this->depth_image_box(zmin_, zmax_);
00519   double Tx = -(un->get_min_x()), Ty = -(un->get_min_y());
00520   int w = (int)(un->width()), h = (int)(un->height());
00521 
00522   //data processing images
00523   //an image of maximum correlation value over the depth range
00524   vil1_memory_image_of<float> max_corr(w, h);
00525   float maxv = vnl_numeric_traits<float>::maxval;
00526   max_corr.fill(-maxv);
00527   //the depth image
00528   vil1_memory_image_of<float> depth(w, h);
00529   float null_depth = -10;
00530   depth.fill(null_depth);
00531   float null_corr = -1.0;
00532 
00533   //iterate through the depth planes
00534   vcl_vector<vil1_memory_image_of<float> > imgs;
00535   vcl_vector<vgl_h_matrix_2d<double> > homgs, trans_homgs;
00536   for (double z = zmin_; z<=zmax_; z+=del_)
00537   {
00538     //get the overlap of the left and right images at the specified depth
00539     this->homographies_at_z(z, homgs);
00540     double tx=0, ty=0;
00541     this->overlapping_projections(homgs, imgs, tx, ty);
00542     //correlate the two images
00543 //     vil1_memory_image_of<float> cc =
00544 //       brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1], radius_, intensity_thresh_);
00545 
00546     vil1_memory_image_of<float> cc;
00547     if (!brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1],
00548                                              cc, corr_radius_,
00549                                              intensity_thresh_))
00550       return false;
00551     //translate the correlation image to the base image
00552     double dtx = 2*Tx-tx, dty = 2*Ty-ty;
00553     vgl_h_matrix_2d<double> Htrans = translation_h(dtx, dty);
00554     // the base image space for registering each cc image
00555     vil1_memory_image_of<float> base(w, h);
00556     if (!brip_vil1_float_ops::homography(cc, Htrans, base, true, null_corr))
00557       continue;
00558     z_corr_images_.push_back(base);
00559     vcl_cout << "corr for depth " << z << vcl_endl;
00560     for (int r = 0; r<h; r++)
00561       for (int c=0; c<w; c++)
00562       {
00563         float cc_val = base(c, r);
00564         if (cc_val<corr_thresh_)
00565           continue;
00566         if (cc_val > max_corr(c, r))
00567         {
00568           max_corr(c, r) = cc_val;
00569           depth(c, r) = float(z);
00570         }
00571       }
00572   }
00573   depth_out = brip_vil1_float_ops::convert_to_byte(depth, null_depth, zmax_);
00574   corr_out = brip_vil1_float_ops::convert_to_byte(max_corr, corr_min_,
00575                                                   corr_max_);
00576   return true;
00577 }
00578 
00579 //: sweep the z plane and find positions of max cross-correlation
00580 bool brct_plane_sweeper::
00581 harris_depth_match(vcl_vector<vsol_point_3d_sptr>& points_3d,
00582                    vcl_vector<vsol_point_2d_sptr>& proj_points)
00583 {
00584   if (n_cams_<2)
00585   {
00586     vcl_cout << "In brct_plane_sweeper::cross_correlate_projections(..)-"
00587              << "less than two images\n";
00588     return false;
00589   }
00590   points_3d.clear();
00591   proj_points.clear();
00592   //reset flags
00593   int n_zvals = nz_;
00594   if (n_zvals>256)
00595     n_zvals = 256;
00596   if (n_zvals<=0)
00597     n_zvals = 1;
00598   del_ = (zmax_-zmin_)/n_zvals;
00599   //get the size of the depth image
00600   //scan over the required z planes and get the union of all overlapping boxes
00601   vsol_box_2d_sptr un = this->depth_image_box(zmin_, zmax_);
00602   int w = (int)(un->width()), h = (int)(un->height());
00603 
00604   //data processing images
00605   //an image of maximum correlation value over the depth range
00606   vil1_memory_image_of<float> max_corr(w, h);
00607   float maxv = vnl_numeric_traits<float>::maxval;
00608   max_corr.fill(-maxv);
00609   //the depth image
00610   vil1_memory_image_of<float> depth(w, h);
00611   float null_depth = -10;
00612   depth.fill(null_depth);
00613   //iterate through the depth planes
00614   vil1_memory_image_of<float> back;
00615   vcl_vector<vil1_memory_image_of<float> > imgs;
00616   vcl_vector<vgl_h_matrix_2d<double> > homgs, trans_homgs;
00617   vcl_vector<vcl_vector<vsol_point_2d_sptr> > proj_corners;
00618 
00619   for (double z = zmin_; z<=zmax_; z+=del_)
00620   {
00621     //get the overlap of the left and right images at the specified depth
00622     this->homographies_at_z(z, homgs);
00623     double tx=0, ty=0;
00624     this->overlapping_projections(homgs, imgs, proj_corners, tx, ty);
00625     vcl_vector<vsol_point_2d_sptr> matched_corners;
00626     if (!this->correlate_corners(imgs, proj_corners, matched_corners))
00627       return false;
00628     vcl_cout << "Matched " << matched_corners.size() << " corners at z = "
00629              << z << vcl_endl;
00630     for (vcl_vector<vsol_point_2d_sptr>::iterator pit = matched_corners.begin();
00631          pit != matched_corners.end(); pit++)
00632     {
00633       proj_points.push_back(*pit);
00634       //          bsol_algs::print(*pit);
00635     }
00636 
00637     //back project the matched corners (cam 1) onto the world x-y-z plane
00638     vcl_vector<vsol_point_2d_sptr> trans_pts =
00639       this->project_corners(homgs[1], matched_corners);
00640     //convert to 3-d points
00641     for (vcl_vector<vsol_point_2d_sptr>::iterator pit = trans_pts.begin();
00642          pit != trans_pts.end(); pit++)
00643     {
00644       double x = (*pit)->x(), y = (*pit)->y();
00645       vsol_point_3d_sptr p3d = new vsol_point_3d(x, y, z);
00646       points_3d.push_back(p3d);
00647       bsol_algs::print(p3d);
00648     }
00649     vcl_cout << vcl_endl;
00650   }
00651   return true;
00652 }
00653 
00654 bool brct_plane_sweeper::compute_harris()
00655 {
00656   int n_images = images_.size();
00657   if (n_images!=n_cams_)
00658   {
00659     vcl_cout << "In brct_plane_sweeper::compute_harris() - "
00660              << "images not matched to cameras\n";
00661     return false;
00662   }
00663   vcl_cout << hdp_ << vcl_endl;
00664   sdet_harris_detector hd(hdp_);
00665   for (int cam = 0; cam<n_cams_; cam++)
00666   {
00667     hd.clear();
00668     hd.set_image(images_[cam]);
00669     hd.extract_corners();
00670     vcl_vector<vsol_point_2d_sptr> points = hd.get_points();
00671     harris_corners_[cam]=points;
00672   }
00673   harris_valid_ = true;
00674   return true;
00675 }
00676 
00677 //return true if (r, c) has a neighbor within the radius
00678 static bool has_neighbor(const int r, const int c , const int radius,
00679                          const int h, const int w,
00680                          vbl_array_2d<bool> const& cnr_array)
00681 {
00682   //check bounds
00683   int rmin = radius, rmax = h-radius-1, cmin = radius, cmax = w-radius-1;
00684   if (r<rmin||r>rmax||c<cmin||c>cmax)
00685     return false;
00686   for (int r0 = -radius; r0<=radius; r0++)
00687     for (int c0 = -radius; c0<=radius; c0++)
00688       if (cnr_array[r+r0][c+c0])
00689         return true;
00690   return false;
00691 }
00692 
00693 //: match harris corners from image 1 to image 0 and return matches
00694 bool brct_plane_sweeper::
00695 correlate_corners(vcl_vector<vil1_memory_image_of<float> > const& imgs,
00696                   vcl_vector<vcl_vector<vsol_point_2d_sptr> > const& corners,
00697                   vcl_vector<vsol_point_2d_sptr>& matched_corners)
00698 {
00699   int n_imgs=imgs.size();
00700   int n_corn=corners.size();
00701   if (n_imgs!=2||n_imgs!=n_corn)
00702     return false;
00703   matched_corners.clear();
00704   int w = imgs[0].width(), h = imgs[0].height();
00705   vbl_array_2d<bool> pt_index(h, w);
00706   pt_index.fill(false);
00707   vcl_vector<vsol_point_2d_sptr> const& pts0 = corners[0],
00708     pts1 = corners[1];
00709   //for marking
00710   vcl_vector<vsol_point_2d_sptr> h1 = harris_corners_[1];
00711   //set the image 0 point_index array at Harris corner locations
00712   for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = pts0.begin();
00713        pit != pts0.end(); pit++)
00714   {
00715     int r = (int)((*pit)->y()), c = (int)((*pit)->x());
00716     if (r<0||r>=h||c<0||c>=w)
00717       continue;
00718     pt_index[r][c] = true;
00719   }
00720   //test each Harris corner in image 1 for a neighbor
00721   int n1 = pts1.size();
00722   for (int i = 0; i< n1; i++)
00723   {
00724     //sub-pixel locations
00725     double x0 = pts1[i]->x(), y0 = pts1[i]->y();
00726     //integer locations
00727     int r = (int)y0, c = (int)x0;
00728     if (r<0||r>=h||c<0||c>=w)
00729       continue;
00730     int pr = (int)point_radius_;
00731     if (has_neighbor(r, c, pr, h, w, pt_index))
00732     {
00733       float val =
00734         brip_vil1_float_ops::cross_correlate(imgs[0], imgs[1],
00735                                              float(x0), float(y0),
00736                                              corr_radius_,
00737                                              intensity_thresh_);
00738 
00739       if (val > corr_thresh_)
00740       {
00741         vsol_point_2d_sptr p = h1[i];
00742         matched_corners.push_back(p);//cache original Harris point
00743         vcl_cout << "C(" << p->x() << ' ' << p->y()
00744                  << ")=" << val << vcl_endl;
00745       }
00746     }
00747   }
00748   return true;
00749 }
00750 
00751 vcl_vector<vsol_point_2d_sptr>
00752 brct_plane_sweeper::harris_corners(const int cam)
00753 {
00754   vcl_vector<vsol_point_2d_sptr> points;
00755   if (cam>=n_cams_||!harris_valid_)
00756     return points;
00757   return harris_corners_[cam];
00758 }
00759 
00760 
00761 vil1_memory_image_of<unsigned char>
00762 brct_plane_sweeper::z_corr_image(const int i)
00763 {
00764   vil1_memory_image_of<unsigned char> temp;
00765   int li = i;
00766   int n = z_corr_images_.size();
00767   if (!n)
00768     return temp;
00769   if (i>=n)
00770     li = n-1;
00771   temp = brip_vil1_float_ops::convert_to_byte(z_corr_images_[li],
00772                                               corr_min_, corr_max_);
00773   return temp;
00774 }
00775 
00776 void brct_plane_sweeper::corr_vals(const int col, const int row,
00777                                    vcl_vector<float>& z,
00778                                    vcl_vector<float>& corr)
00779 {
00780   z.clear();
00781   corr.clear();
00782   int i = 0, n = z_corr_images_.size();
00783   for (float zi = zmin_; zi<=zmax_; zi+=del_, i++)
00784   {
00785     z.push_back(zi);
00786     if (i<n)
00787       corr.push_back(z_corr_images_[i](col, row));
00788   }
00789 }
00790 
00791 vsol_point_2d_sptr brct_plane_sweeper::
00792 map_point(vsol_point_2d_sptr const& p, vgl_h_matrix_2d<double> const& Hcomp)
00793 {
00794   vgl_homg_point_2d<double> hp(p->x(), p->y()), hp_to;
00795   //map the point
00796   hp_to = Hcomp(hp);
00797   vgl_point_2d<double> p_to(hp_to);
00798   return new vsol_point_2d(p_to);
00799 }
00800 
00801 vsol_point_2d_sptr brct_plane_sweeper::
00802 map_point(vsol_point_2d_sptr const& p, const int cam, const double z)
00803 {
00804   vsol_point_2d_sptr q;
00805   if (!p)
00806     return q;
00807   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00808   this->homographies_at_z(z, homgs);
00809   //assume two cameras for now
00810   int nc = homgs.size();
00811   if (nc!=2||cam>=nc)
00812     return q;
00813   vgl_h_matrix_2d<double> H_from = homgs[cam], H_to =homgs[1-cam];
00814   //form the composite homography
00815   vgl_h_matrix_2d<double> H_from_inv = H_from.get_inverse();
00816   vgl_h_matrix_2d<double> Hcomp = H_to*H_from_inv;
00817   return this->map_point(p, Hcomp);
00818 }
00819 
00820 //Map points from one image to the other assuming that they lie on plane z
00821 bool brct_plane_sweeper::
00822 map_points(const int from_cam, const double z,
00823            vcl_vector<vsol_point_2d_sptr> const& from_points,
00824            vcl_vector<vsol_point_2d_sptr>& to_points)
00825 {
00826   //get the homographies interpolated at plane z
00827   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00828   this->homographies_at_z(z, homgs);
00829   int nc = homgs.size();
00830   if (nc!=2||from_cam>=nc)
00831     return false;
00832   to_points.clear();
00833   int to_cam = 1-from_cam;
00834   vgl_h_matrix_2d<double> H_from = homgs[from_cam], H_to =homgs[to_cam];
00835   //map the point to the plane at z
00836   vgl_h_matrix_2d<double> H_from_inv = H_from.get_inverse();
00837   vgl_h_matrix_2d<double> Hcomp = H_to*H_from_inv;
00838 
00839   for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = from_points.begin();
00840        pit != from_points.end(); pit++)
00841     to_points.push_back(this->map_point(*pit, Hcomp));
00842 
00843   return true;
00844 }
00845 
00846 //: Map an image from one camera to the other, assuming all the pixels lie on the plane at z.
00847 //  Put the result into the coordinate frame of the target camera (to camera).
00848 bool brct_plane_sweeper::map_image(const int from_cam, const double z,
00849                                    vil1_memory_image_of<float>& mapped_image)
00850 {
00851   //get the homographies interpolated at plane z
00852   vcl_vector<vgl_h_matrix_2d<double> > homgs;
00853   this->homographies_at_z(z, homgs);
00854   int nc = homgs.size();
00855   if (nc!=2||from_cam>=nc)
00856     return false;
00857   int to_cam = 1-from_cam;
00858   //Form the composed map
00859   vgl_h_matrix_2d<double> Ha = homgs[from_cam], Hb =homgs[to_cam];
00860   vgl_h_matrix_2d<double> Hainv = Ha.get_inverse();
00861   vgl_h_matrix_2d<double> Hcomp = Hb*Hainv;
00862   vil1_memory_image_of<float> temp = smooth_images_[from_cam],
00863     to = smooth_images_[to_cam];
00864   vsol_box_2d_sptr from_box =box_from_image(temp), to_box = box_from_image(to),
00865     inter_box;
00866   vcl_cout << "Intersecting Mapped Box\n";
00867   if (this->intersecting_bounding_box(Hcomp, from_box, to_box, inter_box))
00868     bsol_algs::print(inter_box);
00869 
00870   mapped_image.resize(temp.width(), temp.height());
00871   if (!brip_vil1_float_ops::homography(temp, Hcomp, mapped_image, true, 0))
00872     return false;
00873   return true;
00874 }
00875 
00876 //: Map the image of the from_cam to the image space of the to_cam.
00877 //  Assumes that the world is a plane at z.
00878 bool brct_plane_sweeper::map_image_to_image(const int from_cam, const double z,
00879                                             vil1_memory_image_of<unsigned char>& mapped_to_image,
00880                                             vil1_memory_image_of<unsigned char>& orig_to_image)
00881 {
00882   vil1_memory_image_of<float> temp;
00883   if (!this->map_image(from_cam, z, temp))
00884     return false;
00885   int to_cam = 1-from_cam;
00886   mapped_to_image =  brip_vil1_float_ops::convert_to_byte(temp, 0, 255);
00887   orig_to_image =
00888     brip_vil1_float_ops::convert_to_byte(smooth_images_[to_cam], 0, 255);
00889   return true;
00890 }
00891 
00892 bool brct_plane_sweeper::
00893 intersecting_bounding_box(vgl_h_matrix_2d<double> const& Hcomp,
00894                           vsol_box_2d_sptr const& from_box,
00895                           vsol_box_2d_sptr const& to_box,
00896                           vsol_box_2d_sptr & box)
00897 {
00898   vsol_box_2d_sptr intersection = new vsol_box_2d();
00899   vsol_box_2d_sptr mapped_box;
00900   if (!bsol_algs::homography(from_box, Hcomp, mapped_box))
00901     return false;
00902   if (!bsol_algs::intersection(mapped_box, to_box, box))
00903     return false;
00904   return true;
00905 }
00906 
00907 bool brct_plane_sweeper::
00908 map_harris_corners(const int from_cam, const double z,
00909                    vcl_vector<vsol_point_2d_sptr>& mapped_to_points,
00910                    vcl_vector<vsol_point_2d_sptr>& orig_to_points)
00911 {
00912   if (from_cam<0||from_cam>=2)
00913     return false;
00914   if (!harris_valid_)
00915     return false;
00916   int to_cam = 1-from_cam;
00917   vcl_vector<vsol_point_2d_sptr> harris_from = harris_corners_[from_cam];
00918   orig_to_points = harris_corners_[to_cam];
00919   this->map_points(from_cam, z, harris_from, mapped_to_points);
00920   return true;
00921 }
00922 
00923 //:initialize the harris corner matching index
00924 void brct_plane_sweeper::init_harris_match(const int from_cam)
00925 {
00926   //make the grid 1/4 the size of the image
00927   int nrows = 192, ncols = 256;
00928   int to_cam = 1-from_cam;
00929   vcl_vector<vsol_point_2d_sptr> to_points = harris_corners_[to_cam];
00930   pindx_ = bsol_point_index_2d(nrows, ncols, to_points);
00931   vcl_vector<vsol_point_2d_sptr> temp = pindx_.points();
00932   vcl_cout << "\nTotal points in point index = " << temp.size() << vcl_endl;
00933   pindx_.clear_marks();
00934   matched_corners_.clear();
00935   del_ = (zmax_-zmin_)/nz_;
00936 }
00937 
00938 //:for debugging testing
00939 bool brct_plane_sweeper::
00940 match_harris_corners(const int from_cam,