contrib/gel/gevd/gevd_detector.cxx
Go to the documentation of this file.
00001 // This is gel/gevd/gevd_detector.cxx
00002 #include "gevd_detector.h"
00003 //:
00004 // \file
00005 // see gevd_detector.h
00006 //
00007 //-----------------------------------------------------------------------------
00008 
00009 #include <vil1/vil1_image.h>
00010 #include <vcl_iostream.h>
00011 #include "gevd_pixel.h"
00012 #include "gevd_float_operators.h"
00013 #include "gevd_step.h"
00014 #include "gevd_bufferxy.h"
00015 #include "gevd_contour.h"
00016 #include <vtol/vtol_edge_2d.h>
00017 
00018 //--------------------------------------------------------------------------------
00019 //
00020 //: Constructors.
00021 //
00022 gevd_detector::gevd_detector(gevd_detector_params& params)
00023   : gevd_detector_params(params),
00024     edgel(NULL), direction(NULL),
00025     locationx(NULL), locationy(NULL), grad_mag(NULL),
00026     angle(NULL), junctionx(NULL), junctiony(NULL), njunction(0),
00027     vertices(NULL), edges(NULL),
00028     filterFactor(2), hysteresisFactor(2.0), noiseThreshold(0.0)
00029 {
00030   if (params.automatic_threshold)
00031     noise = -params.noise_weight;
00032   else
00033     noise = params.noise_multiplier;
00034 
00035   image_float_buf_ = 0;
00036 }
00037 
00038 gevd_detector::gevd_detector(vil1_image img, float smoothSigma, float noiseSigma,
00039                              float contour_factor, float junction_factor, int min_length,
00040                              float maxgap, float min_jump)
00041   : image(img), noise(noiseSigma), edgel(NULL), direction(NULL),
00042     locationx(NULL), locationy(NULL), grad_mag(NULL),
00043     angle(NULL), junctionx(NULL), junctiony(NULL), njunction(0),
00044     vertices(NULL), edges(NULL),
00045     filterFactor(2), hysteresisFactor(2.0f), noiseThreshold(0.0f)
00046 {
00047   gevd_detector_params::smooth = smoothSigma;
00048   gevd_detector_params::contourFactor = contour_factor;
00049   gevd_detector_params::junctionFactor = junction_factor;
00050   gevd_detector_params::minLength = min_length;
00051   gevd_detector_params::maxGap = maxgap;
00052   gevd_detector_params::minJump = min_jump;
00053   image_float_buf_ = 0;
00054 }
00055 
00056 //--------------------------------------------------------------------------
00057 //: UnProtect lists that are protected by Contour::
00058 void gevd_detector::UnProtectLists()
00059 {
00060 #if 0 // commented out
00061   if (edges)//Need to mimic the protection of Contour
00062   for (CoolListP<Edge*>::iterator eit = edges->begin();
00063        eit != edges->end(); eit++)
00064     (*eit)->UnProtect();
00065   if (vertices)
00066     for (CoolListP<Vertex*>::iterator vit = vertices->begin();
00067          vit != vertices->end(); vit++)
00068       (*vit)->UnProtect();
00069 #endif
00070 }
00071 
00072 
00073 //: Destructor.
00074 //  Caller has an obligation to clear all the created edges and vertices.
00075 gevd_detector::~gevd_detector()
00076 {
00077   ClearData();
00078 }
00079 
00080 
00081 //: Clear data buffer.  Protected.
00082 //
00083 void gevd_detector::ClearData()
00084 {
00085   delete edgel; delete direction; delete locationx; delete locationy;
00086   delete grad_mag; delete angle;
00087   delete [] junctionx; delete [] junctiony;
00088   delete vertices;
00089   delete edges;
00090   if (image_float_buf_) delete image_float_buf_;
00091 }
00092 
00093 
00094 //: Detect the contour, a list of edges and vertices are generated.
00095 //
00096 bool  gevd_detector::DoContour()
00097 {
00098   if (edges && vertices) return true;
00099 
00100   if (!DoStep()) {
00101     vcl_cout << "***Fail on DoContour.\n";
00102     return false;
00103   }
00104   gevd_contour::ClearNetwork(edges, vertices);       // delete vertices/edges
00105   gevd_contour contour(this->hysteresisFactor*this->noiseThreshold, this->minLength,
00106                        this->minJump*this->noiseThreshold, this->maxGap);
00107   bool t  = contour.FindNetwork(*edgel, njunction, // first, find isolated
00108                                 junctionx, junctiony,   // chains/cycles
00109                                 edges, vertices);
00110   if (!t) {
00111     vcl_cout << "***Fail on FindNetwork.\n";
00112     return false;
00113   }
00114 
00115   vcl_vector<vtol_edge_2d_sptr>::iterator edge;
00116   vcl_cout << "IN DoContour before SubPixelAccuracy\n";
00117   this->print(vcl_cout);
00118   for ( edge = edges->begin() ; edge != edges->end(); ++edge)
00119     {
00120     vcl_cout << "Edgel output from DoContour:";
00121     (*edge)->describe(vcl_cout, 2);
00122     }
00123 
00124   contour.SubPixelAccuracy(*edges, *vertices, // insert subpixel
00125                            *locationx, *locationy); // accuracy
00126   if (this->spacingp)           // reduce zig-zags and space out pixels
00127     gevd_contour::EqualizeSpacing(*edges); // in chains
00128   if (this->borderp)            // insert a virtual contour to enforce
00129     contour.InsertBorder(*edges, *vertices); // closure at border
00130   if (grad_mag&&angle)
00131     gevd_contour::SetEdgelData(*grad_mag, *angle, *edges); //Continuous edgel orientation.
00132 
00133 //   const RectROI* roi = image->GetROI();
00134 //   gevd_contour::Translate(*edges, *vertices, // display location at center
00135 //                      roi->GetOrigX()+0.5, // of pixel instead of
00136 //                      roi->GetOrigY()+0.5); // upper-left corner
00137 
00138   return true;
00139 }
00140 
00141 //--------------------------------------------------------------------------------
00142 //
00143 //: Detect the fold contour, a list of edges and vertices are generated.
00144 //
00145 bool  gevd_detector::DoFoldContour()
00146 {
00147   if (edges && vertices) return true;
00148 
00149 //   if (!DoFold()) {
00150 //     vcl_cout << "***Fail on DoFoldContour.\n";
00151 //     return false;
00152 //   }
00153   gevd_contour::ClearNetwork(edges, vertices);       // delete vertices/edges
00154   gevd_contour contour(this->hysteresisFactor*this->noiseThreshold,
00155                        this->minLength, this->minJump*this->noiseThreshold,
00156                        this->maxGap);
00157 
00158   bool t  = contour.FindNetwork(*edgel, njunction, // first, find isolated
00159                                 junctionx, junctiony,   // chains/cycles
00160                                 edges, vertices);
00161   if (!t) {
00162     vcl_cout << "***Fail on FindNetwork.\n";
00163     return false;
00164   }
00165   contour.SubPixelAccuracy(*edges, *vertices, // insert subpixel
00166                            *locationx, *locationy); // accuracy
00167   if (this->spacingp)           // reduce zig-zags and space out pixels
00168     gevd_contour::EqualizeSpacing(*edges); // in chains
00169   if (this->borderp)            // insert a virtual contour to enforce
00170     contour.InsertBorder(*edges, *vertices); // closure at border
00171   if (grad_mag&&angle)
00172     gevd_contour::SetEdgelData(*grad_mag, *angle, *edges); //Continuous edgel orientation.
00173 
00174 //   const RectROI* roi = image->GetROI();
00175 //   gevd_contour::Translate(*edges, *vertices, // display location at center
00176 //                      roi->GetOrigX()+0.5, // of pixel instead of
00177 //                      roi->GetOrigY()+0.5); // upper-left corner
00178 
00179   return true;
00180 }
00181 
00182 //---------------------------------------------------------------------------
00183 //
00184 //: Detect step profiles in the image, using dG+NMS+extension.
00185 //
00186 bool gevd_detector::DoStep()
00187 {
00188   if (edgel) return true;
00189 
00190   const gevd_bufferxy* source = GetBufferFromImage();
00191   if (!source) {
00192     vcl_cout << " cannot get image buffer\n";
00193     return false;
00194   }
00195 
00196   gevd_step step(this->smooth, this->noise, this->contourFactor, this->junctionFactor);
00197   step.DetectEdgels(*source, edgel, direction, locationx, locationy, grad_mag, angle);
00198 
00199   if (this->junctionp) {                // extension to real/virtual contours
00200     njunction = step.RecoverJunctions(*source,
00201                                       *edgel, *direction,
00202                                       *locationx, *locationy,
00203                                       junctionx, junctiony);
00204   }
00205   else {
00206     njunction = 0;
00207     delete [] junctionx; junctionx = NULL;
00208     delete [] junctiony; junctiony = NULL;
00209   }
00210 
00211   this->noiseThreshold = step.NoiseThreshold();
00212 
00213   return edgel!=NULL;
00214 }
00215 
00216 #if 0 // commented out
00217 //---------------------------------------------------------------------------
00218 //
00219 //: Detect fold profiles in the image, using dG+NMS+extension.
00220 //
00221 bool gevd_detector::DoFold()
00222 {
00223   if (edgel) return true;
00224 
00225   const BufferXY* source = GetBufferFromImage();
00226   if (!source) {
00227     vcl_cout << " cannot get image buffer\n";
00228     return false;
00229   }
00230 
00231   Fold fold(this->smooth, this->noise,
00232             this->contourFactor,
00233             this->junctionFactor);
00234   fold.DetectEdgels(*source, edgel, direction,
00235                     locationx, locationy, true, //Flag to compute mag, angle
00236                     grad_mag, angle); //Reusing grad_mag, actually |d2G|
00237 
00238   if (this->junctionp) {                // extension to real/virtual contours
00239     njunction = fold.RecoverJunctions(*source,
00240                                       *edgel, *direction,
00241                                       *locationx, *locationy,
00242                                       junctionx, junctiony);
00243   }
00244   else {
00245     njunction = 0;
00246     delete [] junctionx; junctionx = NULL;
00247     delete [] junctiony; junctiony = NULL;
00248   }
00249 
00250   this->noiseThreshold = fold.NoiseThreshold();
00251   return edgel!=NULL;
00252 }
00253 #endif // 0
00254 
00255 //--------------------------------------------------------------------------------
00256 //
00257 //: Transform data in the image as float buffer.
00258 //
00259 gevd_bufferxy* gevd_detector::GetBufferFromImage()
00260 {
00261   if (image_float_buf_) return image_float_buf_;
00262 
00263   if (!image)
00264   {
00265     vcl_cout << "No image\n";
00266     return 0;
00267   }
00268 
00269   //  RectROI* roi = image->GetROI(); // find user-selected region of interest
00270   //  int sizex = roi->GetSizeX();
00271   //  int sizey = roi->GetSizeY();
00272   int sizey= image.rows();
00273   int sizex= image.cols();
00274 
00275   image_float_buf_ = new gevd_bufferxy(sizex, sizey,8*sizeof(float));
00276 
00277 #if 0 // commented out
00278   if (image->GetPixelType() == Image::FLOAT)
00279   {
00280     image->GetSection(image_float_buf_->GetBuffer(),
00281                       roi->GetOrigX(), roi->GetOrigY(), sizex, sizey);
00282     return image_float_buf_;
00283   }
00284 #endif
00285 
00286   //   gevd_bufferxy image_buf(sizex, sizey, image->GetBitsPixel());
00287   gevd_bufferxy image_buf(sizex, sizey, image.bits_per_component());
00288 
00289 #if 0 // commented out
00290   image->GetSection(image_buf.GetBuffer(),      // copy bytes image into buf
00291                     roi->GetOrigX(), roi->GetOrigY(), sizex, sizey);
00292 #endif
00293 
00294   image.get_section(image_buf.GetBuffer(),     // copy bytes image into buf
00295                     0, 0, sizex, sizey);
00296 
00297   if (! gevd_float_operators::BufferToFloat(image_buf, *image_float_buf_))
00298   {
00299     delete image_float_buf_;
00300     image_float_buf_ = 0;
00301   }
00302 
00303   return image_float_buf_;
00304 }
00305 
00306 // If we're setting a new image, we need to start from scratch
00307 void gevd_detector::SetImage(vil1_image img)
00308 {
00309   image = img;
00310   if (image_float_buf_) {
00311     delete image_float_buf_;
00312     image_float_buf_ = 0;
00313   }
00314   if (edgel) delete edgel;
00315   if (vertices) delete vertices;
00316   if (direction) delete direction;
00317   if (locationx) delete locationx;
00318   if (locationy) delete locationy;
00319   if (grad_mag) delete grad_mag;
00320   if (angle) delete angle;
00321   if (junctionx) delete [] junctionx;
00322   if (junctiony) delete [] junctiony;
00323 }
00324 
00325 void gevd_detector::print(vcl_ostream &strm) const
00326 {
00327   strm << "gevd_Detector:\n"
00328        << "    noise " << noise << vcl_endl
00329        << "    njunction " << njunction << vcl_endl
00330        << "    num vertices " << vertices->size() << vcl_endl
00331        << "    num edges " << edges->size() << vcl_endl
00332        << "    filterfactor " << filterFactor << vcl_endl
00333        << "    hysteresisfactor " << hysteresisFactor << vcl_endl
00334        << "    noiseThreshold " << noiseThreshold << vcl_endl
00335        << "    smooth " <<   smooth << vcl_endl // Smoothing kernel sigma
00336        << "    noise_weight " <<   noise_weight << vcl_endl //The weight between sensor noise and texture noise
00337        << "    noise_multiplier " <<   noise_multiplier << vcl_endl // The overal noise threshold scale factor
00338        << "    automatic_threshold " <<   automatic_threshold << vcl_endl // Determine the threshold values from image
00339        << "    aggressive_junction_closure " <<   aggressive_junction_closure << vcl_endl //Close junctions aggressively
00340        << "    minLength " <<   minLength << vcl_endl          // minimum chain length
00341        << "    contourFactor " <<   contourFactor << vcl_endl  // Threshold along contours
00342        << "    junctionFactor " <<   junctionFactor << vcl_endl //Threshold at junctions
00343        << "    filterFactor " <<   filterFactor << vcl_endl    // ratio of sensor to texture noise
00344        << "    junctionp " <<   junctionp << vcl_endl // recover missing junctions
00345        << "    minJump " <<   minJump << vcl_endl  // change in strength at junction
00346        << "    maxGap " <<   maxGap << vcl_endl   // Bridge small gaps up to max_gap across.
00347        << "    spacingp " <<   spacingp << vcl_endl  // equalize spacing?
00348        << "    borderp " <<   borderp << vcl_endl   // insert virtual border for closure?
00349        << "    corner_angle " <<   corner_angle << vcl_endl // smallest angle at corner
00350        << "    separation " <<   separation << vcl_endl // |mean1-mean2|/sigma
00351        << "    min_corner_length " <<   min_corner_length << vcl_endl // min length to find corners
00352        << "    cycle " <<   cycle << vcl_endl // number of corners in a cycle
00353        << "    ndimension " <<   ndimension << vcl_endl // spatial dimension of edgel chains.
00354        << vcl_endl;
00355 }