00001
00002 #include "sdet_detector.h"
00003
00004
00005
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
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
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
00085
00086 sdet_detector::~sdet_detector()
00087 {
00088 ClearData();
00089 }
00090
00091
00092
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
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);
00122 sdet_contour contour(this->hysteresisFactor*this->noiseThreshold,
00123 this->minLength, this->minJump*this->noiseThreshold,
00124 this->maxGap);
00125
00126
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
00137 if (this->borderp)
00138 contour.InsertBorder(*edges, *vertices);
00139
00140
00141 contour.SubPixelAccuracy(*edges, *vertices,
00142 *locationx, *locationy);
00143
00144
00145 if (this->spacingp)
00146 sdet_contour::EqualizeSpacing(*edges);
00147
00148
00149 if (grad_mag&&angle)
00150 sdet_contour::SetEdgelData(*grad_mag, *angle, *edges);
00151
00152
00153 #if 0 // TargetJr
00154 const RectROI* roi = image->GetROI();
00155 sdet_contour::Translate(*edges, *vertices,
00156 roi->GetOrigX()+0.5,
00157 roi->GetOrigY()+0.5);
00158 #endif
00159 if(!use_roi_)
00160 return true;
00161 sdet_contour::Translate(*edges, *vertices,
00162 static_cast<float>(roi_.cmin(0)),
00163 static_cast<float>(roi_.rmin(0)));
00164 return true;
00165 }
00166
00167
00168
00169
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);
00182 sdet_contour contour(this->hysteresisFactor*this->noiseThreshold,
00183 this->minLength, this->minJump*this->noiseThreshold,
00184 this->maxGap);
00185
00186
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,
00196 *locationx, *locationy);
00197 if (this->spacingp)
00198 sdet_contour::EqualizeSpacing(*edges);
00199 if (this->borderp)
00200 contour.InsertBorder(*edges, *vertices);
00201 if (grad_mag&&angle)
00202 sdet_contour::SetEdgelData(*grad_mag, *angle, *edges);
00203 #if 0 // TargetJr
00204 sdet_contour::add_vertex_edgels(*edges);
00205 const RectROI* roi = image->GetROI();
00206 sdet_contour::Translate(*edges, *vertices,
00207 roi->GetOrigX()+0.5,
00208 roi->GetOrigY()+0.5);
00209 #endif
00210 return true;
00211 }
00212
00213
00214
00215
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) {
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;
00248 return edgel!=NULL;
00249 }
00250
00251 #if 0 // commented out
00252
00253
00254
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,
00271 grad_mag, angle);
00272
00273 if (this->junctionp) {
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
00292
00293
00294
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
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();
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(),
00337 roi->GetOrigX(), roi->GetOrigY(), sizex, sizey);
00338 #endif
00339
00340 image.get_section(image_buf.GetBuffer(),
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
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
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
00368 if(use_roi_)
00369 {
00370 if(roi_.n_regions()!=1)
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
00415 << " noise_weight " << noise_weight << vcl_endl
00416 << " noise_multiplier " << noise_multiplier << vcl_endl
00417 << " automatic_threshold " << automatic_threshold << vcl_endl
00418 << " aggressive_junction_closure " << aggressive_junction_closure << vcl_endl
00419 << " minLength " << minLength << vcl_endl
00420 << " contourFactor " << contourFactor << vcl_endl
00421 << " junctionFactor " << junctionFactor << vcl_endl
00422 << " filterFactor " << filterFactor << vcl_endl
00423 << " junctionp " << junctionp << vcl_endl
00424 << " minJump " << minJump << vcl_endl
00425 << " maxGap " << maxGap << vcl_endl
00426 << " spacingp " << spacingp << vcl_endl
00427 << " borderp " << borderp << vcl_endl
00428 << " corner_angle " << corner_angle << vcl_endl
00429 << " separation " << separation << vcl_endl
00430 << " min_corner_length " << min_corner_length << vcl_endl
00431 << " cycle " << cycle << vcl_endl
00432 << " ndimension " << ndimension
00433 << vcl_endl;
00434 }
00435
00436 void sdet_detector::DoBreakCorners(vcl_vector<vtol_edge_2d_sptr >& ,
00437 vcl_vector<vtol_edge_2d_sptr >& )
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
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
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 }