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

sdet_detector.cxx

Go to the documentation of this file.
00001 // This is brl/bseg/sdet/sdet_detector.cxx
00002 #include "sdet_detector.h"
00003 //:
00004 // \file
00005 // see sdet_detector.h
00006 //
00007 //-----------------------------------------------------------------------------
00008 
00009 #include <vil1/vil1_image.h>
00010 #include <vcl_iostream.h>
00011 #include <gevd/gevd_float_operators.h>
00012 #include <gevd/gevd_step.h>
00013 #include <gevd/gevd_bufferxy.h>
00014 #include <sdet/sdet_contour.h>
00015 #include <vil/vil_new.h>
00016 #include <vil/vil_image_view.h>
00017 #include <brip/brip_vil_float_ops.h>
00018 #include <vdgl/vdgl_digital_curve.h>
00019 #include <vdgl/vdgl_edgel_chain.h>
00020 #include <vdgl/vdgl_interpolator.h>
00021 #include <vsol/vsol_point_2d.h>
00022 //--------------------------------------------------------------------------------
00023 //
00024 //: Constructors.
00025 //
00026 sdet_detector::sdet_detector(sdet_detector_params& params)
00027   : sdet_detector_params(params),
00028     edgel(NULL), direction(NULL),
00029     locationx(NULL), locationy(NULL), grad_mag(NULL),
00030     angle(NULL), junctionx(NULL), junctiony(NULL), njunction(0),
00031     vertices(NULL), edges(NULL),
00032     filterFactor(2), hysteresisFactor(2.0), noiseThreshold(0.0)
00033 {   
00034   if (params.automatic_threshold)
00035     noise = -params.noise_weight;
00036   else
00037     noise = params.noise_multiplier;
00038 //don't really know but have to pick one
00039   use_vil_image = true;
00040   image=0;
00041   vimage=0;
00042   use_roi_ = false;
00043 }
00044 
00045 sdet_detector::sdet_detector(vil1_image img, float smoothSigma, float noiseSigma,
00046                              float contour_factor, float junction_factor, int min_length,
00047                              float maxgap, float min_jump)
00048   : image(img), vimage(0), noise(noiseSigma), edgel(NULL), direction(NULL),
00049     locationx(NULL), locationy(NULL), grad_mag(NULL),
00050     angle(NULL), junctionx(NULL), junctiony(NULL), njunction(0),
00051     vertices(NULL), edges(NULL),
00052     filterFactor(2), hysteresisFactor(2.0), noiseThreshold(0.0)
00053 {
00054   use_vil_image = false;
00055   sdet_detector_params::smooth = smoothSigma;
00056   sdet_detector_params::contourFactor = contour_factor;
00057   sdet_detector_params::junctionFactor = junction_factor;
00058   sdet_detector_params::minLength = min_length;
00059   sdet_detector_params::maxGap = maxgap;
00060   sdet_detector_params::minJump = min_jump;
00061   use_roi_ = false;
00062 }
00063 
00064 sdet_detector::sdet_detector(vil_image_resource_sptr & img, float smoothSigma, float noiseSigma,
00065                              float contour_factor, float junction_factor, int min_length,
00066                              float maxgap, float min_jump)
00067   : image(0),vimage(img), noise(noiseSigma), edgel(NULL), direction(NULL),
00068     locationx(NULL), locationy(NULL), grad_mag(NULL),
00069     angle(NULL), junctionx(NULL), junctiony(NULL), njunction(0),
00070     vertices(NULL), edges(NULL),
00071     filterFactor(2), hysteresisFactor(2.0), noiseThreshold(0.0)
00072 {
00073   use_vil_image = true;
00074   sdet_detector_params::smooth = smoothSigma;
00075   sdet_detector_params::contourFactor = contour_factor;
00076   sdet_detector_params::junctionFactor = junction_factor;
00077   sdet_detector_params::minLength = min_length;
00078   sdet_detector_params::maxGap = maxgap;
00079   sdet_detector_params::minJump = min_jump;
00080   use_roi_ = false;
00081 }
00082 
00083 
00084 //: Destructor.
00085 //  Caller has an obligation to clear all the created edges and vertices.
00086 sdet_detector::~sdet_detector()
00087 {
00088   ClearData();
00089 }
00090 
00091 
00092 //: Clear data buffer.  Protected.
00093 //
00094 void sdet_detector::ClearData()
00095 {
00096   delete edgel; delete direction; delete locationx; delete locationy;
00097   delete grad_mag; delete angle;
00098   delete [] junctionx; delete [] junctiony;
00099   if (vertices)
00100     vertices->clear();
00101   if (edges)
00102     edges->clear();
00103   delete vertices;
00104   vertices = 0;
00105   delete edges;
00106   edges = 0;
00107 }
00108 
00109 
00110 //: Detect the contour, a list of edges and vertices are generated.
00111 //
00112 bool  sdet_detector::DoContour()
00113 {
00114   if (edges && vertices) return true;
00115 
00116   if (!DoStep()) {
00117     vcl_cout << "***Fail on DoContour.\n";
00118     return false;
00119   }
00120 
00121   sdet_contour::ClearNetwork(edges, vertices);       // delete vertices/edges
00122   sdet_contour contour(this->hysteresisFactor*this->noiseThreshold,
00123                        this->minLength, this->minJump*this->noiseThreshold,
00124                        this->maxGap);
00125 
00126   // first, find isolated chains/cycles
00127   bool find_net  = contour.FindNetwork(*edgel, junctionp,
00128                                        njunction,
00129                                        junctionx, junctiony,
00130                                        edges, vertices);
00131   if (!find_net) {
00132     vcl_cout << "***Fail on FindNetwork.\n";
00133     return false;
00134   }
00135 
00136   //Insert a virtual border to enforce closure to support region topology.
00137   if (this->borderp)
00138     contour.InsertBorder(*edges, *vertices);
00139 
00140   //Move the edgel locations to interpolated positions using zero crossings
00141   contour.SubPixelAccuracy(*edges, *vertices,
00142                            *locationx, *locationy);
00143 
00144   // Reduce zig-zags and space out pixels in chains
00145   if (this->spacingp)
00146     sdet_contour::EqualizeSpacing(*edges);
00147 
00148   //Set gradient magnitude and angle values on each edgel
00149   if (grad_mag&&angle)
00150     sdet_contour::SetEdgelData(*grad_mag, *angle, *edges);
00151 
00152   //Keep this code which will be needed when we have ROI's
00153 #if 0 // TargetJr
00154    const RectROI* roi = image->GetROI();
00155    sdet_contour::Translate(*edges, *vertices, // display location at center
00156                            roi->GetOrigX()+0.5, // of pixel instead of
00157                            roi->GetOrigY()+0.5); // upper-left corner
00158 #endif
00159    if(!use_roi_)
00160      return true;
00161    sdet_contour::Translate(*edges, *vertices, // display location at center
00162                            static_cast<float>(roi_.cmin(0)), // of pixel instead of
00163                            static_cast<float>(roi_.rmin(0))); // upper-left corner
00164    return true;
00165 }
00166 
00167 //--------------------------------------------------------------------------------
00168 //
00169 //: Detect the fold contour, a list of edges and vertices are generated.
00170 //
00171 bool  sdet_detector::DoFoldContour()
00172 {
00173   if (edges && vertices) return true;
00174 
00175 #if 0
00176   if (!DoFold()) {
00177     vcl_cout << "***Fail on DoFoldContour.\n";
00178     return false;
00179   }
00180 #endif
00181   sdet_contour::ClearNetwork(edges, vertices);       // delete vertices/edges
00182   sdet_contour contour(this->hysteresisFactor*this->noiseThreshold,
00183                        this->minLength, this->minJump*this->noiseThreshold,
00184                        this->maxGap);
00185 
00186   // first, find isolated  chains/cycles
00187   bool t  = contour.FindNetwork(*edgel, junctionp,
00188                                 njunction,
00189                                 junctionx, junctiony,
00190                                 edges, vertices);
00191   if (!t) {
00192     vcl_cout << "***Fail on FindNetwork.\n";
00193     return false;
00194   }
00195   contour.SubPixelAccuracy(*edges, *vertices, // insert subpixel
00196                            *locationx, *locationy); // accuracy
00197   if (this->spacingp)           // reduce zig-zags and space out pixels
00198     sdet_contour::EqualizeSpacing(*edges); // in chains
00199   if (this->borderp)            // insert a virtual contour to enforce
00200     contour.InsertBorder(*edges, *vertices); // closure at border
00201   if (grad_mag&&angle)
00202     sdet_contour::SetEdgelData(*grad_mag, *angle, *edges); //Continuous edgel orientation.
00203 #if 0 // TargetJr
00204   sdet_contour::add_vertex_edgels(*edges);
00205   const RectROI* roi = image->GetROI();
00206   sdet_contour::Translate(*edges, *vertices, // display location at center
00207                           roi->GetOrigX()+0.5, // of pixel instead of
00208                           roi->GetOrigY()+0.5); // upper-left corner
00209 #endif
00210   return true;
00211 }
00212 
00213 //---------------------------------------------------------------------------
00214 //
00215 //: Detect step profiles in the image, using dG+NMS+extension.
00216 //
00217 bool sdet_detector::DoStep()
00218 {
00219   if (edgel) return true;
00220 
00221   const gevd_bufferxy* source;
00222   if(use_vil_image)
00223     source = GetBufferFromVilImage();
00224   else
00225     source = GetBufferFromImage();
00226   if (!source) {
00227     vcl_cout << " cannot get image buffer\n";
00228     return false;
00229   }
00230   gevd_step step(this->smooth, this->noise, this->contourFactor, this->junctionFactor);
00231 
00232   step.DetectEdgels(*source, edgel, direction, locationx, locationy, grad_mag, angle);
00233 
00234 
00235   if (this->junctionp) {                // extension to real/virtual contours
00236     njunction = step.RecoverJunctions(*source,
00237                                       *edgel, *direction,
00238                                       *locationx, *locationy,
00239                                       junctionx, junctiony);
00240   } else {
00241     njunction = 0;
00242     delete [] junctionx; junctionx = NULL;
00243     delete [] junctiony; junctiony = NULL;
00244   }
00245 
00246   this->noiseThreshold = step.NoiseThreshold();
00247   delete source;//this fixes a leak
00248   return edgel!=NULL;
00249 }
00250 
00251 #if 0 // commented out
00252 //---------------------------------------------------------------------------
00253 //
00254 //: Detect fold profiles in the image, using dG+NMS+extension.
00255 //
00256 bool sdet_detector::DoFold()
00257 {
00258   if (edgel) return true;
00259 
00260   const BufferXY* source = GetBufferFromImage();
00261   if (!source) {
00262     vcl_cout << " cannot get image buffer\n";
00263     return false;
00264   }
00265 
00266   Fold fold(this->smooth, this->noise,
00267             this->contourFactor,
00268             this->junctionFactor);
00269   fold.DetectEdgels(*source, edgel, direction,
00270                     locationx, locationy, true, //Flag to compute mag, angle
00271                     grad_mag, angle); //Reusing grad_mag, actually |d2G|
00272 
00273   if (this->junctionp) {                // extension to real/virtual contours
00274     njunction = fold.RecoverJunctions(*source,
00275                                       *edgel, *direction,
00276                                       *locationx, *locationy,
00277                                       junctionx, junctiony);
00278   } else {
00279     njunction = 0;
00280     delete [] junctionx; junctionx = NULL;
00281     delete [] junctiony; junctiony = NULL;
00282   }
00283 
00284   this->noiseThreshold = fold.NoiseThreshold();
00285   return edgel!=NULL;
00286 }
00287 #endif // 0
00288 
00289 //--------------------------------------------------------------------------------
00290 //
00291 //: Transform data in the image as float buffer.
00292 //
00293 // two versions so as not to break anything from the ancient code JLM
00294 // vil1_image version
00295 gevd_bufferxy* sdet_detector::GetBufferFromImage()
00296 {
00297   gevd_bufferxy* image_float_buf = 0;
00298 
00299   if (image_float_buf) return image_float_buf;
00300   //Tests for validity
00301   if (!image)
00302   {
00303     vcl_cout << "In sdet_detector::GetBufferFromImage() - no image\n";
00304     return 0;
00305   }
00306   if (image.components()!=1)
00307   {
00308     vcl_cout << "In sdet_detector::GetBufferFromImage() -"
00309              << " not exactly one component\n";
00310     return 0;
00311   }
00312 
00313 #if 0 // TargetJr
00314   RectROI* roi = image->GetROI(); // find user-selected region of interest
00315   int sizex = roi->GetSizeX();
00316   int sizey = roi->GetSizeY();
00317 #endif
00318   int sizey= image.rows();
00319   int sizex= image.cols();
00320 
00321   image_float_buf = new gevd_bufferxy(sizex, sizey,8*sizeof(float));
00322 
00323 
00324 #if 0 // commented out
00325   if (image->GetPixelType() == Image::FLOAT)
00326   {
00327     image->GetSection(image_float_buf->GetBuffer(),
00328                       roi->GetOrigX(), roi->GetOrigY(), sizex, sizey);
00329     return image_float_buf;
00330   }
00331 #endif
00332 
00333   gevd_bufferxy image_buf(sizex, sizey, image.bits_per_component());
00334 
00335 #if 0 // commented out
00336   image->GetSection(image_buf.GetBuffer(),      // copy bytes image into buf
00337                     roi->GetOrigX(), roi->GetOrigY(), sizex, sizey);
00338 #endif
00339 
00340   image.get_section(image_buf.GetBuffer(),     // copy bytes image into buf
00341                     0, 0, sizex, sizey);
00342 
00343   if (! gevd_float_operators::BufferToFloat(image_buf, *image_float_buf))
00344   {
00345     delete image_float_buf;
00346     image_float_buf = 0;
00347   }
00348 
00349   return image_float_buf;
00350 }
00351 // vil_image version
00352 gevd_bufferxy* sdet_detector::GetBufferFromVilImage()
00353 {
00354   gevd_bufferxy* image_float_buf = 0;
00355 
00356   if (image_float_buf) return image_float_buf;
00357   //Tests for validity
00358   
00359   if(!use_vil_image||!vimage->ni()||!vimage->nj())
00360   {
00361     vcl_cout << "In sdet_detector::GetBufferFromVilImage() - no image\n";
00362     return 0;
00363   }
00364 
00365   vil_image_resource_sptr process_region = vimage;
00366 
00367   //if an roi is specified then extract view and wrap a resource around it
00368   if(use_roi_)
00369     {
00370       if(roi_.n_regions()!=1)//no roi to process
00371         return 0;
00372       vil_image_view_base_sptr vb = 
00373         vimage->get_view(roi_.cmin(0), roi_.csize(0), roi_.rmin(0), roi_.rsize(0));
00374       if(!vb)
00375         return 0;
00376       process_region = vil_new_image_resource_of_view(*vb);
00377     }
00378 
00379   if (vimage->nplanes()!=1)
00380   {
00381     vil_image_view<unsigned short> sview 
00382       = brip_vil_float_ops::convert_to_short(process_region);
00383     process_region = vil_new_image_resource_of_view(sview);
00384   }
00385   
00386   int sizey= process_region->nj();
00387   int sizex= process_region->ni();
00388 
00389   image_float_buf = new gevd_bufferxy(sizex, sizey,8*sizeof(float));
00390 
00391 
00392 
00393   gevd_bufferxy image_buf(process_region);
00394 
00395   if (! gevd_float_operators::BufferToFloat(image_buf, *image_float_buf))
00396   {
00397     delete image_float_buf;
00398     image_float_buf = 0;
00399   }
00400 
00401   return image_float_buf;
00402 }
00403 
00404 void sdet_detector::print(vcl_ostream &strm) const
00405 {
00406   strm << "sdet_detector:\n"
00407        << "    noise " << noise << vcl_endl
00408        << "    njunction " << njunction << vcl_endl
00409        << "    num vertices " << vertices->size() << vcl_endl
00410        << "    num edges " << edges->size() << vcl_endl
00411        << "    filterfactor " << filterFactor << vcl_endl
00412        << "    hysteresisfactor " << hysteresisFactor << vcl_endl
00413        << "    noiseThreshold " << noiseThreshold << vcl_endl
00414        << "    smooth " <<   smooth << vcl_endl // Smoothing kernel sigma
00415        << "    noise_weight " <<   noise_weight << vcl_endl //The weight between sensor noise and texture noise
00416        << "    noise_multiplier " <<   noise_multiplier << vcl_endl // The overal noise threshold scale factor
00417        << "    automatic_threshold " <<   automatic_threshold << vcl_endl // Determine the threshold values from image
00418        << "    aggressive_junction_closure " <<   aggressive_junction_closure << vcl_endl //Close junctions agressively
00419        << "    minLength " <<   minLength << vcl_endl          // minimum chain length
00420        << "    contourFactor " <<   contourFactor << vcl_endl  // Threshold along contours
00421        << "    junctionFactor " <<   junctionFactor << vcl_endl //Threshold at junctions
00422        << "    filterFactor " <<   filterFactor << vcl_endl    // ratio of sensor to texture noise
00423        << "    junctionp " <<   junctionp << vcl_endl // recover missing junctions
00424        << "    minJump " <<   minJump << vcl_endl  // change in strength at junction
00425        << "    maxGap " <<   maxGap << vcl_endl   // Bridge small gaps up to max_gap across.
00426        << "    spacingp " <<   spacingp << vcl_endl  // equalize spacing?
00427        << "    borderp " <<   borderp << vcl_endl   // insert virtual border for closure?
00428        << "    corner_angle " <<   corner_angle << vcl_endl // smallest angle at corner
00429        << "    separation " <<   separation << vcl_endl // |mean1-mean2|/sigma
00430        << "    min_corner_length " <<   min_corner_length << vcl_endl // min length to find corners
00431        << "    cycle " <<   cycle << vcl_endl // number of corners in a cycle
00432        << "    ndimension " <<   ndimension // spatial dimension of edgel chains.
00433        << vcl_endl;
00434 }
00435 
00436 void sdet_detector::DoBreakCorners(vcl_vector<vtol_edge_2d_sptr >& /* in_edgels */,
00437                                    vcl_vector<vtol_edge_2d_sptr >& /* out_edgels */)
00438 {
00439   vcl_cerr << "sdet_detector::DoBreakCorners() NYI\n";
00440 }
00441 
00442 void sdet_detector::SetImage(vil1_image img)
00443 {
00444   use_vil_image = false;
00445   image = img;
00446 }
00447 
00448 void sdet_detector::SetImage(vil_image_resource_sptr const& img, brip_roi const& roi)
00449 {
00450   use_vil_image = true;
00451   vimage = img;
00452   use_roi_ = true;
00453   roi_ = roi;
00454 }
00455 
00456 void sdet_detector::SetImage(vil_image_resource_sptr const& img)
00457 {
00458   use_vil_image = true;
00459   vimage = img;
00460 }
00461 
00462 bool sdet_detector::
00463 get_vdgl_edges(vcl_vector<vdgl_digital_curve_sptr>& vd_edges )
00464 {
00465   vd_edges.clear();
00466   if(!edges)
00467     return false;
00468 
00469   for(vcl_vector<vtol_edge_2d_sptr >::iterator eit = edges->begin();
00470       eit != edges->end(); ++eit)
00471     {
00472       vtol_edge_2d_sptr & e = *eit;
00473       if(!e)
00474         continue;
00475       vsol_curve_2d_sptr c = e->curve();
00476       vdgl_digital_curve* dc = c->cast_to_vdgl_digital_curve();
00477       if(!dc)
00478         continue;
00479       
00480       vd_edges.push_back(dc);
00481     }
00482   if(!vd_edges.size())
00483     return false;
00484   return true;
00485 }
00486 
00487 bool 
00488 sdet_detector::get_vsol_edges(vcl_vector<vsol_digital_curve_2d_sptr>& edges )
00489 {
00490   vcl_vector<vdgl_digital_curve_sptr> vd_edges;
00491   if(!this->get_vdgl_edges(vd_edges))
00492     return false;
00493   edges.clear();
00494   for(vcl_vector<vdgl_digital_curve_sptr>::iterator eit = vd_edges.begin();
00495       eit != vd_edges.end(); ++eit)
00496     {
00497         //get the edgel chain
00498       vdgl_interpolator_sptr itrp = (*eit)->get_interpolator();
00499       vdgl_edgel_chain_sptr ech = itrp->get_edgel_chain();
00500       unsigned int n = ech->size();
00501       // convert to vsol_digital curve
00502       vsol_digital_curve_2d_sptr vsdc = new vsol_digital_curve_2d();
00503       for (unsigned int i=0; i<n;i++)
00504         {
00505           vdgl_edgel ed = (*ech)[i];
00506           double x = ed.get_x(), y = ed.get_y();
00507           vsdc->add_vertex(new vsol_point_2d(x, y));
00508         }
00509           
00510      edges.push_back(vsdc);
00511     }
00512   return true;
00513 }

Generated on Thu Jan 10 14:52:44 2008 for contrib/brl/bseg/sdet by  doxygen 1.4.4