00001
00002
00003
00004 #include "osl_canny_ox.h"
00005 #include <osl/osl_canny_port.h>
00006 #include <osl/osl_canny_ox_params.h>
00007 #include <osl/osl_kernel.h>
00008 #include <osl/osl_canny_smooth.h>
00009 #include <osl/osl_canny_gradient.h>
00010 #include <osl/osl_canny_nms.h>
00011
00012 #include <vcl_cmath.h>
00013 #include <vcl_cstdlib.h>
00014 #include <vcl_list.h>
00015 #include <vcl_iostream.h>
00016 #include <vcl_cassert.h>
00017 #include <vnl/vnl_math.h>
00018
00019
00020
00021
00022
00023
00024 osl_canny_ox::osl_canny_ox(osl_canny_ox_params const ¶ms)
00025 : osl_canny_base(params.sigma, params.low, params.high, params.verbose)
00026 {
00027
00028 gauss_tail_ = params.gauss_tail;
00029 max_width_OX_ = params.max_width;
00030 kernel_ = new float[max_width_OX_];
00031 sub_area_OX_ = new float[max_width_OX_];
00032
00033 edge_min_OX_ = params.edge_min;
00034 min_length_OX_ = params.min_length;
00035 join_flag_OX_ = params.join_flag;
00036 border_size_OX_ = params.border_size;
00037 border_value_OX_ = params.border_value;
00038 scale_OX_ = params.scale;
00039 follow_strategy_OX_ = params.follow_strategy;
00040 junction_option_OX_ = params.junction_option;
00041
00042 xjunc_ = new vcl_list<int>;
00043 yjunc_ = new vcl_list<int>;
00044 vlist_ = new vcl_list<osl_Vertex*>;
00045
00046 jval_ = 2000.0;
00047 }
00048
00049
00050
00051 osl_canny_ox::~osl_canny_ox()
00052 {
00053 osl_canny_base_free_raw_image(smooth_);
00054 osl_canny_base_free_raw_image(dx_);
00055 osl_canny_base_free_raw_image(dy_);
00056 osl_canny_base_free_raw_image(grad_);
00057 osl_canny_base_free_raw_image(thick_);
00058 osl_canny_base_free_raw_image(thin_);
00059 osl_canny_base_free_raw_image(theta_);
00060
00061 osl_canny_base_free_raw_image(junction_);
00062 osl_canny_base_free_raw_image(jx_);
00063 osl_canny_base_free_raw_image(jy_);
00064
00065 fsm_delete_array kernel_;
00066 fsm_delete_array sub_area_OX_;
00067
00068 fsm_delete vlist_;
00069 fsm_delete xjunc_;
00070 fsm_delete yjunc_;
00071 }
00072
00073
00074
00075 void osl_canny_ox::detect_edges(vil1_image const &image_in, vcl_list<osl_edge*> *edges)
00076 {
00077 assert(edges!=0);
00078
00079
00080 xsize_ = image_in.height();
00081 ysize_ = image_in.width();
00082 xstart_ = 0;
00083 ystart_ = 0;
00084
00085 if (verbose)
00086 vcl_cerr << "Doing Canny on image region "
00087 << xsize_ << " by " << ysize_ << vcl_endl
00088 << "Sigma = " << sigma_ << vcl_endl
00089 << "Gaussian tail = " << gauss_tail_ << vcl_endl
00090 << "Max kernel size = " << max_width_OX_ << vcl_endl
00091 << "Upper threshold = " << high_ << vcl_endl
00092 << "Lower threshold = " << low_ << vcl_endl
00093 << "Min edgel intensity = " << edge_min_OX_ << vcl_endl
00094 << "Min edge length = " << min_length_OX_ << vcl_endl
00095 << "Image border size = " << border_size_OX_ << vcl_endl << vcl_endl;
00096
00097
00098 smooth_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00099 dx_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00100 dy_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00101 grad_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00102 thick_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00103 thin_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00104 theta_ = osl_canny_base_make_raw_image(xsize_, ysize_, (float*)0);
00105 junction_ = osl_canny_base_make_raw_image(xsize_, ysize_, (int*)0);
00106 jx_ = osl_canny_base_make_raw_image(xsize_, ysize_, (int*)0);
00107 jy_ = osl_canny_base_make_raw_image(xsize_, ysize_, (int*)0);
00108
00109
00110
00111 osl_canny_base_fill_raw_image(grad_, xsize_, ysize_, 0.0f);
00112 osl_canny_base_fill_raw_image(thick_, xsize_, ysize_, 0.0f);
00113 osl_canny_base_fill_raw_image(thin_, xsize_, ysize_, 0.0f);
00114 osl_canny_base_fill_raw_image(theta_, xsize_, ysize_, 10000.0f);
00115 osl_canny_base_fill_raw_image(junction_, xsize_, ysize_, 0);
00116 osl_canny_base_fill_raw_image(jx_, xsize_, ysize_, 0);
00117 osl_canny_base_fill_raw_image(jy_, xsize_, ysize_, 0);
00118
00119
00120
00121 if (verbose) vcl_cerr << "setting convolution kernel and zeroing images\n";
00122 osl_kernel_DOG(kernel_, sub_area_OX_, k_size_,
00123 sigma_, gauss_tail_,
00124 max_width_OX_, width_);
00125 if (verbose) vcl_cerr << "Kernel size = " << k_size_ << vcl_endl;
00126
00127
00128 if (verbose) vcl_cerr << "smoothing the image\n";
00129 osl_canny_smooth(image_in,
00130 kernel_, width_, sub_area_OX_,
00131 smooth_);
00132
00133 if (verbose)
00134 vcl_cerr << "computing x derivatives, y derivatives and norm of gradient\n";
00135 osl_canny_gradient(xsize_, ysize_, smooth_, dx_, dy_, grad_);
00136
00137 if (verbose) vcl_cerr << "doing non-maximal suppression\n";
00138 unsigned int n_edgels_NMS = osl_canny_nms(xsize_, ysize_, dx_, dy_, grad_, thick_, theta_);
00139 if (verbose) vcl_cerr << "Number of edgels after NMS = " << n_edgels_NMS << vcl_endl;
00140
00141
00142
00143
00144
00145
00146
00147 int *x_ = new int[n_edgels_NMS];
00148 int *y_ = new int[n_edgels_NMS];
00149
00150
00151
00152
00153
00154 osl_edgel_chain *edgels_NMS = Get_NMS_edgelsOX(n_edgels_NMS, x_, y_);
00155
00156
00157 if (verbose) vcl_cerr << "doing hysteresis\n";
00158 int *status = new int[n_edgels_NMS];
00159 int n_edgels_Hysteresis = HysteresisOX(edgels_NMS, status);
00160 if (verbose) vcl_cerr << "Number of edgels after Hysteresis = " << n_edgels_Hysteresis << vcl_endl;
00161
00162 osl_edgel_chain *edgels_Hysteresis = new osl_edgel_chain(n_edgels_Hysteresis);
00163 Get_hysteresis_edgelsOX(edgels_NMS,status,edgels_Hysteresis, x_, y_);
00164
00165
00166 fsm_delete_array status;
00167 fsm_delete edgels_NMS; edgels_NMS = 0;
00168
00169
00170 fsm_delete_array x_;
00171 fsm_delete_array y_;
00172
00173 if (follow_strategy_OX_ == 0)
00174 {
00175 edges->push_front( NO_FollowerOX(edgels_Hysteresis) );
00176
00177 fsm_delete edgels_Hysteresis;
00178 return;
00179 }
00180
00181
00182 fsm_delete edgels_Hysteresis;
00183
00184
00185 Scale_imageOX(thin_, scale_OX_);
00186
00187 Set_image_borderOX(thin_, border_size_OX_, border_value_OX_);
00188
00189 if (junction_option_OX_)
00190 {
00191
00192 if (verbose) vcl_cerr << "locating junctions in the edge image - ";
00193 Find_junctionsOX();
00194 if (verbose) vcl_cerr << xjunc_->size() << " junctions found\n";
00195 Find_junction_clustersOX();
00196 if (verbose) vcl_cerr << vlist_->size() << " junction clusters found\n";
00197 }
00198
00199
00200 if (verbose) vcl_cerr << "doing final edge following\n";
00201 FollowerOX(edges);
00202 if (verbose) vcl_cerr << "finished osl_canny_ox\n";
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 osl_edgel_chain *osl_canny_ox::Get_NMS_edgelsOX(int n_edgels_NMS, int *x_, int *y_)
00215 {
00216
00217 osl_edgel_chain *edgels_NMS = new osl_edgel_chain(n_edgels_NMS);
00218
00219 int i = 0;
00220
00221 for (unsigned int y=1; y+1<ysize_; ++y)
00222 for (unsigned int x=1; x+1<xsize_; ++x)
00223 if ( thick_[x][y] != 0 )
00224 {
00225 assert(i < n_edgels_NMS);
00226
00227 edgels_NMS->SetX(dx_[x][y],i);
00228 edgels_NMS->SetY(dy_[x][y],i);
00229 edgels_NMS->SetGrad(thick_[x][y],i);
00230 edgels_NMS->SetTheta(theta_[x][y],i);
00231
00232 x_[i] = x; y_[i] = y;
00233 i++;
00234 }
00235
00236 return edgels_NMS;
00237 }
00238
00239
00240
00241
00242
00243
00244 int osl_canny_ox::HysteresisOX(osl_edgel_chain *&edgels_NMS,
00245 int *&status)
00246 {
00247 unsigned int n_edgels_NMS = edgels_NMS->size();
00248 if (!n_edgels_NMS)
00249 return 0;
00250
00251
00252 vcl_vector<unsigned> rows(ysize_+1);
00253
00254
00255 vcl_vector<unsigned> row(n_edgels_NMS);
00256 vcl_vector<unsigned> col(n_edgels_NMS);
00257 vcl_vector<osl_LINK *> links(n_edgels_NMS);
00258
00259 for (unsigned int i=0; i<n_edgels_NMS; ++i) {
00260 links[i] = 0;
00261 row[i] = (int) edgels_NMS->GetY(i);
00262 col[i] = (int) edgels_NMS->GetX(i);
00263 status[i] = 0;
00264 }
00265 for (unsigned int i=0,j=0; i<=ysize_; ++i) {
00266 while (j<n_edgels_NMS && row[j]<i)
00267 ++j;
00268 rows[i]=j;
00269 }
00270
00271
00272
00273 Link_edgelsOX(col, rows, &links[0]);
00274
00275
00276
00277 double low = (32.0/vcl_log(2.0)) * vcl_log(low_/100+1.0);
00278 double high = (32.0/vcl_log(2.0)) * vcl_log(high_/100+1.0);
00279
00280 for (unsigned int i=0; i<n_edgels_NMS; ++i)
00281 if (!status[i] && edgels_NMS->GetGrad(i)>high) {
00282 status[i]=1;
00283 for (osl_LINK *lptr=links[i]; lptr; lptr=lptr->nextl)
00284 Initial_followOX(lptr->to, i, edgels_NMS, &links[0], status, (float)low);
00285 }
00286
00287
00288
00289 int n_edgels_Hysteresis = Get_n_edgels_hysteresisOX(edgels_NMS,status);
00290
00291
00292 for (unsigned int i=0; i<n_edgels_NMS; ++i)
00293 for (osl_LINK *link1 = links[i]; link1; ) {
00294 osl_LINK *link2 = link1->nextl;
00295 fsm_delete link1;
00296 link1 = link2;
00297 }
00298
00299 return n_edgels_Hysteresis;
00300 }
00301
00302
00303
00304
00305
00306 void osl_canny_ox::Initial_followOX(int to,
00307 int from,
00308 osl_edgel_chain *&edgels_NMS,
00309 osl_LINK *links[],
00310 int *&status,
00311 float low)
00312 {
00313 if (!status[to] && edgels_NMS->GetGrad(to) > low)
00314 status[to]=1;
00315 else
00316 return;
00317
00318 for (osl_LINK *lptr=links[to]; lptr; lptr=lptr->nextl)
00319 if (lptr->to!=from)
00320 Initial_followOX(lptr->to,to,edgels_NMS,links,status,low);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 void osl_canny_ox::Add_linkOX(int edgel,
00330 int to,
00331 osl_LINK *links[])
00332 {
00333 osl_LINK *lptr1=new osl_LINK;
00334 lptr1->to=to;
00335 lptr1->nextl=links[edgel];
00336 links[edgel]=lptr1;
00337
00338 osl_LINK *lptr2=new osl_LINK;
00339 lptr2->to=edgel;
00340 lptr2->nextl=links[to];
00341 links[to]=lptr2;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 void osl_canny_ox::Link_edgelsOX(vcl_vector<unsigned> const &col,
00359 vcl_vector<unsigned> const &rows,
00360 osl_LINK *links[])
00361
00362 {
00363 for (unsigned int i=0; i<ysize_; ++i)
00364 {
00365 for (unsigned j=rows[i]; j<rows[i+1]; ++j)
00366 {
00367 bool e=false;
00368 bool s=false;
00369
00370
00371
00372 if (j+1<rows[i+1] && col[j]+1==col[j+1]) {
00373 Add_linkOX(j, j+1, links); e=true; }
00374
00375 bool w=(j>rows[i] && col[j]==col[j-1]+1);
00376
00377
00378
00379 if (rows[i+1] == rows[ysize_])
00380 {
00381 if (e) continue;
00382
00383 if (i > 0) {
00384 unsigned int k=rows[i-1];
00385 while (k < rows[i] && col[k] < col[j]+1) ++k;
00386 if (k < rows[i] && col[k] == col[j]+1) continue;
00387 }
00388
00389 if (j+1<rows[i+1] && col[j]+2==col[j+1])
00390 Add_linkOX(j, j+1, links);
00391 continue;
00392 }
00393
00394
00395
00396 unsigned int k=rows[i+1];
00397
00398 while (k < rows[i+2] && col[k]+1 < col[j]) ++k;
00399
00400
00401 if (k == rows[i+2]) continue;
00402
00403 if (k+1 < rows[i+2] && col[k+1] == col[j]) ++k;
00404 if (col[j]==col[k]) {
00405 Add_linkOX(j, k, links); s = true; }
00406
00407
00408
00409 bool se = false;
00410 if (!e && !s && col[j]+1==col[k]) {
00411 Add_linkOX(j,k,links); se = true; }
00412 if (!w && !s && col[j]==col[k]+1) {
00413 Add_linkOX(j,k,links); s = w = true; }
00414 if (se) s = e = true;
00415
00416
00417 if (i > 0) {
00418 k=rows[i-1];
00419 while (k < rows[i] && col[k]+1 < col[j]) ++k;
00420 if (k < rows[i] && col[k]+1 == col[j]) w = true;
00421 while (k < rows[i] && col[k] < col[j]+1) ++k;
00422 if (k < rows[i] && col[k] == col[j]+1) e = true;
00423 }
00424
00425 if (e && w && s) continue;
00426
00427
00428
00429 if (!e && j+1<rows[i+1] && col[j]+2==col[j+1]) {
00430 Add_linkOX(j, j+1, links); e = true; }
00431
00432 if (j>rows[i] && col[j]==col[j-1]+2)
00433 w = true;
00434
00435
00436
00437 k=rows[i+2];
00438 if (!s && k < rows[ysize_]) {
00439 while (k < rows[i+3] && col[k] < col[j]) ++k;
00440
00441 if (k < rows[i+3] && col[j] == col[k]) {
00442 Add_linkOX(j, k, links); s = true; }
00443 }
00444
00445 if (e && w && s) continue;
00446
00447
00448
00449
00450 k=rows[i+1];
00451 while (k < rows[i+2] && col[k]+2 < col[j]) ++k;
00452 if (!w && k < rows[i+2] && col[j] == col[k]+2) {
00453 Add_linkOX(j, k, links); s = w = true; }
00454 while (k < rows[i+2] && col[k] < col[j]+2) ++k;
00455 if (!e && k < rows[i+2] && col[j]+2 == col[k]) {
00456 Add_linkOX(j, k, links); s = e = true; }
00457
00458 if (s) continue;
00459
00460
00461 k=rows[i+2]; if (k == rows[ysize_]) continue;
00462 while (k < rows[i+3] && col[k]+1 < col[j]) ++k;
00463 if (k < rows[i+3] && (col[j] == col[k]+1 || col[j]+1 == col[k]))
00464 Add_linkOX(j, k, links);
00465
00466 }
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475 int osl_canny_ox::Get_n_edgels_hysteresisOX(osl_edgel_chain *&edgels_NMS,
00476 int *&status)
00477 {
00478 int n_edgels_Hysteresis = 0;
00479 for (int i=edgels_NMS->size()-1; i>=0; --i)
00480 if (status[i])
00481 ++n_edgels_Hysteresis;
00482 return n_edgels_Hysteresis;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492 void osl_canny_ox::Get_hysteresis_edgelsOX(osl_edgel_chain *& edgels_NMS,
00493 int *&status,
00494 osl_edgel_chain *& edgels_Hysteresis,
00495 int *x_, int *y_)
00496 {
00497
00498 osl_canny_base_fill_raw_image(thin_, xsize_, ysize_, 0.0f);
00499
00500 unsigned int n_edgels_NMS = edgels_NMS->size();
00501
00502 for (unsigned int i=0,j=0; i<n_edgels_NMS; ++i)
00503 {
00504 if (status[i])
00505 {
00506
00507 edgels_Hysteresis->SetX(edgels_NMS->GetX(i),j);
00508 edgels_Hysteresis->SetY(edgels_NMS->GetY(i),j);
00509 edgels_Hysteresis->SetGrad(edgels_NMS->GetGrad(i),j);
00510 edgels_Hysteresis->SetTheta(edgels_NMS->GetTheta(i),j);
00511
00512 thin_[x_[i]][y_[i]] = edgels_NMS->GetGrad(i);
00513 j++;
00514 }
00515 }
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525 osl_edge *osl_canny_ox::NO_FollowerOX(osl_edgel_chain *edgels_Hysteresis)
00526 {
00527 int n_edgels_Hysteresis = edgels_Hysteresis->size();
00528
00529
00530
00531
00532 osl_edge *dc = new osl_edge(n_edgels_Hysteresis,
00533 new osl_Vertex(edgels_Hysteresis->GetX(0)+xstart_,
00534 edgels_Hysteresis->GetY(0)+ystart_),
00535 new osl_Vertex(edgels_Hysteresis->GetX(n_edgels_Hysteresis-1)+xstart_,
00536 edgels_Hysteresis->GetY(n_edgels_Hysteresis-1)+ystart_));
00537
00538 float* px = dc->GetX(); float* py = dc->GetY();
00539 float* pg = dc->GetGrad(); float* pt = dc->GetTheta();
00540
00541 for (int i=0; i<n_edgels_Hysteresis; ++i) {
00542 *(px++) = edgels_Hysteresis->GetX(i) + xstart_;
00543 *(py++) = edgels_Hysteresis->GetY(i) + ystart_;
00544 *(pg++) = edgels_Hysteresis->GetGrad(i);
00545 *(pt++) = edgels_Hysteresis->GetTheta(i);
00546 }
00547
00548 return dc;
00549 }
00550
00551
00552
00553
00554
00555
00556 osl_Vertex *osl_find(vcl_list<osl_Vertex*> const *l, osl_Vertex const &v)
00557 {
00558 for (vcl_list<osl_Vertex*>::const_iterator i=l->begin(); i!=l->end(); ++i)
00559 if (v == *(*i))
00560 return *i;
00561 return 0;
00562 }
00563
00564 osl_Vertex *osl_find(vcl_list<osl_Vertex*> const *l, float x, float y)
00565 {
00566 for (vcl_list<osl_Vertex*>::const_iterator i=l->begin(); i!=l->end(); ++i)
00567 if ((*i)->x == x && (*i)->y == y)
00568 return *i;
00569 return 0;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579 void osl_canny_ox::FollowerOX(vcl_list<osl_edge*> *edges)
00580 {
00581 if (junction_option_OX_)
00582 chain_no_ = 10;
00583
00584
00585 vcl_list<int> xcoords, ycoords;
00586 vcl_list<float> grad;
00587
00588 edges->clear();
00589 for (unsigned int x=border_size_OX_; x<xsize_-border_size_OX_; ++x)
00590 for (unsigned int y=border_size_OX_; y<ysize_-border_size_OX_; ++y)
00591 {
00592
00593 if ( (thin_[x][y] < edge_min_OX_) || junction_[x][y] )
00594 continue;
00595
00596 if (junction_option_OX_)
00597 chain_no_++;
00598
00599
00600 xcoords.clear();
00601 ycoords.clear();
00602 grad.clear();
00603
00604
00605 Final_followOX(x,y, &xcoords, &ycoords, &grad,0);
00606
00607
00608
00609
00610 xcoords.reverse();
00611 ycoords.reverse();
00612 grad.reverse();
00613 Final_followOX(x,y,&xcoords,&ycoords,&grad,1);
00614
00615 int count=xcoords.size();
00616 if (count < min_length_OX_ || count < 1)
00617 #ifdef DEBUG
00618 vcl_cerr << "short list found in Final_followOX\n";
00619 #endif
00620 continue;
00621
00622
00623 osl_edgel_chain * dc = new osl_edgel_chain(count);
00624 float *px = dc->GetX();
00625 float *py = dc->GetY();
00626 float *pg = dc->GetGrad();
00627 float *pt = dc->GetTheta();
00628
00629
00630
00631 while (count--)
00632 {
00633 int tmpx = xcoords.front(); xcoords.pop_front();
00634 int tmpy = ycoords.front(); ycoords.pop_front();
00635 float val = grad.front(); grad.pop_front();
00636
00637 if ( val != jval_ ) {
00638 *(px++) = dx_[tmpx][tmpy] + xstart_;
00639 *(py++) = dy_[tmpx][tmpy] + ystart_;
00640 *(pg++) = val;
00641 }
00642 else {
00643 *(px++) = float(tmpx + xstart_);
00644 *(py++) = float(tmpy + ystart_);
00645 *(pg++) = 0.0f;
00646 }
00647 *(pt++) = theta_[tmpx][tmpy];
00648
00649 }
00650
00651
00652
00653 if ( (dc->size()==2) &&
00654 (dc->GetX(0)==dc->GetX(1)) &&
00655 (dc->GetY(0)==dc->GetY(1)) ) {
00656 #ifdef DEBUG
00657 vcl_cerr << "trivial edgechain\n";
00658 #endif
00659 }
00660 else if ( dc->size() > 1 )
00661 {
00662
00663 osl_Vertex *v1 = new osl_Vertex(dc->GetX(0),dc->GetY(0));
00664 osl_Vertex *v2 = new osl_Vertex(dc->GetX(dc->size()-1),dc->GetY(dc->size()-1));
00665
00666 if (junction_option_OX_)
00667 {
00668
00669 osl_Vertex *V1 = osl_find(vlist_, *v1);
00670 osl_Vertex *V2 = osl_find(vlist_, *v2);
00671
00672
00673
00674 bool single_chain = false;
00675 if ( !V1 && !V2 )
00676 {
00677 float dx = dc->GetX(0) - dc->GetX(dc->size()-1);
00678 float dy = dc->GetY(0) - dc->GetY(dc->size()-1);
00679 if (dc->size() < 1 || dx*dx+dy*dy < 4) {
00680
00681 delete v2;
00682 v2 = v1;
00683 single_chain = true;
00684 }
00685 }
00686
00687 if (!single_chain) {
00688 if (V1) { delete v1; v1 = V1; }
00689 if (V2) { delete v2; v2 = V2; }
00690
00691 }
00692 }
00693 else {
00694
00695
00696 float dx = dc->GetX(0) - dc->GetX(dc->size()-1);
00697 float dy = dc->GetY(0) - dc->GetY(dc->size()-1);
00698 if ((dx*dx+dy*dy) < 4.0) {
00699
00700 delete v2;
00701 v2 = v1;
00702 }
00703
00704
00705 }
00706
00707
00708
00709
00710
00711
00712 #ifdef DEBUG
00713 vcl_cerr << __FILE__ ": push\n";
00714 #endif
00715 edges->push_front(new osl_edge(*dc, v1, v2));
00716 }
00717 delete dc;
00718 }
00719 #ifdef DEBUG
00720 vcl_cerr << "edges->size() : " << edges->size() << vcl_endl;
00721 #endif
00722 }
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 void osl_canny_ox::Final_followOX(int x,
00754 int y,
00755 vcl_list<int> *xc,
00756 vcl_list<int> *yc,
00757 vcl_list<float> *grad,
00758 int reverse)
00759 {
00760
00761 assert ( x>0 && y>0 );
00762 assert ( (unsigned)x+1<xsize_ );
00763 assert ( (unsigned)y+1<ysize_ );
00764
00765
00766
00767 if (!reverse) {
00768 xc->push_front(x);
00769 yc->push_front(y);
00770 grad->push_front(thin_[x][y]);
00771 }
00772 thin_[x][y] = 0.0;
00773
00774 bool junction_or_jump = false;
00775
00776 switch (follow_strategy_OX_)
00777 {
00778 case 1:
00779
00780
00781 if (false) { }
00782 #define smoo(a, b) \
00783 else if ( (thin_[a][b] >= edge_min_OX_) && (!junction_[a][b]) ) \
00784 Final_followOX(a,b,xc,yc,grad,0);
00785 smoo(x-1, y )
00786 smoo(x-1, y+1)
00787 smoo(x , y+1)
00788 smoo(x+1, y+1)
00789 smoo(x+1, y )
00790 smoo(x+1, y-1)
00791 smoo(x , y-1)
00792 smoo(x-1, y-1)
00793 #undef smoo
00794 else
00795 junction_or_jump = true;
00796 break;
00797
00798 case 2:
00799 default:
00800 if (false) { }
00801 #define smoo(a, b) \
00802 else if ( (thin_[a][b] >= edge_min_OX_) && (!junction_[a][b]) ) Final_followOX(a,b ,xc,yc,grad,0);
00803 smoo(x-1, y )
00804 smoo(x , y+1)
00805 smoo(x-1, y+1)
00806 smoo(x+1, y )
00807 smoo(x+1, y+1)
00808 smoo(x , y-1)
00809 smoo(x+1, y-1)
00810 smoo(x-1, y-1)
00811 #undef smoo
00812 else
00813 junction_or_jump = true;
00814 break;
00815 }
00816
00817 if (!junction_or_jump)
00818 return;
00819
00820
00821
00822
00823
00824 if (false) { }
00825 #define smoo(a, b) \
00826 else if ( junction_[a][b] && ((xc->size()>2) || (junction_[a][b]!=chain_no_)) ) { \
00827 xc->push_front(jx_[a][b]); \
00828 yc->push_front(jy_[a][b]); \
00829 grad->push_front(jval_); \
00830 junction_[a][b] = chain_no_; \
00831 }
00832 smoo(x , y-1)
00833 smoo(x-1, y )
00834 smoo(x , y+1)
00835 smoo(x+1, y )
00836 smoo(x+1, y-1)
00837 smoo(x-1, y-1)
00838 smoo(x-1, y+1)
00839 smoo(x+1, y+1)
00840 #undef smoo
00841 else if ( join_flag_OX_ && (xc->size() > 1) )
00842 {
00843
00844
00845 int x_c = xc->front(); xc->pop_front();
00846 int x_p = xc->front(); xc->pop_front();
00847 int y_c = yc->front(); yc->pop_front();
00848 int y_p = yc->front(); yc->pop_front();
00849 int dx = x_c - x_p;
00850 int dy = y_c - y_p;
00851 xc->push_front(x_p); xc->push_front(x_c);
00852 yc->push_front(y_p); yc->push_front(y_c);
00853 int xNew, yNew;
00854 if (Join_dotsOX(x, y, dx, dy, xNew, yNew))
00855 Final_followOX(xNew,yNew,xc,yc,grad,0);
00856 }
00857 }
00858
00859
00860
00861
00862 #if 0
00863 void Set_intsOX(int& int1, int& int2, int val1, int val2)
00864 {
00865 int1 = val1;
00866 int2 = val2;
00867 }
00868 #endif
00869 #define Set_intsOX(d1, d2, v1, v2) ((d1)=(v1), (d2)=(v2))
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 int osl_canny_ox::Join_dotsOX(int x, int y, int dx, int dy, int& xNew, int& yNew)
00883 {
00884 if ((vcl_abs(dx) > 1) || (vcl_abs(dy) > 1)) {
00885
00886
00887
00888 return false;
00889 }
00890
00891
00892 assert( x>1 && y>1 );
00893 assert( (unsigned int)x+2<xsize_ );
00894 assert( (unsigned int)y+2<ysize_ );
00895
00896 if (!dx && (vcl_abs(dy) == 1))
00897 {
00898 if (thin_[x ][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x , y+2*dy);
00899 else if (thin_[x+1][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+1, y+2*dy);
00900 else if (thin_[x-1][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x-1, y+2*dy);
00901 else if (thin_[x+2][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2, y+2*dy);
00902 else if (thin_[x-2][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x-2, y+2*dy);
00903 else if (thin_[x+2][y+ dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2, y+dy );
00904 else if (thin_[x-2][y+ dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x-2, y+dy );
00905 else if (thin_[x+2][y ] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2, y );
00906 else if (thin_[x-2][y ] >= edge_min_OX_) Set_intsOX(xNew, yNew, x-2, y );
00907 else return false;
00908 }
00909 else if ((vcl_abs(dx) == 1) && !dy)
00910 {
00911 if (thin_[x+2*dx][y ] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y );
00912 else if (thin_[x+2*dx][y+1] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y+1);
00913 else if (thin_[x+2*dx][y-1] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y-1);
00914 else if (thin_[x+2*dx][y+2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y+2);
00915 else if (thin_[x+2*dx][y-2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y-2);
00916 else if (thin_[x+ dx][y+2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+ dx, y+2);
00917 else if (thin_[x+ dx][y-2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+ dx, y-2);
00918 else if (thin_[x ][y+2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x , y+2);
00919 else if (thin_[x ][y-2] >= edge_min_OX_) Set_intsOX(xNew, yNew, x , y-2);
00920 else return false;
00921 }
00922 else if (vcl_abs(dx*dy) == 1)
00923 {
00924 if (thin_[x+2*dx][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y+2*dy);
00925 else if (thin_[x+2*dx][y+ dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y+ dy);
00926 else if (thin_[x+ dx][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+ dx, y+2*dy);
00927 else if (thin_[x+2*dx][y ] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y );
00928 else if (thin_[x ][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x , y+2*dy);
00929 else if (thin_[x+2*dx][y- dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x+2*dx, y- dy);
00930 else if (thin_[x- dx][y+2*dy] >= edge_min_OX_) Set_intsOX(xNew, yNew, x- dx, y+2*dy);
00931 else return false;
00932 }
00933 else
00934 return false;
00935
00936 return true;
00937 }
00938
00939
00940
00941
00942
00943
00944 void osl_canny_ox::Scale_imageOX(float **image, float scale)
00945 {
00946 for (unsigned int x=0; x<xsize_; ++x)
00947 for (unsigned int y=0; y<ysize_; ++y)
00948 image[x][y] = vnl_math_min( image[x][y]*scale, 255.0f );
00949 }
00950
00951
00952
00953
00954
00955
00956 void osl_canny_ox::Set_image_borderOX(float **image, int border_size, float value)
00957 {
00958 assert(border_size >= 0);
00959 assert((unsigned int)border_size <= xsize_);
00960 assert((unsigned int)border_size <= ysize_);
00961
00962 for (int i=0; i<border_size; ++i) {
00963 for (unsigned int x=0; x<xsize_; ++x)
00964 image[x][i] = image[x][ysize_-1-i] = value;
00965 for (unsigned int y=0; y<ysize_; ++y)
00966 image[i][y] = image[xsize_-1-i][y] = value;
00967 }
00968 }
00969
00970
00971
00972
00973
00974
00975 void osl_canny_ox::Find_junctionsOX()
00976 {
00977
00978 xjunc_->clear(); yjunc_->clear();
00979 osl_canny_base_fill_raw_image(junction_, xsize_, ysize_, 0);
00980
00981 for (unsigned int x=border_size_OX_; x+border_size_OX_<xsize_; ++x)
00982 for (unsigned int y=border_size_OX_; y+border_size_OX_<ysize_; ++y)
00983 {
00984 if ( thin_[x][y] < edge_min_OX_ )
00985 continue;
00986
00987 int a = ( thin_[x-1][y-1] >= edge_min_OX_ ) ? 1 : 0;
00988 a += ( thin_[x ][y-1] >= edge_min_OX_ ) ? 1 : 0;
00989 a += ( thin_[x+1][y-1] >= edge_min_OX_ ) ? 1 : 0;
00990 a += ( thin_[x+1][y ] >= edge_min_OX_ ) ? 1 : 0;
00991 a += ( thin_[x+1][y+1] >= edge_min_OX_ ) ? 1 : 0;
00992 a += ( thin_[x ][y+1] >= edge_min_OX_ ) ? 1 : 0;
00993 a += ( thin_[x-1][y+1] >= edge_min_OX_ ) ? 1 : 0;
00994 a += ( thin_[x-1][y ] >= edge_min_OX_ ) ? 1 : 0;
00995
00996 if ( a > 2 ) {
00997 xjunc_->push_front(x); yjunc_->push_front(y);
00998 junction_[x][y] = 1;
00999 }
01000 }
01001 }
01002
01003
01004
01005
01006
01007
01008 void osl_canny_ox::Find_junction_clustersOX()
01009 {
01010 vcl_list<int> xvertices,yvertices,xjunc,yjunc;
01011
01012
01013 xvertices.clear(); yvertices.clear();
01014 xjunc.clear(); yjunc.clear();
01015 for (unsigned int x=border_size_OX_; x+border_size_OX_<xsize_; ++x)
01016 for (unsigned int y=border_size_OX_; y+border_size_OX_<ysize_; ++y)
01017 if ( junction_[x][y] )
01018 {
01019
01020 vcl_list<int> xcoords,ycoords;
01021 Follow_junctions(junction_, x,y,&xcoords,&ycoords);
01022
01023
01024
01025 int x0,y0;
01026 Cluster_centre_of_gravity(jx_, jy_, xcoords,ycoords,x0,y0);
01027
01028
01029
01030 xvertices.push_front(x0);
01031 yvertices.push_front(y0);
01032 xjunc.insert(xjunc.begin(), xcoords.begin(), xcoords.end());
01033 yjunc.insert(yjunc.begin(), ycoords.begin(), ycoords.end());
01034 }
01035
01036
01037
01038
01039 while ( xjunc.size() ) {
01040 junction_[xjunc.front()][yjunc.front()] = 1;
01041 xjunc.pop_front();
01042 yjunc.pop_front();
01043 }
01044
01045
01046 typedef vcl_list<int>::iterator it;
01047 for (it i=xvertices.begin(), j=yvertices.begin(); i!=xvertices.end() && j!=yvertices.end(); ++i, ++j) {
01048 osl_Vertex *v = new osl_Vertex( float((*i)+xstart_), float((*j)+ystart_));
01049 vlist_->push_front(v);
01050 junction_[*i][*j] = 2;
01051 }
01052 }