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

vsrl_manager.cxx

Go to the documentation of this file.
00001 #include "vsrl_manager.h"
00002 //:
00003 // \file
00004 // \brief This program was written to test the Dense Matching software
00005 // \author
00006 // G.W. Brooksby
00007 // \date 02/13/03
00008 
00009 #include <vcl_cstdlib.h>
00010 #include <vcl_cmath.h>
00011 #include <vcl_iostream.h>
00012 #include <vil1/vil1_load.h>
00013 #include <vil1/vil1_scale_intensities.h>
00014 #include <vil1/vil1_save.h>
00015 #include <vnl/vnl_double_2.h>
00016 #include <vgui/vgui.h>
00017 #include <vgui/vgui_dialog.h>
00018 #include <vgui/vgui_image_tableau.h>
00019 #include <vgui/vgui_viewer2D_tableau.h>
00020 #include <vgui/vgui_easy2D_tableau.h>
00021 #include <vgui/vgui_soview2D.h>
00022 #include <vgui/vgui_grid_tableau.h>
00023 #include <vgui/vgui_shell_tableau.h>
00024 #include <vsrl/vsrl_stereo_dense_matcher.h>
00025 #include <sdet/sdet_region_proc_params.h>
00026 #include <sdet/sdet_region_proc.h>
00027 #include <vdgl/vdgl_digital_curve.h>
00028 #include <vdgl/vdgl_interpolator.h>
00029 #include <vdgl/vdgl_edgel_chain.h>
00030 #include <vtol/vtol_vertex_2d.h>
00031 #include <vtol/vtol_vertex_2d_sptr.h>
00032 #include <vtol/vtol_vertex.h>
00033 #include <vtol/vtol_edge_2d.h>
00034 #include <vtol/vtol_edge_2d_sptr.h>
00035 #include <vtol/vtol_intensity_face.h>
00036 #include <vepl/vepl_gradient_mag.h>
00037 #include <vepl/vepl_gaussian_convolution.h>
00038 #include <vepl/vepl_threshold.h>
00039 #include <vsrl/vsrl_point_picker.h>
00040 #include <vsrl/vsrl_results_dense_matcher.h>
00041 #include <vsrl/vsrl_3d_output.h>
00042 #include <vsrl/vsrl_region_disparity.h>
00043 #include <vsrl/vsrl_image_correlation.h>
00044 #include <vgel/vgel_multi_view_data.h>
00045 #include <vgel/vgel_multi_view_data_vertex_sptr.h>
00046 #include <vgel/vgel_kl.h>
00047 #include <vgl/vgl_point_3d.h>
00048 #include <rsdl/rsdl_point.h>
00049 #include <rsdl/rsdl_kd_tree.h>
00050 #if 0
00051 #ifdef INCLUDE_JSEG
00052 extern "C"
00053 {
00054 #include <jseg/jseg.h>
00055 }
00056 #endif
00057 #endif
00058 // static manager instance
00059 vsrl_manager* vsrl_manager::instance_=0;
00060 
00061 //ensure only one instance is created
00062 vsrl_manager *vsrl_manager::instance()
00063 {
00064   if (!instance_)
00065   {
00066     instance_ = new vsrl_manager();
00067     instance_->init();
00068   }
00069   return vsrl_manager::instance_;
00070 }
00071 
00072 vsrl_manager::vsrl_manager():vgui_wrapper_tableau(){}
00073 
00074 vsrl_manager::~vsrl_manager(){}
00075 
00076 void vsrl_manager::init()
00077 {
00078   shadow_mean_ = 50.0;
00079   shadows_only_ = true;
00080   shadow_metric_ = NULL;
00081   // Load the image tableaux
00082   itabL_ = vgui_image_tableau_new();
00083   itabR_ = vgui_image_tableau_new();
00084   dimg_tab_ = vgui_image_tableau_new();  // disparity image tableau
00085   disparity_bias_=0;
00086 
00087   // Put the image tableaux into an easy2D tableau
00088   e2d0_ = vgui_easy2D_tableau_new(itabL_);
00089   e2d1_ = vgui_easy2D_tableau_new(itabR_);
00090   e2d2_ = vgui_easy2D_tableau_new(dimg_tab_);
00091 
00092   // Set up characteristics of points to be drawn
00093   e2d0_->set_foreground(1,0,0);
00094   e2d1_->set_foreground(1,0,0);
00095   e2d2_->set_foreground(1,0,0);
00096   e2d0_->set_point_radius(5);
00097   e2d1_->set_point_radius(5);
00098   e2d2_->set_point_radius(5);
00099   e2d0_->set_line_width(2);
00100   e2d1_->set_line_width(2);
00101   e2d2_->set_line_width(2);
00102 
00103   // Put the easy2D tableaux into the viewers
00104   vgui_viewer2D_tableau_sptr viewer0 = vgui_viewer2D_tableau_new(e2d0_);
00105   vgui_viewer2D_tableau_sptr viewer1 = vgui_viewer2D_tableau_new(e2d1_);
00106   vgui_viewer2D_tableau_sptr viewer2 = vgui_viewer2D_tableau_new(e2d2_);
00107 
00108   // Put the viewers into tableaux for picking points
00109   vpicker0_=new vsrl_point_picker(viewer0);
00110   vpicker1_=new vsrl_point_picker(viewer1);
00111   vpicker2_=new vsrl_point_picker(viewer2);
00112 
00113   //Put the viewers into a grid
00114   grid_ = new vgui_grid_tableau(3,1);
00115   grid_->add_at(vpicker0_, 0,0);
00116   grid_->add_at(vpicker1_, 1,0);
00117   grid_->add_at(vpicker2_, 2,0);
00118   grid_->set_selected(0,0);
00119   grid_->set_uses_paging_events(false); // disable paging
00120   grid_->set_grid_size_changeable(false); // disable adding panes
00121 
00122   // Put the grid into a shell tableau at the top the hierarchy
00123   vgui_shell_tableau_new shell(grid_);
00124 
00125   // Get a parameters object
00126   params_ = vsrl_parameters::instance();
00127 
00128   this->add_child(shell);
00129 }
00130 
00131 void vsrl_manager::quit()
00132 {
00133   vcl_exit(1);
00134 }
00135 
00136 void vsrl_manager::load_left_image()
00137 {
00138   vgui_dialog load_image_dlg("Load Image file");
00139   static vcl_string image_filename = "";
00140   static vcl_string ext = "*.*";
00141   load_image_dlg.file("Image Filename:", ext, image_filename);
00142   if (!load_image_dlg.ask()) return;
00143   imgL_ = vil1_load(image_filename.c_str());
00144   itabL_->set_image(imgL_);
00145   this->post_redraw();
00146   return;
00147 }
00148 
00149 void vsrl_manager::load_right_image()
00150 {
00151   vgui_dialog load_image_dlg("Load Image file");
00152   static vcl_string image_filename = "";
00153   static vcl_string ext = "*.*";
00154   load_image_dlg.file("Image Filename:", ext, image_filename);
00155   if (!load_image_dlg.ask()) return;
00156   imgR_ = vil1_load(image_filename.c_str());
00157   itabR_->set_image(imgR_);
00158   this->post_redraw();
00159   return;
00160 }
00161 
00162 void vsrl_manager::load_disparity_image()
00163 {
00164   vgui_dialog load_image_dlg("Load Disparity Image file");
00165   static vcl_string image_filename = "";
00166   static vcl_string ext = "*.*";
00167   load_image_dlg.file("Disparity Image Filename:", ext, image_filename);
00168   if (!load_image_dlg.ask()) return;
00169   disp_img_ = vil1_load(image_filename.c_str());
00170   vil1_memory_image_of<unsigned char> real_image(disp_img_);
00171 
00172   vil1_image scaled_image = scale_image(real_image);
00173 
00174   // Display the scaled image
00175   dimg_tab_->set_image(scaled_image);
00176   this->post_redraw();
00177 }
00178 
00179 void vsrl_manager::save_disparity_image()
00180 {
00181   vgui_dialog save_image_dlg("Save Disparity Image file");
00182   static vcl_string image_filename = "";
00183   static vcl_string ext = "*.tif";
00184   save_image_dlg.file("Disparity Image Filename", ext, image_filename);
00185   if (!save_image_dlg.ask()) return;
00186   vil1_memory_image_of<unsigned char> disp(disp_img_);
00187   if (!vil1_save(disp,image_filename.c_str())) {
00188     vcl_cout << "Error saving disparity image!\n";
00189   }
00190   return;
00191 }
00192 
00193 void vsrl_manager::load_params_file()
00194 {
00195   //
00196   vgui_dialog load_params_dlg("Load Dense Matcher Parameters file");
00197   static vcl_string params_filename = "";
00198   static vcl_string ext = "*.*";
00199   load_params_dlg.file("Dense Matcher Parameter Filename:", ext, params_filename);
00200   if (!load_params_dlg.ask()) return;
00201 
00202   // Due to the need for a non-const char* being fed to the .load function
00203   // we have to construct a filename that is NOT const!
00204   char* filename = new char[params_filename.length()+1]; // get a new char* array
00205   params_filename.copy(filename,params_filename.length()); // copy the string into it
00206   filename[params_filename.length()]=0; //add null terminator
00207   params_->load(filename); // load the parameters file
00208   disparity_bias_ = params_->correlation_range;
00209   delete [] filename;  // delete the filename
00210 }
00211 
00212 void vsrl_manager::point_pick()
00213 {
00214   vcl_cerr << "vsrl_manager::point_pick() not yet implemented\n";
00215   return;
00216 }
00217 
00218 void vsrl_manager::clear_all()
00219 {
00220   e2d0_->clear();
00221   e2d1_->clear();
00222   e2d2_->clear();
00223   this->post_redraw();
00224   return;
00225 }
00226 
00227 bool vsrl_manager::handle(vgui_event const & event)
00228 {
00229   this->child.handle(event);
00230 
00231   if (event.type == vgui_BUTTON_DOWN &&
00232       event.button == vgui_LEFT &&
00233       !event.modifier)
00234     {
00235       put_points();
00236     }
00237   else if (event.type == vgui_BUTTON_DOWN &&
00238            event.button == vgui_LEFT &&
00239            event.modifier == vgui_SHIFT)
00240     {
00241       put_lines();
00242     }
00243   else if (event.type == vgui_BUTTON_DOWN &&
00244            event.button == vgui_MIDDLE &&
00245            event.modifier == vgui_SHIFT)
00246     {
00247       vgl_point_2d<float>  pos = vpicker0_->get_point();  // get the last point picked
00248       vcl_cout << "handle: pos = " << pos << vcl_endl;
00249       int x = int(pos.x()); int y = int(pos.y()); // convert to int.
00250       show_correlations(x,y);
00251     }
00252   return true;
00253 }
00254 
00255 bool vsrl_manager::validate_point(vgl_point_2d<float> const& pt)
00256 {
00257   if (pt.x() < 0 ||
00258       pt.y() < 0 ||
00259       pt.x() >= disp_img_.cols() ||
00260       pt.y() >= disp_img_.rows() )
00261     {
00262       vcl_cout << "Error: point out of range of disparity image.\n";
00263       return false;
00264     }
00265   else
00266     return true;
00267 }
00268 
00269 int vsrl_manager::get_disparity(vgl_point_2d<float> const& pt)
00270 {
00271   vil1_memory_image_of<unsigned char> disp(disp_img_);
00272   int pixel_val = disp(int(pt.x()),int(pt.y()));
00273   if (pixel_val > 0) {
00274     // we subtract the disparity bias, plus 1 for the indexing offset
00275     //    pixel_val -= (disparity_bias_ + 1);
00276     pixel_val -= (params_->correlation_range + 1);
00277     vcl_cout << "Disparity: " << pixel_val << vcl_endl;
00278   }
00279   return pixel_val;
00280 }
00281 
00282 bool vsrl_manager::put_points()
00283 {
00284   unsigned r=0, c=0;
00285   grid_->get_last_selected_position(&c, &r);
00286 
00287   // determine which grids to update
00288   vgl_point_2d<float> pos;
00289   // Point Picked in Left Pane
00290   if (c==0)
00291   {
00292     pos = vpicker0_->get_point();  // get the last point picked
00293     vcl_cout << "put_points: pos = " << pos << vcl_endl;
00294     if (!validate_point(pos)) return true;
00295     int disp = get_disparity(pos);
00296     vpicker1_->put_point(pos.x()+disp,pos.y());
00297     vpicker2_->put_point(pos.x(),     pos.y());
00298   }
00299   // Point Picked in Right Pane
00300   if (c==1)
00301   {
00302     pos = vpicker1_->get_point();  // get the last point picked
00303     if (!validate_point(pos)) return true;
00304     int disp = get_disparity(pos);
00305     vpicker0_->put_point(pos.x()-disp,pos.y());
00306     vpicker2_->put_point(pos.x(),     pos.y());
00307   }
00308   // Point Picked in Disparity Pane
00309   if (c==2)
00310   {
00311     pos = vpicker2_->get_point();  // get the last point picked
00312     if (!validate_point(pos)) return true;
00313     int disp = get_disparity(pos);
00314     vpicker0_->put_point(pos.x(),     pos.y());
00315     vpicker1_->put_point(pos.x()+disp,pos.y());
00316   }
00317   this->post_redraw();
00318   return true;
00319 }
00320 
00321 bool vsrl_manager::put_lines()
00322 {
00323   unsigned r=0, c=0;
00324   grid_->get_last_selected_position(&c, &r);
00325 
00326   // determine which grids to update
00327   vgl_point_2d<float> pos;
00328   // Point Picked in Left Pane
00329   if (c==0)
00330   {
00331     pos = vpicker0_->get_point();  // get the last point picked
00332     vpicker1_->put_H_line(pos.x(),pos.y());
00333     vpicker2_->put_H_line(pos.x(),pos.y());
00334   }
00335   // Point Picked in Right Pane
00336   if (c==1)
00337   {
00338     pos = vpicker1_->get_point();  // get the last point picked
00339     vpicker0_->put_H_line(pos.x(),pos.y());
00340     vpicker2_->put_H_line(pos.x(),pos.y());
00341   }
00342   // Point Picked in Disparity Pane
00343   if (c==2)
00344   {
00345     pos = vpicker2_->get_point();  // get the last point picked
00346     vpicker0_->put_H_line(pos.x(),pos.y());
00347     vpicker1_->put_H_line(pos.x(),pos.y());
00348   }
00349   this->post_redraw();
00350   return true;
00351 }
00352 
00353 bool vsrl_manager::do_dense_matching()
00354 {
00355   if (!imgL_ || !imgR_) return false;
00356 
00357   static float sig = 1.0f;
00358   static float cutoff = 0.01f;
00359   static bool smoothing = false;
00360   vgui_dialog gs_dialog("Gaussian Smoothing");
00361   gs_dialog.field("Sigma:",sig);
00362   gs_dialog.field("Cutoff:",cutoff);
00363   gs_dialog.checkbox("Perform Gaussian Smoothing",smoothing);
00364   if (!gs_dialog.ask()) return false;
00365 
00366   // If desired, we can do Gaussian smoothing.  This can be handy for
00367   // badly interlaced images.
00368   if (smoothing) {
00369     vil1_image left = vepl_gaussian_convolution(imgL_,sig,cutoff);
00370     vil1_image right = vepl_gaussian_convolution(imgR_,sig,cutoff);
00371     imgL_=left;
00372     imgR_=right;
00373   }
00374 
00375   itabL_->set_image(imgL_);
00376   itabR_->set_image(imgR_);
00377 
00378   // The parameters used will be the default parameters or
00379   // the parameters loaded manually from a file.
00380   // Now create a dense matcher with the images that are loaded.
00381   vcl_cout << "Begin Stereo Dense Matcher...";
00382   vsrl_stereo_dense_matcher matcher(imgL_,imgR_);
00383   vcl_cout << "Setting Correlation Range...";
00384   matcher.set_correlation_range(params_->correlation_range);
00385   vcl_cout << "Running Dense Matcher.\n";
00386   // Run the dense matcher.
00387   matcher.execute();
00388 
00389   // Get & display the disparity image
00390   // Get a buffer the size of the left image
00391   vil1_memory_image_of<unsigned char> buffer(imgL_.cols(),imgL_.rows());
00392   // Zero out the buffer
00393   for (int x=0;x<buffer.width();x++)
00394     for (int y=0;y<buffer.height();y++)
00395       buffer(x,y)=0;
00396   // Get the disparities into the buffer
00397   for (int y=0;y<buffer.height();y++) {
00398     for (int x=0;x<buffer.width();x++) {
00399       int disparity = matcher.get_disparity(x,y);
00400       int value = disparity + params_->correlation_range+1;
00401       if (value < 0)
00402         value = 0;
00403       if (value>2*params_->correlation_range+1)
00404         value=0;
00405       buffer(x,y)=value;
00406     }
00407   }
00408 
00409   // Display the disparity image
00410   disp_img_ = buffer;
00411   vil1_image scaled_image = scale_image(buffer);
00412   dimg_tab_->set_image(scaled_image);
00413 
00414   vcl_cout << "Dense Matcher complete.\n";
00415   this->post_redraw();
00416   return true;
00417 }
00418 
00419 vil1_image vsrl_manager::scale_image(vil1_memory_image_of<unsigned char> img)
00420 {
00421   double maxval = 0;
00422   double minval = 1e15;
00423   for (int x=0;x<img.width();x++) {
00424     for (int y=0;y<img.height();y++) {
00425       if (img(x,y) > maxval) {
00426         maxval = img(x,y);
00427       }
00428       if (img(x,y) < minval) {
00429         minval = img(x,y);
00430       }
00431     }
00432   }
00433   vcl_cout << "vsrl_manager::scale_image<unsigned char> - Max = " << maxval
00434            << ", Min = " << minval << vcl_endl;
00435 
00436   double scale = 255.0/maxval;
00437   double shift = 0;
00438   vil1_image scaled_image = vil1_scale_intensities(img, scale, shift);
00439   return scaled_image;
00440 }
00441 
00442 vil1_image vsrl_manager::scale_image(vil1_memory_image_of<double> img)
00443 {
00444   double maxval = 0;
00445   double minval = 1e15;
00446   for (int x=0;x<img.width();x++) {
00447     for (int y=0;y<img.height();y++) {
00448       if (img(x,y) > maxval) {
00449         maxval = img(x,y);
00450       }
00451       if (img(x,y) < minval) {
00452         minval = img(x,y);
00453       }
00454     }
00455   }
00456   vcl_cout << "vsrl_manager::scale_image<double> - Max = " << maxval
00457            << ", Min = " << minval << vcl_endl;
00458 
00459   double scale = 255.0/maxval;
00460   double shift = 0;
00461   vil1_image scaled_image = vil1_scale_intensities(img, scale, shift);
00462   return scaled_image;
00463 }
00464 
00465 void vsrl_manager::find_regions()
00466 {
00467   this->clear_all();
00468   static bool debug = false;
00469   static bool agr = true;
00470   static bool residual = false;
00471   static sdet_detector_params dp;
00472   vgui_dialog region_dialog("Edgel Regions");
00473   region_dialog.field("Gaussian sigma", dp.smooth);
00474   region_dialog.field("Noise Threshold", dp.noise_multiplier);
00475   region_dialog.checkbox("Automatic Threshold", dp.automatic_threshold);
00476   region_dialog.checkbox("Agressive Closure", agr);
00477   region_dialog.checkbox("Compute Junctions", dp.junctionp);
00478   region_dialog.checkbox("Debug", debug);
00479   region_dialog.checkbox("Residual Image", residual);
00480   region_dialog.field("Shadow Mean Intensity Threshold", shadow_mean_);
00481   region_dialog.checkbox("Display Only Shadow Regions", shadows_only_);
00482   if (!region_dialog.ask())
00483     return;
00484   if (agr)
00485     dp.aggressive_junction_closure=1;
00486   else
00487     dp.aggressive_junction_closure=0;
00488 
00489   sdet_region_proc_params rpp(dp, true, debug, 2);
00490   sdet_region_proc rp(rpp);
00491   rp.set_image(imgL_);
00492   rp.extract_regions();
00493   if (debug)
00494   {
00495     vil1_image ed_img = rp.get_edge_image();
00496     vgui_image_tableau_sptr itab =  e2d0_->get_image_tableau();
00497     if (!itab)
00498     {
00499       vcl_cout << "In segv_segmentation_manager::regions() - null image tableau\n";
00500       return;
00501     }
00502     itab->set_image(ed_img);
00503   }
00504   if (!debug)
00505   {
00506     vcl_vector<vtol_intensity_face_sptr>& regions = rp.get_regions();
00507     this->find_shadows(regions);
00508     this->draw_regions(regions, true);
00509   }
00510   if (residual)
00511   {
00512     vil1_image res_img = rp.get_residual_image();
00513     vgui_image_tableau_sptr itab =  e2d0_->get_image_tableau();
00514     if (!itab)
00515     {
00516       vcl_cout << "In segv_segmentation_manager::regions() - null image tableau\n";
00517       return;
00518     }
00519     itab->set_image(res_img);
00520   }
00521 }
00522 
00523 void vsrl_manager::draw_regions(vcl_vector<vtol_intensity_face_sptr>& regions,
00524                                 bool verts)
00525 {
00526   // This segment of code is ripped from various places in brl...bgui.
00527 
00528   for (vcl_vector<vtol_intensity_face_sptr>::iterator rit = regions.begin();
00529        rit != regions.end(); rit++)
00530   {
00531     vtol_face_2d_sptr f = (*rit)->cast_to_face_2d();
00532     edge_list edges; f->edges(edges);
00533 
00534     vgui_soview2D_group* vsovg = new vgui_soview2D_group();
00535 
00536     for (edge_list::iterator eit = edges.begin(); eit != edges.end(); eit++)
00537     {
00538       vtol_edge_2d_sptr e = (*eit)->cast_to_edge_2d();
00539 
00540       vgui_soview2D_linestrip* e_line = new vgui_soview2D_linestrip();
00541 
00542       vsol_curve_2d_sptr c = e->curve();
00543 
00544       if (!c) {
00545         vcl_cout << "vsrl_manager::draw_regions - null curve.\n";
00546         return;
00547       }
00548       if (c->cast_to_vdgl_digital_curve())
00549       {
00550         vdgl_digital_curve_sptr dc = c->cast_to_vdgl_digital_curve();
00551         //get the edgel chain
00552         vdgl_interpolator_sptr itrp = dc->get_interpolator();
00553         vdgl_edgel_chain_sptr ech = itrp->get_edgel_chain();
00554 
00555         //n, x, and y are in the parent class vgui_soview2D_linestrip
00556         e_line->n = ech->size();
00557         //offset the coordinates for display (may not be needed)
00558         e_line->x = new float[e_line->n], e_line->y = new float[e_line->n];
00559         for (unsigned int i=0; i<e_line->n;i++)
00560         {
00561           vdgl_edgel ed = (*ech)[i];
00562           e_line->x[i]=ed.get_x();
00563           e_line->y[i]=ed.get_y();
00564         }
00565       }
00566       else
00567         vcl_cout << "vsrl_manager::draw_regions - attempt to draw an edge with unknown curve geometry\n";
00568 
00569       vsovg->ls.push_back(e_line);
00570     }
00571 
00572     e2d0_->add(vsovg);
00573 
00574     if (verts)
00575     {
00576       vertex_list vts; f->vertices(vts);
00577       for (vcl_vector<vtol_vertex_sptr>::iterator vit = vts.begin();
00578            vit != vts.end(); vit++)
00579       {
00580         vtol_vertex_2d_sptr v = (*vit)->cast_to_vertex_2d();
00581         e2d0_->add_point(v->x(),v->y());
00582       }
00583     }
00584   }
00585 }
00586 
00587 void
00588 vsrl_manager::set_params()
00589 {
00590   // establish the variables.  Should already have instantiated params_
00591   int corr_range=params_->correlation_range;
00592   double inner_cost=params_->inner_cost;
00593   double outer_cost=params_->outer_cost;
00594   double continuity_cost=params_->continuity_cost;
00595   int correlation_window_width=params_->correlation_window_width;
00596   int correlation_window_height=params_->correlation_window_height;
00597   double bias_cost=params_->bias_cost;
00598   double common_intensity_diff=params_->common_intensity_diff;
00599 
00600   vgui_dialog params_dialog("Dense Matcher Parameters");
00601   params_dialog.field("Correlation Range:", corr_range);
00602   params_dialog.field("Inner Cost:", inner_cost);
00603   params_dialog.field("Outer Cost:", outer_cost);
00604   params_dialog.field("Continuity Cost:",continuity_cost);
00605   params_dialog.field("Correlation Window Width:", correlation_window_width);
00606   params_dialog.field("Correlation Window Height:", correlation_window_height);
00607   params_dialog.field("Bias Cost:",bias_cost);
00608   params_dialog.field("Common Intensity Difference:",common_intensity_diff);
00609   if (!params_dialog.ask()) {
00610     return;
00611   }
00612   else {
00613     params_->correlation_range = corr_range;
00614     params_->inner_cost = inner_cost;
00615     params_->outer_cost = outer_cost;
00616     params_->continuity_cost = continuity_cost;
00617     params_->correlation_window_width = correlation_window_width;
00618     params_->correlation_window_height = correlation_window_height;
00619     params_->bias_cost = bias_cost;
00620     params_->common_intensity_diff = common_intensity_diff;
00621   }
00622   return;
00623 }
00624 
00625 void vsrl_manager::draw_north_arrow()
00626 {
00627   // use a vector of length 10 for the north arrow
00628   north_.set(0.0,10.0);
00629 
00630   // (0,0) is the origin for the north vector
00631   /* vgui_soview2D_lineseg* line = */ draw_vector_at(&north_, 0.0f, 0.0f, 0.0);
00632 
00633   this->post_redraw();
00634   return;
00635 }
00636 
00637 //
00638 // Draw the given vector at the specified point with the specified rotation.
00639 // (x,y) = where to draw the vector
00640 // theta = the angle through which the vector is rotated before drawing.
00641 //
00642 vgui_soview2D_lineseg*
00643 vsrl_manager::draw_vector_at(vgl_vector_2d<float>* vec, float x, float y, float theta)
00644 {
00645   // make the vector green
00646   e2d0_->set_foreground(0,1,0);
00647 
00648   // Apply rotation to get rot_vec
00649   vgl_vector_2d<float> rot_vec;
00650   rot_vec.x_ =  vec->x() * vcl_cos(theta) + vec->y() * vcl_sin(theta);
00651   rot_vec.y_ = -vec->x() * vcl_sin(theta) + vec->y() * vcl_cos(theta);
00652 
00653   // Apply translation
00654   float endx = rot_vec.x()+x;
00655   float endy = rot_vec.y()+y;
00656 
00657   // Create the lineseg & draw it
00658   vgui_soview2D_lineseg* vector = new vgui_soview2D_lineseg(x,y,endx,endy);
00659   e2d0_->add(vector);
00660 
00661   e2d0_->set_foreground(1,0,0);
00662   this->post_redraw();
00663   return vector;
00664 }
00665 
00666 // Calculate & Display Image Gradient magnitudes
00667 //
00668 vil1_image
00669 vsrl_manager::show_gradient_mag(vil1_image* im_in)
00670 {
00671   vil1_image im_out = vepl_gradient_mag(*im_in);
00672   disp_img_ = im_out;  // this line lets us save out the image
00673   //  vil1_image scaled_image = scale_image(im_out);
00674   dimg_tab_->set_image(im_out);
00675   this->post_redraw();
00676   return im_out;
00677 }
00678 
00679 // Calculate & Display Image Gradient directions
00680 //
00681 vil1_image
00682 vsrl_manager::show_gradient_dir(vil1_memory_image_of<double> im_in)
00683 {
00684   // calculate the gradient
00685   // I prefer to implement my own gradient operation because I want to handle the edges
00686   // more carefully and I want better control of what happens at inflection points of ATAN2.
00687   // The scale (40) and offset (128) keep the range of the ATAN2 function within the range of
00688   // the <unsigned char> image.
00689   vcl_cout << "vsrl_manager::show_gradient_dir() - Begin\n";
00690 
00691   vil1_memory_image_of<double> im_out(im_in.width(),im_in.height());
00692 
00693   const double shift=128;
00694   const double scale=40; // actually: 127/pi
00695   register double dx, dy;
00696   for (int x=0; x<im_out.width(); x++) {
00697     for (int y=0; y<im_out.height(); y++) {
00698       if (x==0) {
00699         dx = im_in(x+1,y) - im_in(x,y); // image edge
00700       }
00701       else {
00702         dx = im_in(x,y) - im_in(x-1,y);
00703       }
00704       if (y==0) {
00705         dy = im_in(x,y+1) - im_in(x,y); // image edge
00706       }
00707       else {
00708         dy = im_in(x,y) - im_in(x,y-1);
00709       }
00710       im_out(x,y) = vcl_atan2(dy,dx) * scale + shift;
00711     }
00712   }
00713 
00714   vil1_image scaled_image = scale_image(im_out);
00715   dimg_tab_->set_image(scaled_image);
00716   this->post_redraw();
00717   vcl_cout << "vsrl_manager::show_gradient_dir() - End\n";
00718   return im_out;
00719 }
00720 
00721 // Generic function called by menu to make testing easier
00722 void
00723 vsrl_manager::test_left_func()
00724 {
00725   this->occlusion_map();
00726   this->post_redraw();
00727   return;
00728 }
00729 
00730 // Generic function called by menu to make testing easier
00731 void
00732 vsrl_manager::test_right_func()
00733 {
00734   // get the regions from jseg algorithm
00735   //  vcl_vector<vdgl_digital_region*> regions = run_jseg(imgR_);
00736   //  find_shadows(regions);
00737   //  this->post_redraw();
00738   this->region_disparity();
00739   return;
00740 }
00741 
00742 // Generate 3D output & display range image
00743 vil1_memory_image_of<double>
00744 vsrl_manager::make_3d()
00745 {
00746   // set up the dense matcher
00747   if (!disp_img_ || !imgL_ || !imgR_) {
00748     vil1_memory_image_of<double> null_image;
00749     return null_image; // Sanity check.
00750   }
00751   vsrl_results_dense_matcher matcher(imgL_,disp_img_);
00752   matcher.set_correlation_range(params_->correlation_range);
00753   vsrl_3d_output output(imgL_,imgR_);
00754   output.set_matcher(&matcher);
00755   //  Write the 3D output & triangles to out.dat
00756   output.write_output("out.dat");
00757   vil1_image scaled_image = scale_image(output.range_image_);
00758   itabR_->set_image(scaled_image);  // put the image in the viewer
00759   this->post_redraw();
00760   return output.range_image_;
00761 }
00762 
00763 // Make a vector of digital regions and pass the problem to
00764 // find_shadows(vcl_vector<vdgl_digital_region*>) below.
00765 //
00766 void vsrl_manager::find_shadows(vcl_vector<vtol_intensity_face_sptr>& faces)
00767 {
00768   vcl_vector<vdgl_digital_region*> reg_vec;
00769 
00770   for (vcl_vector<vtol_intensity_face_sptr>::iterator fit = faces.begin();
00771        fit != faces.end(); fit++) {
00772     vdgl_digital_region* reg = (*fit)->cast_to_digital_region();
00773     reg_vec.push_back(reg);
00774   }
00775   find_shadows(reg_vec);
00776   return;
00777 }
00778 
00779 //: This algorithm taken pretty much verbatim from the DDB/RegionSaliency class.
00780 //  Repeated here for digital regions instead of intensity faces...
00781 //
00782 
00783 void vsrl_manager::find_shadows(vcl_vector<vdgl_digital_region*> regions)
00784 {
00785   // Create an array to hold shadow metric
00786   // (First get rid of anything there already)
00787   if (shadow_metric_ != NULL) delete shadow_metric_;
00788   shadow_metric_ = new vcl_vector<float>(regions.size());
00789 
00790   e2d1_->set_foreground(0,0,1);
00791   e2d1_->set_point_radius(5);
00792 
00793   int i=0;
00794   vcl_vector<float>::iterator sm = shadow_metric_->begin();
00795   vcl_cout << "Shadow Threshold: " << shadow_mean_ << vcl_endl;
00796 
00797   for (vcl_vector<vdgl_digital_region*>::iterator rit = regions.begin();
00798        rit != regions.end(); ++rit,++i,++sm)
00799   {
00800     if ((*rit)->Npix() > 0)
00801     {
00802       (*rit)->ComputeIntensityStdev();
00803       vcl_cout << "Intensity Face: " << i << "  Io = " << (*rit)->Io()
00804                << "  I_stdev = " << (*rit)->Io_sd();
00805       if ((*rit)->Io() == 0)
00806         *sm=0.0;
00807       else if ((*rit)->Io() < shadow_mean_)
00808         *sm=1.0;
00809       else
00810       {
00811         // This segment of code is taken from the HistEntropy class
00812         // in TargetJr, GeneralUtility/Basics.  It is used to mimic
00813         // the operation of the shadow detection used in the DDB
00814         // RegionSaliency class.
00815 
00816         float m1=(*rit)->Io(); // Get the region mean
00817         float v1=(*rit)->Io_sd(); // Get the region Stdev.
00818 
00819         // Later we can adjust the shadow reference parameters.
00820 
00821         // For now, this is what we'll use...
00822         float m2 = shadow_mean_; // m2 is the reference shadow mean.
00823         float v2 = 1.0f; // v2 is the reference shadow stdev.
00824 
00825         if (m1==0 || m2==0)
00826           *sm=0.0;
00827         else if ( v1 < 1e-6 || v2 < 1e-6 )
00828           *sm=0.0;
00829         else
00830           *sm = vcl_exp(- vcl_fabs(0.693 * (m1-m2) * vcl_sqrt(1.0/(v1*v1) + 1.0/(v2*v2))));
00831       }
00832       vcl_cout << "  Shadow = " << *sm << vcl_endl;
00833     }
00834 
00835     if (*sm ==1)
00836       e2d1_->add_point((*rit)->Xo(),(*rit)->Yo());
00837   }
00838   e2d1_->set_foreground(1,0,0);
00839   e2d1_->set_point_radius(5);
00840 }
00841 
00842 // Though called "run_jseg" this routine does more than that.  After the jseg routine
00843 // executes, the output of jseg is partitioned into digital_regions and a vector of
00844 // the resulting digital regions is returned.
00845 #if 0
00846 vcl_vector<vdgl_digital_region*>
00847 vsrl_manager::run_jseg(vil1_image image_in)
00848 {
00849 #ifndef INCLUDE_JSEG
00850   vcl_cout << "vsrl_manager::run_jseg - Error. JSEG not included in this compilation.\n";
00851   vcl_vector<vdgl_digital_region*> empty;
00852   return empty;
00853 #else
00854   // Set up the JSEG parameters
00855   static float TQUAN=-1.0f;
00856   static int NSCALE=-1;
00857   static float threshcolor=-1.0f;
00858   vgui_dialog jseg_dialog("JSEG Parameters");
00859   jseg_dialog.field("Color Quantization Threshold (-1=automatic): ",TQUAN);
00860   jseg_dialog.field("Number of Scales (-1=automatic): ",NSCALE);
00861   jseg_dialog.field("Region Merge Threshold (-1=automatic): ",threshcolor);
00862   jseg_dialog.field("Shadow Mean Intensity Threshold: ", shadow_mean_);
00863   if (!jseg_dialog.ask()) return NULL;
00864 
00865   // Get the image for segmentation
00866   vil1_memory_image_of<unsigned char> im(image_in);
00867   unsigned char* cp = im.get_buffer();
00868   int nx = im.cols();
00869   int ny = im.rows();
00870   int dim = 1; // grayscale image
00871 
00872   // Run JSEG
00873   unsigned char* js_img = jseg(cp,dim,nx,ny,TQUAN,NSCALE,threshcolor);
00874   vil1_memory_image_of<unsigned char>* js_out = new vil1_memory_image_of<unsigned char>(js_img,nx,ny);
00875 
00876   // Now we have an "image" of the regions.  We need to sort it into
00877   // vdgl_digital_regions. We'll hold the regions in a vector.
00878 
00879   vcl_vector<vdgl_digital_region*> reg_vec;
00880 
00881   int reg_cntr = 0;  // A counter for regions
00882 
00883   // Initialize things with one region
00884   // We'll use a 3D region and use the Z coord. for the class label.
00885   vcl_cout << "Creating initial region.  #0\n";
00886   vdgl_digital_region* region1 = new vdgl_digital_region();
00887 
00888   // vdgl_digital_region(x,y,z,pix)
00889   // x & y are pixel coords. z is class label. pix=Intensity value of orignal image pixel.
00890   region1->IncrementMeans(0,0,(*js_out)(0,0),im(0,0));
00891   reg_vec.push_back(region1);  // Add the region to the vector.
00892 
00893   // Loop through all the image pixels, assigning them to regions
00894   // This pass only counts the pixels in regions and calculates their means.
00895   // Another pass is required later to actually assign inividual pixels to
00896   // their respective regions.
00897   // (See vdgl_digital_region::IncrementMeans(float,float,float,unsigned short)
00898   // for a description.
00899   for (int x=0;x<im.cols();x++) {
00900