contrib/brl/vvid/vvid_live_video_manager.cxx
Go to the documentation of this file.
00001 // This is brl/vvid/vvid_live_video_manager.cxx
00002 #include "vvid_live_video_manager.h"
00003 //:
00004 // \file
00005 // \author J.L. Mundy
00006 
00007 #include <vcl_cstdlib.h> // for vcl_exit()
00008 #include <vcl_sstream.h>
00009 #include <vcl_vector.h>
00010 #include <vcl_iostream.h>
00011 #include <vul/vul_timer.h>
00012 #include <vul/vul_file.h>
00013 #include <vil1/vil1_memory_image_of.h>
00014 #include <vgui/vgui.h>
00015 #include <vgui/vgui_adaptor.h>
00016 #include <vgui/vgui_dialog.h>
00017 #include <vgui/vgui_viewer2D_tableau.h>
00018 #include <vgui/vgui_shell_tableau.h>
00019 #include <vgui/vgui_grid_tableau.h>
00020 #include <bgui/bgui_vtol2D_tableau.h>
00021 #include <vtol/vtol_face_2d.h>
00022 #include <vtol/vtol_edge_2d.h>
00023 #include <sdet/sdet_detector_params.h>
00024 #include <vvid/cmu_1394_camera_params.h>
00025 #include <vpro/vpro_video_process.h>
00026 #include <vpro/vpro_edge_process.h>
00027 #include <vpro/vpro_region_process.h>
00028 #include <vpro/vpro_capture_process.h>
00029 #include <bgui/bgui_histogram_tableau.h>
00030 
00031 //static live_video_manager instance
00032 vvid_live_video_manager *vvid_live_video_manager::instance_ = 0;
00033 
00034 
00035 vvid_live_video_manager *vvid_live_video_manager::instance()
00036 {
00037   if (!instance_)
00038   {
00039     instance_ = new vvid_live_video_manager();
00040     instance_->init();
00041   }
00042   return vvid_live_video_manager::instance_;
00043 }
00044 
00045 //-----------------------------------------------------------
00046 // constructors/destructor
00047 //
00048 vvid_live_video_manager::
00049 vvid_live_video_manager() :
00050   cp_(cmu_1394_camera_params()),
00051   histogram_(false),
00052   width_(960),
00053   height_(480),
00054   min_msec_per_frame_(1000.0/30.0),
00055   win_(0),
00056   video_process_(0),
00057   init_successful_(false)
00058 {}
00059 
00060 vvid_live_video_manager::~vvid_live_video_manager()
00061 {}
00062 //----------------------------------------------------------
00063 // determine the number of active cameras and install the reduced
00064 // resolution views accordingly.
00065 //
00066 void vvid_live_video_manager::init()
00067 {
00068   //Determine the number of active cameras
00069   // for now we assume use a pre-defined _N_views
00070   cmu_1394_camera cam;
00071   num_cameras_ = cam.GetNumberCameras();
00072   vcl_cout << "Number of Cameras Detected: " << num_cameras_ << vcl_endl;
00073   if (num_cameras_ <= 0) {
00074     vcl_cerr << "Exiting - no cameras detected\n";
00075     vcl_exit(0);
00076   }
00077 
00078   vgui_grid_tableau_sptr grid = vgui_grid_tableau_new(num_cameras_,2);
00079   grid->set_grid_size_changeable(true);
00080   sample_ = 1;
00081   init_successful_ = true;
00082   edges_ = true;
00083   vvid_live_video_tableau_sptr vtab;
00084   bgui_vtol2D_tableau_sptr vt2D;
00085 
00086   for (unsigned cam=0; cam<num_cameras_; ++cam)
00087   {
00088     vtab = vvid_live_video_tableau_new(cam, sample_, cmu_1394_camera_params());
00089     vtabs_.push_back(vtab);
00090     init_successful_ = init_successful_&&vtab->attach_live_video();
00091     if (!init_successful_)
00092     {
00093       vcl_cout << "In vvid_live_video_manager::init() -"
00094                << " bad initialization - camera #"<< cam << vcl_endl;
00095       return;
00096     }
00097     vt2D =  bgui_vtol2D_tableau_new(vtab);
00098     vt2Ds_.push_back(vt2D);
00099 
00100     // make a 2D viewer tableau and add it to the grid
00101     vgui_viewer2D_tableau_sptr v2d = vgui_viewer2D_tableau_new(vt2D);
00102     grid->add_at(v2d, cam, 0);
00103 
00104   // make a histogram
00105   bgui_histogram_tableau_new htab;
00106     htabs_.push_back(htab);
00107     vgui_viewer2D_tableau_new viewer(htab);
00108   grid->add_at(viewer, cam, 1);
00109   }
00110 
00111   // get the camera parameters from the last camera (assume are are the same)
00112   cp_ = vtab->get_camera_params();
00113 
00114   // put the grid in a shell
00115   vgui_shell_tableau_sptr shell = vgui_shell_tableau_new(grid);
00116   this->add_child(shell);
00117   video_process_  = (vpro_video_process*)0;
00118 }
00119 
00120 //: make an event handler
00121 // Note that we have to get an adaptor and set the tableau to receive events
00122 bool vvid_live_video_manager::handle(const vgui_event &e)
00123 {
00124   //nothing special here yet
00125   //just pass the event back to the base class
00126   return vgui_wrapper_tableau::handle(e);
00127 }
00128 //---------------------------------------------------------
00129 //:
00130 //  Cameras have different possible resolutions, frame rates and color
00131 //  sampling choices. This method sets up a vgui choice menu item
00132 //  based on the valid video configurations supported by the camera.
00133 //  (currently the rgb_ flag doesn't do anything but ultimately will
00134 //   control color/vs/mono acquisition if the camera supports it.)
00135 //  The pix_sample_interval determines the resolution of the display
00136 //
00137 void vvid_live_video_manager::set_camera_params()
00138 {
00139   vvid_live_video_tableau_sptr vtab = vtabs_.back();
00140   if (vtabs_.size() != num_cameras_ || !vtab)
00141   {
00142     vcl_cout << "in vvid_live_video_manager::set_camera_params() -"
00143              << " no live video tableau\n";
00144     return;
00145   }
00146   cp_ = vtab->get_camera_params();
00147   static int pix_sample_interval = 1;
00148   vcl_vector<vcl_string> choices;
00149   vcl_string no_choice="CurrentConfiguration";
00150   choices.push_back(no_choice);
00151   vcl_vector<vcl_string> valid_descrs = vtab->get_capability_descriptions();
00152   for (vcl_vector<vcl_string>::iterator cit = valid_descrs.begin();
00153        cit != valid_descrs.end(); cit++)
00154        choices.push_back(*cit);
00155   static int choice=0;
00156   static double max_frame_rate=30.0;
00157   //Set up the dialog.
00158   vgui_dialog cam_dlg("Camera Parameters");
00159   cam_dlg.message(vtab->current_capability_desc().c_str());
00160   cam_dlg.choice("Choose Configuration", choices, choice);
00161   cam_dlg.checkbox("Auto Exposure ", cp_.auto_exposure_);
00162   cam_dlg.checkbox("Auto Gain ", cp_.auto_gain_);
00163   cam_dlg.field("Shutter Speed", cp_.shutter_);
00164   cam_dlg.field("brightness",cp_.brightness_);
00165   cam_dlg.field("sharpness",cp_.sharpness_);
00166   cam_dlg.field("exposure",cp_.exposure_);
00167   cam_dlg.field("gain",cp_.gain_);
00168   cam_dlg.field("Display Sample Interval", pix_sample_interval);
00169   cam_dlg.field("Maximum Frame Rate", max_frame_rate);
00170   cam_dlg.checkbox("image capture(acquisition) ", cp_.capture_);
00171   cam_dlg.checkbox("RGB(monochrome) ", cp_.rgb_);
00172   cam_dlg.checkbox("Auto White Balance",cp_.autowhitebalance_);
00173   cam_dlg.field("White Balance U",cp_.whitebalanceU_);
00174   cam_dlg.field("White Balance V",cp_.whitebalanceV_);
00175   cam_dlg.checkbox(" One push WhiteBalance",cp_.onepushWBbalance_);
00176 
00177   if (!cam_dlg.ask())
00178     return;
00179 
00180   // set the results to all video tableaux
00181   for (unsigned i=0; i<num_cameras_; ++i) {
00182     if (choice)
00183       vtabs_[i]->set_current(choice-1);
00184     vtabs_[i]->set_pixel_sample_interval(pix_sample_interval);
00185     vtabs_[i]->set_camera_params(cp_);
00186   }
00187 
00188   min_msec_per_frame_ = 1000.0/max_frame_rate;
00189 
00190   vcl_cout << "Current Camera Parameters\n" << cp_ << '\n';
00191 }
00192 
00193 void vvid_live_video_manager::set_detection_params()
00194 {
00195   if (vtabs_.size() != num_cameras_)
00196   {
00197     vcl_cout << "in vvid_live_video_manager::set_camera_params() -"
00198              << " no live video tableau\n";
00199     return;
00200   }
00201   //cache the live video state to restore
00202   bool live = vtabs_.back()->get_video_live();
00203   if (live)
00204     this->stop_live_video();
00205   static bool agr = false;
00206   static sdet_detector_params dp;
00207   static float max_gap = 0;
00208   vgui_dialog det_dialog("Video Edges");
00209   det_dialog.field("Gaussian sigma", dp.smooth);
00210   det_dialog.field("Noise Threshold", dp.noise_multiplier);
00211   det_dialog.checkbox("Automatic Threshold", dp.automatic_threshold);
00212   det_dialog.checkbox("Aggressive Closure", agr);
00213   det_dialog.checkbox("Compute Junctions", dp.junctionp);
00214   det_dialog.checkbox("Edges vs Regions", edges_);
00215   if (!det_dialog.ask())
00216     return;
00217   if (agr)
00218     dp.aggressive_junction_closure=0;
00219   else
00220     dp.aggressive_junction_closure=-1;
00221   dp.maxGap = max_gap;
00222 
00223   if (edges_)
00224     video_process_  = new vpro_edge_process(dp);
00225   else
00226     video_process_  = new vpro_region_process(dp);
00227   sample_ = 2;
00228   if (live)
00229     this->start_live_video();
00230 }
00231 
00232 void vvid_live_video_manager::no_op()
00233 {
00234   video_process_ = 0;
00235 }
00236 
00237 void vvid_live_video_manager::capture_sequence()
00238 {
00239   this->stop_live_video();
00240   vgui_dialog save_video_dlg("Save Video Sequence");
00241   static vcl_string video_filename = "";
00242   static vcl_string ext = "*.*";
00243   save_video_dlg.file("Video Filename:", ext, video_filename);
00244   if (!save_video_dlg.ask())
00245     return;
00246   sample_ = 1;
00247   video_process_ = new vpro_capture_process(video_filename);
00248 }
00249 
00250 void vvid_live_video_manager::init_capture()
00251 {
00252   this->stop_live_video();
00253   vgui_dialog save_video_dlg("Init Capture");
00254   static vcl_string video_directory = vul_file::get_cwd();
00255   static vcl_string ext = "*.*";
00256   static bool auto_increment = true;
00257   static vcl_string dir_prefix = "video";
00258   static int dir_index = 0;
00259   save_video_dlg.file("Video Directory:", ext, video_directory);
00260   save_video_dlg.checkbox("Automatically Create Incremental Subdirectories", auto_increment);
00261   save_video_dlg.field("Directory Prefix", dir_prefix);
00262   save_video_dlg.field("Current Directory Index", dir_index);
00263   vcl_stringstream complete_path;
00264   complete_path << "Complete Path: " << video_directory << '/' << dir_prefix << dir_index;
00265   save_video_dlg.message(complete_path.str().c_str());
00266 
00267   if (!save_video_dlg.ask())
00268     return;
00269 
00270   // if not a directory, use the base directory
00271   if (!vul_file::is_directory(video_directory))
00272     video_directory = vul_file::dirname(video_directory);
00273 
00274   vcl_string video_filename = video_directory;
00275   if (auto_increment){
00276     vcl_stringstream auto_dir;
00277     auto_dir << '/' << dir_prefix << dir_index++;
00278     video_filename += auto_dir.str();
00279     vul_file::make_directory(video_filename);
00280   }
00281 
00282   for (unsigned i=0; i<num_cameras_; ++i)
00283   {
00284     vcl_stringstream camera_subdir;
00285     camera_subdir << "/camera" << i << '/';
00286     vul_file::make_directory(video_filename+camera_subdir.str());
00287     vtabs_[i]->start_capture(video_filename+camera_subdir.str());
00288   }
00289 }
00290 
00291 void vvid_live_video_manager::stop_capture()
00292 {
00293   this->stop_live_video();
00294   for (unsigned i=0; i<num_cameras_; ++i)
00295     vtabs_[i]->stop_capture();
00296 }
00297 
00298 void vvid_live_video_manager::toggle_histogram()
00299 {
00300   if (histogram_) {
00301     histogram_ = false;
00302     for (unsigned i=0; i<num_cameras_; ++i)
00303       htabs_[i]->clear();
00304   }
00305   else
00306     histogram_ = true;
00307 }
00308 
00309 void vvid_live_video_manager::display_topology()
00310 {
00311   for (unsigned i=0; i<num_cameras_; ++i)
00312   {
00313     vt2Ds_[i]->clear_all();
00314     vcl_vector<vtol_topology_object_sptr> const & seg = video_process_->get_output_topology();
00315 
00316     for (vcl_vector<vtol_topology_object_sptr>::const_iterator ti=seg.begin();
00317          ti != seg.end(); ti++)
00318     {
00319       if (edges_)
00320       {
00321         vtol_edge_2d_sptr e=(*ti)->cast_to_edge()->cast_to_edge_2d();
00322         if (e)
00323           vt2Ds_[i]->add_edge(e);
00324       }
00325       else
00326       {
00327         vtol_face_2d_sptr f=(*ti)->cast_to_face()->cast_to_face_2d();
00328         if (f)
00329           vt2Ds_[i]->add_face(f);
00330       }
00331     }
00332   }
00333 }
00334 
00335 void vvid_live_video_manager::display_image()
00336 {
00337   //do nothing for now
00338 }
00339 
00340 void vvid_live_video_manager::run_frames()
00341 {
00342   if (!init_successful_)
00343     return;
00344   while (vtabs_.back()->get_video_live()) {
00345     vul_timer t;
00346     for (unsigned i=0; i<num_cameras_; ++i)
00347     {
00348       vtabs_[i]->update_frame();
00349 
00350       if (histogram_)
00351         htabs_[i]->update(vtabs_[i]->get_rgb_frame());
00352 
00353       if (!cp_.rgb_&&video_process_)//i.e. grey scale
00354       {
00355         vil1_memory_image_of<unsigned char> image;
00356         video_process_->clear_input();
00357 
00358         if (vtabs_[i]->get_current_mono_image(sample_,image))
00359           video_process_->add_input_image(image);
00360         else return;
00361         if (video_process_->execute())
00362         {
00363           if (video_process_->get_output_type()==vpro_video_process::IMAGE)
00364             display_image();
00365           if (video_process_->get_output_type()==vpro_video_process::TOPOLOGY)
00366             display_topology();
00367         }
00368       }
00369       vt2Ds_[i]->post_redraw();
00370     }
00371     vgui::run_till_idle();
00372     // delay until the minimum time has passed for this frame
00373     while (t.real()<min_msec_per_frame_) ;
00374     float ft = float(t.real())/1000.f, rate=1e33f;
00375     if (ft!=0.f) rate = 1.0f/ft;
00376     vgui::out << "Tf = " << ft << " sec/frame  = " << rate << " frs/sec\n";
00377   }
00378 }
00379 
00380 void vvid_live_video_manager::start_live_video()
00381 {
00382   if (!init_successful_ || vtabs_.size() != num_cameras_)
00383     return;
00384 
00385   for (unsigned i=0; i<num_cameras_; ++i)
00386     if (!vtabs_[i]->start_live_video())
00387     {
00388       vcl_cout << "In vvid_live_video_manager::start_live_video() -"
00389                << " start failed - camera #" << i << vcl_endl;
00390       return;
00391     }
00392   this->run_frames();
00393 }
00394 
00395 void vvid_live_video_manager::stop_live_video()
00396 {
00397   if (!init_successful_)
00398     return;
00399 
00400   for (unsigned i=0; i<num_cameras_; ++i)
00401     if (vtabs_[i])
00402       vtabs_[i]->stop_live_video();
00403   if (video_process_)
00404     video_process_->finish();
00405 }
00406 
00407 void vvid_live_video_manager::quit()
00408 {
00409   this->stop_live_video();
00410   vcl_exit(1);
00411 }
00412 
00413 bool vvid_live_video_manager::
00414 get_current_rgb_image(unsigned camera_index,
00415                       int pix_sample_interval,
00416                       vil1_memory_image_of< vil1_rgb<unsigned char> >& im)
00417 {
00418   if (!init_successful_||!vtabs_[camera_index])
00419   {
00420     vcl_cout << "In vvid_live_video_manger::get_current_rgb_imge(..) -"
00421              << " bad initialization\n";
00422     return false;
00423   }
00424 
00425   return vtabs_[camera_index]->get_current_rgb_image(pix_sample_interval, im);
00426 }
00427 
00428 bool vvid_live_video_manager::
00429 get_current_mono_image(unsigned camera_index,
00430                        int pix_sample_interval,
00431                        vil1_memory_image_of<unsigned char>& im)
00432 {
00433   if (!init_successful_||!vtabs_[camera_index])
00434   {
00435     vcl_cout << "In vvid_live_video_manger::get_current_mono_imge(..) -"
00436              << " bad initialization\n";
00437     return false;
00438   }
00439 
00440   return vtabs_[camera_index]->get_current_mono_image(pix_sample_interval, im);
00441 }
00442 
00443 void vvid_live_video_manager::
00444 set_process_rgb_image(vil1_memory_image_of< vil1_rgb<unsigned char> >& im)
00445 {
00446   process_rgb_ = im;
00447 }
00448 
00449 void vvid_live_video_manager::
00450 set_process_mono_image(vil1_memory_image_of<unsigned char>& im)
00451 {
00452   process_mono_ = im;
00453 }