Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bmvv_cal_manager.cxx

Go to the documentation of this file.
00001 // This is brl/bmvl/bmvv/bmvv_cal_manager.cxx
00002 #include "bmvv_cal_manager.h"
00003 //:
00004 // \file
00005 // \author J.L. Mundy
00006 
00007 #include <vcl_iostream.h>
00008 #include <vil/vil_image_view.h>
00009 #include <vil/vil_load.h>
00010 #include <vil/vil_save.h>
00011 #include <vil/vil_math.h>
00012 #include <vil/vil_new.h>
00013 #include <vnl/vnl_matrix_fixed.h>
00014 #include <vgl/algo/vgl_h_matrix_2d.h>
00015 #include <vgl/algo/vgl_p_matrix.h>
00016 #include <vgui/vgui.h>
00017 #include <vgui/vgui_key.h>
00018 #include <vgui/vgui_style.h>
00019 #include <vgui/vgui_macro.h>
00020 #include <vgui/vgui_dialog.h>
00021 #include <vgui/vgui_image_tableau.h>
00022 #include <vgui/vgui_viewer2D_tableau.h>
00023 #include <vgui/vgui_shell_tableau.h>
00024 #include <vgui/vgui_range_map_params.h>
00025 #include <vgui/vgui_projection_inspector.h>
00026 #include <bgui/bgui_image_tableau.h>
00027 #include <bgui/bgui_range_adjuster_tableau.h>
00028 #include <bgui/bgui_vsol_soview2D.h>
00029 #include <bgui/bgui_vtol2D_tableau.h>
00030 #include <bgui/bgui_picker_tableau.h>
00031 #include <brip/brip_vil_float_ops.h>
00032 #include <brct/brct_algos.h>
00033 #include <vsol/vsol_point_2d.h>
00034 #include <vsol/vsol_point_3d.h>
00035 #include <vsol/vsol_polygon_2d.h>
00036 #include <vsol/vsol_polygon_3d.h>
00037 #include <vpgl/vpgl_proj_camera.h>
00038 #include <vpgl/algo/vpgl_camera_compute.h>
00039 #include <vpgl/algo/vpgl_optimize_camera.h>
00040 //static live_video_manager instance
00041 bmvv_cal_manager *bmvv_cal_manager::instance_ = 0;
00042 //===============================================================
00043 
00044 //: The singleton pattern - only one instance of the manager can occur
00045 //==============================================================
00046 bmvv_cal_manager *bmvv_cal_manager::instance()
00047 {
00048   if (!instance_)
00049   {
00050     instance_ = new bmvv_cal_manager();
00051     instance_->init();
00052   }
00053   return bmvv_cal_manager::instance_;
00054 }
00055 
00056 //==================================================================
00057 //: constructors/destructor
00058 //==================================================================
00059 bmvv_cal_manager::
00060 bmvv_cal_manager() : vgui_wrapper_tableau(), cam_(vgl_p_matrix<double>()),
00061                      prev_cam_(vgl_p_matrix<double>())
00062 {
00063   corrs_.resize(0);
00064   corrs_valid_.resize(0);
00065   proj_image_pts_.resize(0);
00066   corr_sovs_.resize(0);
00067 }
00068 
00069 bmvv_cal_manager::~bmvv_cal_manager()
00070 {
00071   delete instance_;
00072 }
00073 
00074 //======================================================================
00075 //: set up the tableaux at each grid cell
00076 //  The vtol2D_tableaux have been initialized in the constructor
00077 //======================================================================
00078 void bmvv_cal_manager::init()
00079 {
00080   itab_ = bgui_image_tableau_new();
00081   btab_ = bgui_vtol2D_tableau_new(itab_);
00082   ptab_ = bgui_picker_tableau_new(btab_);
00083   vgui_viewer2D_tableau_sptr vtab =  vgui_viewer2D_tableau_new(ptab_);
00084   vgui_shell_tableau_sptr shell = vgui_shell_tableau_new(vtab);
00085   this->add_child(shell);
00086   height_ = 0.0;
00087 }
00088 
00089 //=========================================================================
00090 //: make an event handler
00091 // Note that we have to get an adaptor and set the tableau to receive events
00092 // this handler does nothing but is a place holder for future event processing
00093 // For now, just pass the events down to the child tableaux
00094 //=========================================================================
00095 bool bmvv_cal_manager::handle(const vgui_event &e)
00096 {
00097   vgui_projection_inspector proj;
00098   if (e.type == vgui_KEY_PRESS)
00099   {
00100     if (btab_)
00101       if (e.key == 'u')
00102       {
00103         btab_->deselect_all();
00104         return true;
00105       }
00106   }
00107   return this->child.handle(e);
00108 }
00109 
00110 //=========================================================================
00111 //: Quit
00112 //=========================================================================
00113 void bmvv_cal_manager::quit()
00114 {
00115   vgui::quit();
00116 }
00117 
00118 //=========================================================================
00119 //: load an image an put it in the currently selected grid cell
00120 //=========================================================================
00121 void bmvv_cal_manager::load_image_file(vcl_string image_filename, bool /* greyscale */)
00122 {
00123   //add greyscale later
00124   img_ = vil_load_image_resource(image_filename.c_str());
00125   if (!img_)
00126   {
00127     vcl_cout << "Null image resource - couldn't load from "
00128              << image_filename << '\n';
00129     return;
00130   }
00131   vgui_range_map_params_sptr rmps = range_params(img_);
00132   if (itab_)
00133   {
00134     itab_->set_image_resource(img_, rmps);
00135     return;
00136   }
00137   vcl_cout << "In bmvv_cal_manager::load_image_file() - null tableau\n";
00138 }
00139 
00140 void bmvv_cal_manager::add_image(vil_image_resource_sptr const& image,
00141                                  vgui_range_map_params_sptr rmps,
00142                                  bool greyscale)
00143 {
00144   if (greyscale)
00145   {
00146 #if 0// do nothing right now
00147     vil1_memory_image_of<unsigned char> temp1 =
00148     brip_vil1_float_ops::convert_to_grey(image);
00149     img_ = temp1;
00150 #endif
00151   }
00152   else
00153     img_ = image;
00154 
00155   if (itab_)
00156   {
00157     itab_->set_image_resource(img_, rmps);
00158     itab_->post_redraw();
00159     return;
00160   }
00161   vcl_cout << "In bmvv_cal_manager::load_image() - null tableau\n";
00162 }
00163 
00164 //=========================================================================
00165 //: load an image an put it in the currently selected grid cell
00166 //=========================================================================
00167 void bmvv_cal_manager::load_image()
00168 {
00169   static bool greyscale = false;
00170   vgui_dialog load_image_dlg("Load Image");
00171   static vcl_string image_filename = "";
00172   static vcl_string ext = "*.*";
00173   load_image_dlg.file("Image Filename:", ext, image_filename);
00174   load_image_dlg.checkbox("greyscale ", greyscale);
00175   if (!load_image_dlg.ask())
00176     return;
00177   vil_image_resource_sptr temp = vil_load_image_resource(image_filename.c_str());
00178   vgui_range_map_params_sptr rmps = range_params(temp);
00179   this->add_image(temp, rmps, greyscale);
00180 }
00181 
00182 void bmvv_cal_manager::save_image()
00183 {
00184   vgui_dialog file_dialog("Save Image");
00185   static vcl_string image_file;
00186   static vcl_string ext = "tif";
00187   static vcl_string type = "tiff";
00188   static bool byte = false;
00189   file_dialog.file("Image Filename:", ext, image_file);
00190   file_dialog.field("Image Format: ", type);
00191   file_dialog.checkbox("Convert to byte image", byte);
00192   if (!file_dialog.ask())
00193     return;
00194   vil_image_resource_sptr img = itab_->get_image_resource();
00195   if (!img)
00196   {
00197     vcl_cerr << "Null image in bmvv_cal_manager::save_image\n";
00198     return;
00199   }
00200   vil_image_resource_sptr save_image = img;
00201   if (byte)
00202   {
00203     vil_image_view<unsigned char> byte_view = brip_vil_float_ops::convert_to_byte(img);
00204     save_image = vil_new_image_resource_of_view(byte_view);
00205   }
00206   if (!vil_save_image_resource(save_image, image_file.c_str(), type.c_str() ))
00207     vcl_cerr << "bmvv_cal_manager::save_image operation failed\n";
00208 }
00209 
00210 void bmvv_cal_manager::adjust_contrast()
00211 {
00212   if (!itab_)
00213     return;
00214   bgui_range_adjuster_tableau_sptr h= bgui_range_adjuster_tableau_new(itab_);
00215   h->set_hardware(true);
00216   h->update();
00217   vgui_viewer2D_tableau_sptr v = vgui_viewer2D_tableau_new(h);
00218   vgui_shell_tableau_sptr s = vgui_shell_tableau_new(v);
00219   //popup adjuster
00220   vgui_dialog contrast("Histogram Range Adjuster");
00221   contrast.inline_tableau(s, 280, 200);
00222   if (!contrast.ask())
00223     return;
00224 }
00225 
00226 //===================================================================
00227 //: Clear the display
00228 //===================================================================
00229 void bmvv_cal_manager::clear_display()
00230 {
00231   if (btab_)
00232     btab_->clear_all();
00233   else
00234     vcl_cout << "In bmvv_cal_manager::clear_display() - null tableau\n";
00235 }
00236 
00237 //===================================================================
00238 //: clear all selections in both panes
00239 //===================================================================
00240 void bmvv_cal_manager::clear_selected()
00241 {
00242   if (btab_)
00243     btab_->clear_all();
00244 }
00245 
00246 void bmvv_cal_manager::draw_corr_point(const float x, const float y)
00247 {
00248   if (!btab_)
00249     return;
00250   btab_->set_point_radius(5.0f);
00251   btab_->set_foreground(0.0f, 1.0f, 0.0f);
00252   btab_->add_point(x, y);
00253   btab_->post_redraw();
00254 }
00255 
00256 
00257 //: Calculate the range parameters for the input image
00258 vgui_range_map_params_sptr bmvv_cal_manager::
00259 range_params(vil_image_resource_sptr const& image)
00260 {
00261   float gamma = 1.0;
00262   bool invert = false;
00263   bool gl_map = false;
00264   bool cache = true;
00265   unsigned min = 0, max = 255;
00266   if (image->pixel_format()==VIL_PIXEL_FORMAT_BYTE)
00267   {
00268     vil_image_view<unsigned char> temp = image->get_view();
00269     unsigned char vmin=0, vmax=255;
00270     vil_math_value_range<unsigned char>(temp, vmin, vmax);
00271     min = static_cast<unsigned>(vmin);
00272     max = static_cast<unsigned>(vmax);
00273     return  new vgui_range_map_params(min, max, gamma, invert,
00274                                       gl_map, cache);
00275   }
00276   if (image->pixel_format()==VIL_PIXEL_FORMAT_UINT_16)
00277   {
00278     vil_image_view<unsigned short> temp = image->get_view();
00279     unsigned short vmin=0, vmax=60000;
00280     vil_math_value_range<unsigned short>(temp, vmin, vmax);
00281     min = static_cast<unsigned>(vmin);
00282     max = static_cast<unsigned>(vmax);
00283     gl_map = true;
00284     return  new vgui_range_map_params(min, max, gamma, invert,
00285                                       gl_map, cache);
00286   }
00287 vcl_cout << "Image pixel format not handled\n";
00288  return new vgui_range_map_params(0, 255, gamma, invert,
00289                                       gl_map, cache);
00290 }
00291 
00292 void bmvv_cal_manager::set_range_params()
00293 {
00294   if (!itab_||!itab_->get_image_resource())
00295     return;
00296   static double min = 0.0, max = 255;
00297   static float gamma = 1.0;
00298   static bool invert = false;
00299   static bool gl_map = false;
00300   static bool cache = false;
00301   vgui_dialog range_dlg("Set Range Map Params");
00302   range_dlg.field("Range min:", min);
00303   range_dlg.field("Range max:", max);
00304   range_dlg.field("Gamma:", gamma);
00305   range_dlg.checkbox("Invert:", invert);
00306   range_dlg.checkbox("Use GL Mapping", gl_map);
00307   range_dlg.checkbox("Cache Pixels", cache);
00308   if (!range_dlg.ask())
00309     return;
00310   vil_image_resource_sptr img = itab_->get_image_resource();
00311   unsigned n_components = img->nplanes();
00312   vgui_range_map_params_sptr rmps;
00313   if (n_components == 1)
00314     rmps= new vgui_range_map_params(min, max, gamma, invert,
00315                                     gl_map, cache);
00316   else if (n_components == 3)
00317     rmps = new vgui_range_map_params(min, max, min, max, min, max,
00318                                      gamma, gamma, gamma, invert,
00319                                      gl_map, cache);
00320   else
00321     rmps = 0;
00322   itab_->set_mapping(rmps);
00323 }
00324 
00325 void bmvv_cal_manager::load_image_and_camera()
00326 {
00327   static bool greyscale = false;
00328   static vcl_string cam_file = "";
00329   static vcl_string cam_ext = "*.cam";
00330   static vcl_string image_file = "";
00331   static vcl_string ext = "*.*";
00332   vgui_dialog image_cam_dlg("Read Image and Cam");
00333   image_cam_dlg.file("Image Filename:", ext, image_file);
00334   image_cam_dlg.file("Camera File", cam_ext, cam_file);
00335   image_cam_dlg.checkbox("greyscale ", greyscale);
00336   if (!image_cam_dlg.ask())
00337     return;
00338   vil_image_resource_sptr temp = vil_load_image_resource(image_file.c_str());
00339   vgui_range_map_params_sptr rmps = range_params(temp);
00340   this->add_image(temp, rmps, greyscale);
00341   vcl_ifstream cam_istr(cam_file.c_str());
00342   cam_istr >> cam_;
00343   vcl_cout << "Read Camera " << cam_ << '\n';
00344   this->project_world();
00345 }
00346 
00347 void bmvv_cal_manager::load_corrs()
00348 {
00349   vgui_dialog corr_dlg("Load Correspondences");
00350   static vcl_string corr_file = "";
00351   static vcl_string corr_ext = "*.cm";
00352   corr_dlg.file("Correspondence File", corr_ext, corr_file);
00353   if (!corr_dlg.ask())
00354     return;
00355   vcl_ifstream corr_istr(corr_file.c_str());
00356   this->clear_correspondences();
00357   world_.clear();
00358   world_.resize(0);
00359   if (!brct_algos::read_target_corrs(corr_istr, corrs_valid_, corrs_, world_))
00360   {
00361     vcl_cout << "Failed to read correspondences\n";
00362     return ;
00363   }
00364   if (!btab_)
00365     return;
00366   btab_->clear_all();
00367   this->project_world();
00368   //  this->draw_correspondences();
00369 }
00370 
00371 void bmvv_cal_manager::save_corrs()
00372 {
00373   vgui_dialog corr_dlg("Save Correspondences");
00374   static vcl_string corr_file = "";
00375   static vcl_string corr_ext = "*.cm";
00376   corr_dlg.file("Correspondence File", corr_ext, corr_file);
00377   if (!corr_dlg.ask())
00378     return;
00379   vcl_ofstream corr_ostr(corr_file.c_str());
00380   if (!brct_algos::write_corrs(corr_ostr, corrs_valid_, corrs_, world_))
00381   {
00382     vcl_cout << "Failed to write correspondences\n";
00383     return ;
00384   }
00385 }
00386 
00387 void bmvv_cal_manager::save_camera()
00388 {
00389   vgui_dialog cam_dlg("Save Camera");
00390   static vcl_string cam_file = "";
00391   static vcl_string cam_ext = "*.cam";
00392   static bool target = false;
00393   cam_dlg.file("Camera File", cam_ext, cam_file);
00394   cam_dlg.checkbox("Target?", target);
00395   if (!cam_dlg.ask())
00396     return;
00397   vcl_ofstream cam_ostr(cam_file.c_str());
00398   if (!cam_ostr)
00399   {
00400     vcl_cout << "Bad camera file\n";
00401     return;
00402   }
00403   if (!target) {
00404     cam_ostr << cam_;
00405     cam_ostr.close();
00406     return;
00407   }
00408   brct_algos::write_target_camera(cam_ostr, cam_.get_matrix());
00409 }
00410 
00411 void bmvv_cal_manager::set_identity_camera()
00412 {
00413   vnl_matrix_fixed<double,3,4> M;
00414   M[0][0] = 1.0;   M[0][1] = 0.0; M[0][2] = 0.0; M[0][3] = 0.0;
00415   M[1][0] = 0.0;   M[1][1] = 1.0; M[1][2] = 0.0; M[1][3] = 0.0;
00416   M[2][0] = 0.0;   M[2][1] = 0.0; M[2][2] = 0.0; M[2][3] = 1.0;
00417   cam_ = vgl_p_matrix<double>(M);
00418 }
00419 
00420 void bmvv_cal_manager::load_world()
00421 {
00422   vgui_dialog world_dlg("Load World Points3D");
00423   static vcl_string world_file = "";
00424   static vcl_string world_ext = "*.wd";
00425   world_dlg.file("World Point File", world_ext, world_file);
00426   if (!world_dlg.ask())
00427     return;
00428   vcl_ifstream world_istr(world_file.c_str());
00429   this->clear_correspondences();
00430   this->clear_world();
00431   if (!brct_algos::read_world(world_istr, world_, polys_, indexed_face_set_))
00432   {
00433     vcl_cout << "Failed to read world\n";
00434     return ;
00435   }
00436   //add polygons
00437   if (!btab_)
00438     return;
00439   btab_->clear();
00440   //make sure the correspondence point array is the same size as the world
00441   int n = world_.size();
00442   corrs_.resize(n, vgl_point_2d<double>(0,0));
00443   corr_sovs_.resize(n, (vgui_soview2D_point*)0);
00444   corrs_valid_.resize(n, false);
00445   this->project_world();
00446 }
00447 
00448 void bmvv_cal_manager::save_world()
00449 {
00450   vgui_dialog world_dlg("Save World");
00451   static vcl_string world_file = "";
00452   static vcl_string world_ext = "*.wd";
00453   world_dlg.file("World File", world_ext, world_file);
00454   if (!world_dlg.ask())
00455     return;
00456   vcl_ofstream world_ostr(world_file.c_str());
00457   brct_algos::write_world(world_ostr, world_, indexed_face_set_);
00458 }
00459 
00460 void bmvv_cal_manager::save_world_ply2()
00461 {
00462   vgui_dialog world_dlg("Save World Ply2");
00463   static vcl_string world_file = "";
00464   static vcl_string world_ext = "*.ply2";
00465   world_dlg.file("Ply2 File", world_ext, world_file);
00466   if (!world_dlg.ask())
00467     return;
00468   vcl_ofstream world_ostr(world_file.c_str());
00469   brct_algos::write_world_ply2(world_ostr, world_, indexed_face_set_);
00470 }
00471 
00472 bool bmvv_cal_manager::draw_correspondences()
00473 {
00474   if (!btab_)
00475     return false;
00476   btab_->set_point_radius(5.0f);
00477   btab_->set_foreground(0.0f, 1.0f, 1.0f);
00478   unsigned i = 0;
00479   for (vcl_vector<vgl_point_2d<double> >::iterator pit = corrs_.begin();
00480        pit != corrs_.end(); ++pit, ++i)
00481     if (corrs_valid_[i])
00482       corr_sovs_.push_back(btab_->add_point((*pit).x(), (*pit).y()));
00483     else
00484       corr_sovs_.push_back((vgui_soview2D_point*)0);
00485   btab_->post_redraw();
00486   return true;
00487 }
00488 
00489 void bmvv_cal_manager::read_world_ply2()
00490 {
00491   vgui_dialog world_dlg("Read World Ply2");
00492   static vcl_string world_file = "";
00493   static vcl_string world_ext = "*.ply2";
00494   world_dlg.file("Ply2 File", world_ext, world_file);
00495   if (!world_dlg.ask())
00496     return;
00497   vcl_ifstream world_istr(world_file.c_str());
00498   brct_algos::read_world_ply2(world_istr, world_, polys_, indexed_face_set_);
00499   this->project_world();
00500 }
00501 
00502 void bmvv_cal_manager::clear_correspondences()
00503 {
00504   if (!btab_)
00505     return;
00506   btab_->clear_all();
00507   corrs_.clear();
00508   corr_sovs_.clear();
00509   corrs_valid_.clear();
00510   corrs_.resize(0);
00511   corrs_valid_.resize(0);
00512   corr_sovs_.resize(0);
00513 }
00514 
00515 bool bmvv_cal_manager::draw_projected_world_points()
00516 {
00517   if (!btab_)
00518     return false;
00519   int i = 0;
00520   point_3d_map_.clear();
00521   btab_->set_point_radius(5.0f);
00522   btab_->set_foreground(1.0f, 1.0f, 0.2f);
00523   for (vcl_vector<vgl_point_2d<double> >::iterator pit = proj_image_pts_.begin();
00524        pit != proj_image_pts_.end(); pit++, ++i)
00525   {
00526     vgui_soview2D_point* sov = btab_->add_point((*pit).x(), (*pit).y());
00527     int id = sov->get_id();
00528     point_3d_map_[id]=i;
00529   }
00530   btab_->post_redraw();
00531   return true;
00532 }
00533 
00534 
00535 int  bmvv_cal_manager::get_selected_proj_world_pt(vgl_point_2d<double>&  pt)
00536 {
00537   if (!btab_)
00538     return  -1;
00539   vcl_vector<unsigned> ids = btab_->get_selected();
00540   //take the last selected
00541   int n = ids.size();
00542   if (!n)
00543   {
00544     vcl_cout << "Nothing selected\n";
00545     return -1;
00546   }
00547   unsigned int i = point_3d_map_[ids[n-1]];
00548   if (i<proj_image_pts_.size())
00549   {
00550     pt =  proj_image_pts_[i];
00551     return i;
00552   }
00553   vcl_cout << "Bogus correspondence\n";
00554   return -1;
00555 }
00556 
00557 void bmvv_cal_manager::pick_correspondence()
00558 {
00559   if (!world_.size())
00560   {
00561     vcl_cout << "Can't pick correspondence - null 3D world\n";
00562     return;
00563   }
00564   vgl_point_2d<double> pt;
00565   int id = this->get_selected_proj_world_pt(pt);
00566   if (id<0)
00567     return;
00568   vcl_cout << "Projected world point " << pt << '\n';
00569   if (!ptab_)
00570   {
00571     vcl_cout << "Can't pick correspondence - null picker tableau\n";
00572     return;
00573   }
00574   ptab_->set_color(0.0f, 1.0f, 1.0f);
00575   ptab_->set_line_width(3.0f);
00576   float x, y;
00577   ptab_->anchored_pick_point(pt.x(), pt.y(), &x, &y);
00578   corrs_[id].set(x, y);
00579   corrs_valid_[id]=true;
00580   ptab_->set_color();//restore defaults
00581   ptab_->set_line_width();
00582 
00583   if (!btab_)
00584     return;
00585   btab_->set_foreground(0.0f, 1.0f, 1.0f);
00586   btab_->set_point_radius(5.0);
00587   if (!corr_sovs_[id])
00588     corr_sovs_[id]=btab_->add_point(x, y);
00589   else {
00590     corr_sovs_[id]->x = x;
00591     corr_sovs_[id]->y = y;
00592   }
00593   btab_->post_redraw();
00594 }
00595 
00596 void bmvv_cal_manager::remove_correspondence()
00597 {
00598   if (!world_.size())
00599   {
00600     vcl_cout << "Can't remove correspondence - null 3D world\n";
00601     return;
00602   }
00603   vgl_point_2d<double> pt;
00604   int id = this->get_selected_proj_world_pt(pt);
00605   if (id<0)
00606     return;
00607   corrs_[id].set(0, 0);
00608   corrs_valid_[id]=false;
00609   corr_sovs_[id]=(vgui_soview2D_point*)0;
00610   if (!btab_)
00611   {
00612     vcl_cout << "Correspondence removal aborted in progress- null btab\n";
00613     return;
00614   }
00615   this->project_world();
00616   //  this->draw_correspondences();
00617 }
00618 
00619 void bmvv_cal_manager::pick_vertical()
00620 {
00621   ptab_->set_color(0.0f, 1.0f, 0.0f);
00622   ptab_->set_line_width(3.0f);
00623   float x1, y1,x2, y2;
00624   ptab_->pick_line(&x1, &y1, &x2, &y2);
00625   vgl_point_2d<double> p1(x1, y1), p2(x2,y2);
00626   vgl_line_segment_2d<double> vertical(p1, p2);
00627   verticals_.push_back(vertical);
00628   ptab_->set_color();//restore defaults
00629   ptab_->set_line_width();
00630   if (!btab_)
00631     return;
00632   btab_->set_foreground(0.0f, 1.0f, 0.0f);
00633   btab_->add_line(x1,y1,x2,y2);
00634   btab_->post_redraw();
00635 }
00636 
00637 void bmvv_cal_manager::project_world()
00638 {
00639   if (!btab_)
00640   {
00641     vcl_cout << "Can't project world - null btab\n";
00642     return;
00643   }
00644   btab_->clear_all();
00645   brct_algos::project(world_, cam_, proj_image_pts_);
00646   this->draw_projected_world_points();
00647   this->draw_polygons_3d(false, 0.0f, 1.0f, 0.0f);
00648   this->draw_correspondences();
00649 }
00650 
00651 namespace
00652 {
00653 //: function to roughly flip the camera around a set of points when the points are behind the camera.
00654 //   Optimization is needed after this operation.
00655 void flip_camera(vpgl_perspective_camera<double> &camera,
00656                  const vcl_vector< vgl_homg_point_3d<double> >& world_hpts)
00657 {
00658   vgl_vector_3d<double> centroid(0.0, 0.0, 0.0);
00659   unsigned int num_behind = 0;
00660   for (unsigned i = 0; i<world_hpts.size(); ++i){
00661     if (camera.is_behind_camera(world_hpts[i])){
00662       vgl_point_3d<double> p(world_hpts[i]);
00663       centroid += vgl_vector_3d<double>(p.x(),p.y(),p.z());
00664       ++num_behind;
00665     }
00666   }
00667   centroid /= num_behind;
00668 
00669   vgl_point_3d<double> C = camera.get_camera_center();
00670   vcl_cout << "initial center: "<< C<<vcl_endl;
00671   C += 2*(vgl_point_3d<double>(centroid.x(),centroid.y(),centroid.z())-C);
00672   camera.set_camera_center(C);
00673   vcl_cout << "new center: " <<C<<vcl_endl;
00674 }
00675 
00676 }; // namespace
00677 
00678 void bmvv_cal_manager::solve_camera()
00679 {
00680   static bool planar = false;
00681   static bool deg_planar = false;
00682   static bool optimize = true;
00683   static bool restore = false;
00684   vgui_dialog read_homg_dlg("Solve Camera");
00685   read_homg_dlg.checkbox("Planar Camera Only? ", planar);
00686   read_homg_dlg.checkbox("Mostly Planar Camera? ", deg_planar);
00687   read_homg_dlg.checkbox("Optimize? ", optimize);
00688   read_homg_dlg.checkbox("Restore Previous Camera? ", restore);
00689   if (!read_homg_dlg.ask())
00690     return;
00691   if (restore)
00692   {
00693     cam_=prev_cam_;
00694     return;
00695   }
00696 
00697   if (planar || deg_planar)
00698   {
00699     vcl_vector<double> image_y;
00700     vcl_vector< vgl_point_2d<double> > zero_Z_image_corr;
00701     vcl_vector< vgl_point_3d<double> > zero_Z_pts;
00702     vcl_vector< vgl_point_3d<double> > non_zero_Z_pts;
00703     unsigned int n = world_.size();
00704     for (unsigned i = 0; i<n; i++)
00705     {
00706       if (!corrs_valid_[i])
00707         continue;
00708       if (vcl_fabs(world_[i].z()) < 0.01) //planar points
00709       {
00710         zero_Z_pts.push_back(world_[i]);
00711         zero_Z_image_corr.push_back(corrs_[i]);
00712       }
00713       else // non-planar point for camera elevation constraint
00714       {
00715         image_y.push_back(corrs_[i].y());
00716         non_zero_Z_pts.push_back(world_[i]);
00717       }
00718     }
00719     vgl_h_matrix_2d<double> H;
00720     if (!brct_algos::homography(zero_Z_pts, zero_Z_image_corr, H, optimize))
00721     {
00722       vcl_cout << "Linear SVD solve for homography failed\n";
00723       return;
00724     }
00725     //protect from bad solution by saving old camera
00726     prev_cam_ = cam_;
00727     if (!planar)
00728       cam_= brct_algos::p_from_h(H,image_y, non_zero_Z_pts);
00729     else
00730       cam_= brct_algos::p_from_h(H);
00731   }
00732   else
00733   {
00734     vcl_vector< vgl_homg_point_2d<double> > image_hpts;
00735     vcl_vector< vgl_homg_point_3d<double> > world_hpts;
00736     unsigned int n = world_.size();
00737     for (unsigned i = 0; i<n; i++)
00738     {
00739       if (!corrs_valid_[i])
00740         continue;
00741       image_hpts.push_back(vgl_homg_point_2d<double>(corrs_[i]));
00742       world_hpts.push_back(vgl_homg_point_3d<double>(world_[i]));
00743     }
00744     vpgl_proj_camera<double> camera;
00745     vpgl_proj_camera_compute::compute(image_hpts,world_hpts,camera);
00746     prev_cam_ = cam_;
00747     cam_ = vgl_p_matrix<double>(camera.get_matrix());
00748 
00749     vpgl_perspective_camera<double> p_camera;
00750     if (optimize && vpgl_perspective_decomposition(camera.get_matrix(),p_camera)){
00751       vcl_vector< vgl_point_2d<double> > image_pts;
00752       unsigned int num_behind = 0;
00753       for (unsigned i = 0; i<image_hpts.size(); i++){
00754         if (p_camera.is_behind_camera(world_hpts[i]))
00755           ++num_behind;
00756         image_pts.push_back(image_hpts[i]);
00757       }
00758       if (num_behind > world_hpts.size()/2){
00759         vcl_cout << "Majority of points behind camera, flipping" << vcl_endl;
00760         flip_camera(p_camera, world_hpts);
00761       }
00762       p_camera = vpgl_optimize_camera::opt_orient_pos_cal(p_camera, world_hpts, image_pts);
00763       cam_ = vgl_p_matrix<double>(p_camera.get_matrix());
00764     }
00765   }
00766 
00767   if (!btab_)
00768     return;
00769   btab_->clear_all();
00770   this->project_world();
00771   //this->draw_correspondences();
00772 }
00773 
00774 
00775 void bmvv_cal_manager::
00776 draw_vsol_points(const int cam, vcl_vector<vsol_point_2d_sptr> const & points,
00777                  bool clear, const float r, const float g, const float b)
00778 {
00779   if (!btab_)
00780   {
00781     vcl_cout << "In bmvv_cal_manager::draw_vsol_points(..) -"
00782              << " null btol tableau for pane " << cam << vcl_endl;
00783     return;
00784   }
00785   if (clear)
00786     btab_->clear_all();
00787   vgui_style_sptr style = vgui_style::new_style(r, g, b, 3, 0);
00788   for (vcl_vector<vsol_point_2d_sptr>::const_iterator pit = points.begin();
00789        pit != points.end(); pit++)
00790     btab_->add_vsol_point_2d(*pit, style);
00791 }
00792 
00793 void bmvv_cal_manager::
00794 draw_vsol_point(const int cam, vsol_point_2d_sptr const & point,
00795                 bool clear, const float r, const float g, const float b)
00796 {
00797   if (!btab_)
00798   {
00799     vcl_cout << "In bmvv_cal_manager::draw_vsol_point(..) -"
00800              << " null btol tableau for pane " << cam << vcl_endl;
00801     return;
00802   }
00803   if (clear)
00804     btab_->clear_all();
00805   vgui_style_sptr style = vgui_style::new_style(r, g, b, 3, 0);
00806   btab_->add_vsol_point_2d(point,style);
00807 }
00808 
00809 
00810 void bmvv_cal_manager::compute_ransac_homography()
00811 {
00812   vgui_dialog read_homg_dlg("Read Correspondence File");
00813   static vcl_string corr_filename = "";
00814   static vcl_string corr_ext = "*.cm";
00815   static vcl_string cam_filename = "";
00816   static vcl_string cam_ext = "*.cam";
00817   static bool show_projected_points = true;
00818   static bool optimize = true;
00819   vcl_vector<vcl_string> choices;
00820   static int choice=0;
00821   choices.push_back("Linear SVD");
00822   choices.push_back("RANSAC");
00823   choices.push_back("MUSE");
00824   read_homg_dlg.file("TargetJr correspondence file", corr_ext, corr_filename);
00825   read_homg_dlg.file("TargetJr camera file", cam_ext, cam_filename);
00826   read_homg_dlg.checkbox("Show Projected Points ",show_projected_points);
00827   read_homg_dlg.choice("Homography Algo.", choices, choice);
00828   read_homg_dlg.checkbox("Optimize? ", optimize);
00829   if (!read_homg_dlg.ask())
00830     return;
00831   if (corr_filename == ""||cam_filename == "")
00832   {
00833     vcl_cout << "Need a file name\n";
00834     return;
00835   }
00836 
00837   this->clear_display();
00838   vcl_ifstream istr(corr_filename.c_str());
00839   vcl_ofstream ostr(cam_filename.c_str());
00840   vcl_string target_file = cam_filename + "-target";
00841   vcl_ofstream ostr_tar(target_file.c_str());
00842   vcl_vector<bool> valid;
00843   vcl_vector<vgl_point_2d<double> > image_points;
00844   vcl_vector<vgl_point_3d<double> > world_points;
00845   if (!brct_algos::read_target_corrs(istr, valid, image_points, world_points))
00846   {
00847     vcl_cout << "Failed to read correspondences\n";
00848     return;
00849   }
00850   bool show = show_projected_points;
00851   // compute the homography using ransac
00852   vgl_h_matrix_2d<double> H;
00853   switch (choice)
00854   {
00855    case 0:
00856     if (!brct_algos::homography(world_points, image_points, H, optimize))
00857       show = false;
00858     break;
00859    case 1:
00860     if (!brct_algos::homography_ransac(world_points, image_points, H, optimize))
00861       show = false;
00862     break;
00863    case 2:
00864     if (!brct_algos::homography_muse(world_points, image_points, H, optimize))
00865       show = false;
00866     break;
00867   }
00868   vcl_vector<vgl_point_2d<double> > proj_image_points;
00869   vgl_p_matrix<double> P =  brct_algos::p_from_h(H);
00870   brct_algos::project(world_points, P, proj_image_points);
00871 
00872   if (!btab_)
00873     return;
00874   vgui_style_sptr r_style = vgui_style::new_style(1.0, 0.0, 0.0, 5, 0);
00875   vgui_style_sptr g_style = vgui_style::new_style(0.0, 1.0, 0.0, 5, 0);
00876   for (unsigned int i = 0; i<world_points.size(); i++)
00877   {
00878     vgl_point_2d<double> ip = image_points[i];
00879     vgl_point_2d<double> pip = proj_image_points[i];
00880     vsol_point_2d_sptr vip = new vsol_point_2d(ip.x(),ip.y());
00881     vsol_point_2d_sptr vpip = new vsol_point_2d(pip.x(),pip.y());
00882     vcl_cout << ip << " == " << pip << vcl_endl;
00883     btab_->add_vsol_point_2d(vip,r_style);
00884     if (show) btab_->add_vsol_point_2d(vpip,g_style);
00885   }
00886   btab_->post_redraw();
00887 
00888   //write out the camera
00889   ostr << P;
00890   //Also as a target camera for interest sake
00891   brct_algos::write_target_camera(ostr_tar, P.get_matrix());
00892 }
00893 
00894 //map the image back to cartesian world coordinates
00895 void bmvv_cal_manager::map_image_to_world()
00896 {
00897   vil_image_resource_sptr img = itab_->get_image_resource();
00898   if (!img)
00899     return;
00900   vil_image_resource_sptr world_image =
00901     brct_algos::map_image_to_world(img, cam_);
00902   if (world_image)
00903   {
00904     vgui_range_map_params_sptr rmps = range_params(world_image);
00905     this->add_image(world_image, rmps);
00906   }
00907 }
00908 
00909 void bmvv_cal_manager::save_constraints()
00910 {
00911   vgui_dialog cnst_dlg("Save Constraints");
00912   static vcl_string con_file = "";
00913   static vcl_string con_ext = "*.con";
00914   cnst_dlg.file("Constraint File", con_ext, con_file);
00915   if (!cnst_dlg.ask())
00916     return;
00917   vcl_ofstream con_ostr(con_file.c_str());
00918   if (!con_ostr)
00919   {
00920     vcl_cout << "Bad constraint file\n";
00921     return;
00922   }
00923   if (!brct_algos::save_constraint_file(corrs_, corrs_valid_, world_, verticals_, con_ostr))
00924   {
00925     vcl_cout << "Couldn't save constraints\n";
00926     return;
00927   }
00928 }
00929 
00930 // add polygon vertices as world points to enable correspondence for
00931 // additional camera constraints.
00932 void bmvv_cal_manager::add_poly_vertices_to_world_pts(vsol_polygon_3d_sptr const& poly)
00933 {
00934   unsigned nv = poly->size();
00935   vcl_vector<unsigned> vert_indices(nv);
00936   for (unsigned i = 0; i<nv; ++i)
00937   {
00938     vsol_point_3d_sptr v3d = poly->vertex(i);
00939     vgl_point_3d<double> p(v3d->x(), v3d->y(), v3d->z());
00940     world_.push_back(p);
00941     vert_indices[i]=world_.size()-1;
00942   }
00943   indexed_face_set_.push_back(vert_indices);
00944 }
00945 
00946 // Add the most recently created polygon to the world
00947 void bmvv_cal_manager::confirm_polygon()
00948 {
00949   if (!new_poly_)
00950     return;
00951   add_poly_vertices_to_world_pts(new_poly_);
00952   polys_.push_back(new_poly_);
00953   this->project_world();
00954 }
00955 
00956 void bmvv_cal_manager::pick_polygon()
00957 {
00958   vsol_polygon_2d_sptr poly;
00959   ptab_->pick_polygon(poly);
00960   new_poly_ = brct_algos::back_project(poly, cam_, height_);
00961   this->draw_vsol_polygon_3d(new_poly_, false, 1.0f, 0.0f, 1.0f);
00962   btab_->post_redraw();
00963 }
00964 
00965 void bmvv_cal_manager::draw_vsol_polygon_3d(