00001
00002 #include "osl_fit_lines.h"
00003
00004
00005
00006 #include <vcl_cassert.h>
00007 #include <vcl_iostream.h>
00008 #include <vcl_list.h>
00009
00010 #include <vnl/vnl_math.h>
00011
00012 #include <osl/osl_canny_port.h>
00013
00014 #define warn_if_empty(e) \
00015 if (true && e->size()==0) \
00016 vcl_cerr << __FILE__ ": " << __LINE__ << " edge \'" #e "' has zero length\n";
00017
00018 #define WARN if (false) { } else (vcl_cerr << __FILE__ ": " << __LINE__ << ' ')
00019
00020
00021
00022 osl_fit_lines::osl_fit_lines(osl_fit_lines_params const & params,
00023 double scale, double x0, double y0)
00024 : osl_fit_lines_params(params)
00025 {
00026 double temp_thresh = this->threshold_;
00027 if (this->use_square_fit_) temp_thresh *= this->threshold_;
00028 this->threshold_ = temp_thresh;
00029 data_ = new osl_OrthogRegress(scale,x0,y0);
00030 }
00031
00032 osl_fit_lines::~osl_fit_lines()
00033 {
00034 delete data_; data_ = 0;
00035 }
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 void osl_fit_lines::simple_fit_to_list(vcl_list<osl_edge *> *myedges,
00048 vcl_list<osl_edge *> *outedges)
00049 {
00050 int edge_no = 0;
00051 vcl_list<osl_edgel_chain*> curves;
00052 for (vcl_list<osl_edge*>::iterator i=myedges->begin(); i!=myedges->end(); ++i)
00053 {
00054 osl_edge *edge = *i;
00055
00056 bool angle_ok = true;
00057 {
00058 osl_edgel_chain *dc = edge;
00059 assert(dc!=0);
00060 bool success = false;
00061
00062
00063 if ( dc->size() >= min_fit_length_ )
00064 {
00065 double using_degrees = 1.0;
00066
00067
00068
00069 for (unsigned int ii=0; ii<dc->size(); ii++)
00070 {
00071 if (dc->GetTheta(ii) > 3.2 || dc->GetTheta(ii) < -3.2)
00072 {
00073 using_degrees = vnl_math::pi_over_180;
00074 break;
00075 }
00076 }
00077 data_->Reset();
00078 double angle = vnl_math::pi_over_4;
00079 int orient0 = int((dc->GetTheta(0) * using_degrees + angle/2.0) / angle);
00080 for (unsigned int ii=0;ii<dc->size();ii++)
00081 {
00082 data_->IncrByXY(dc->GetX(ii), dc->GetY(ii));
00083 int orient = int((dc->GetTheta(ii) * using_degrees + angle/2.0)/angle);
00084 int diff = vnl_math_abs(orient - orient0);
00085 if (diff > 1 && diff < 7)
00086 angle_ok = false;
00087 }
00088 data_->Fit();
00089 float mean_cost = MyGetCost(data_, 0, dc->size(), dc);
00090 float ls_cost = (float)data_->GetCost();
00091 if ((use_square_fit_ && ls_cost < threshold_) ||
00092 (!use_square_fit_ && mean_cost < threshold_ && angle_ok))
00093 {
00094 success = true;
00095 old_finish_ = 0;
00096 if (use_square_fit_)
00097 OutputLine(&curves, 0, dc->size(), dc, ls_cost);
00098 else
00099 OutputLine(&curves, 0, dc->size(), dc, mean_cost);
00100 }
00101 }
00102
00103 if (success) {
00104 osl_edgel_chain *mycurve = fsm_pop(&curves);
00105
00106
00107
00108
00109 osl_edge *newedge = new osl_edge(*mycurve, edge->GetV1(), edge->GetV2());
00110 delete mycurve;
00111 edge->unref();
00112 edge = newedge;
00113 }
00114 edge->SetId(edge_no);
00115
00116 edge->ref();
00117 outedges->push_front(edge);
00118 warn_if_empty(edge);
00119 }
00120 }
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130 void osl_fit_lines::incremental_fit_to_list(vcl_list<osl_edge *> *myedges,
00131 vcl_list<osl_edge *> *outedges)
00132 {
00133 #ifdef DEBUG
00134 vcl_cout << "Fitting lines to Edge(s), threshold = " << threshold_ << vcl_endl;
00135 #endif
00136 int edge_no = 0;
00137 int vertex_no = 1000;
00138
00139
00140
00141 outedges->clear();
00142 for (vcl_list<osl_edge*>::iterator iter=myedges->begin(); iter!=myedges->end(); ++iter)
00143 {
00144 osl_edge *edge = *iter;
00145 ++edge_no;
00146
00147 vcl_list<osl_edgel_chain*> curves;
00148 if (use_square_fit_)
00149 SquareIncrementalFit(&curves, edge);
00150 else
00151 MeanIncrementalFit(&curves, edge);
00152
00153
00154
00155
00156
00157
00158
00159
00160 if ( curves.empty() )
00161 {
00162 edge->SetId(edge_no);
00163 outedges->push_front(edge);
00164 warn_if_empty(edge);
00165 }
00166
00167
00168 else if ( curves.size() == 1 )
00169 {
00170 osl_edgel_chain *mycurve = fsm_pop(&curves);
00171 outedges->push_front(new osl_edge(*mycurve, edge->GetV1(), edge->GetV2()));
00172 outedges->front()->SetId(edge_no);
00173 warn_if_empty(edge);
00174 edge->unref();
00175 }
00176
00177
00178 else
00179 {
00180 curves.reverse();
00181 osl_vertex *v2 = edge->GetV1();
00182 while (!curves.empty())
00183 {
00184 osl_edgel_chain *next = fsm_pop(&curves);
00185 osl_vertex* v1 = v2;
00186 if (curves.empty())
00187 v2 = edge->GetV2();
00188 else
00189 v2 = new osl_vertex(next->GetX(next->size()-1), next->GetY(next->size()-1), vertex_no++);
00190 outedges->push_front(new osl_edge(*next, v1, v2));
00191 warn_if_empty(outedges->front());
00192 }
00193 }
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202 void osl_fit_lines::MeanIncrementalFit(vcl_list<osl_edgel_chain*> *curves_, osl_edge *edge)
00203 {
00204
00205 float new_cost, new_est_cost;
00206
00207 osl_edgel_chain *dc = edge;
00208 assert(dc!=0);
00209
00210
00211 if ( dc->size() < min_fit_length_ )
00212 return;
00213
00214 bool added = false;
00215 unsigned int i,j,segment_length;
00216
00217
00218 unsigned int start = ignore_end_edgels_;
00219 old_finish_ = 1;
00220 unsigned int finish = start + min_fit_length_;
00221
00222 data_->Reset();
00223 for (i=start;i<finish;i++)
00224 data_->IncrByXY(dc->GetX(i),dc->GetY(i));
00225
00226
00227
00228 while ( finish <= dc->size() )
00229 {
00230
00231 segment_length = finish - start;
00232
00233
00234 data_->Fit();
00235 new_cost = MyGetCost(data_, start, finish, dc);
00236
00237
00238 if ( new_cost < threshold_)
00239 {
00240
00241
00242 if ( finish == dc->size() )
00243 {
00244 OutputLine(curves_, start,finish-ignore_end_edgels_,dc,new_cost);
00245 finish++;
00246 }
00247 else
00248 {
00249
00250
00251
00252
00253
00254 added = false;
00255 new_est_cost = new_cost;
00256 while ( (finish<dc->size()) && (new_est_cost<threshold_ ) )
00257 {
00258
00259
00260
00261 double distance =
00262 data_->GetA()*dc->GetX(finish) + data_->GetB()*dc->GetY(finish) + data_->GetC();
00263 new_est_cost = float(segment_length*new_est_cost + vcl_abs(distance)) / (segment_length+1);
00264
00265
00266
00267 if ( new_est_cost < threshold_ )
00268 {
00269 data_->IncrByXY(dc->GetX(finish),dc->GetY(finish));
00270 finish++;
00271 segment_length++;
00272 added = true;
00273 }
00274 }
00275
00276
00277
00278 if ( !added )
00279 {
00280
00281
00282
00283 for (unsigned int ii=0; ii<ignore_end_edgels_; ++ii)
00284 data_->DecrByXY(dc->GetX(finish-1-ii), dc->GetY(finish-1-ii));
00285 data_->Fit();
00286 new_cost = MyGetCost(data_, start, finish-ignore_end_edgels_, dc);
00287 OutputLine(curves_, start,finish-ignore_end_edgels_,dc,new_cost);
00288 start = finish+ignore_end_edgels_; finish = start + min_fit_length_;
00289 if ( finish<=dc->size() )
00290 {
00291 data_->Reset();
00292 for (i=start;i<finish;i++)
00293 data_->IncrByXY(dc->GetX(i),dc->GetY(i));
00294 }
00295 }
00296 }
00297 }
00298
00299
00300
00301
00302 else
00303 {
00304
00305
00306
00307 if ( added )
00308 {
00309 added = false;
00310 i = finish;
00311 while (new_cost > threshold_ && segment_length > min_fit_length_)
00312 {
00313 data_->DecrByXY(dc->GetX(i), dc->GetY(i));
00314 i --;
00315 segment_length --;
00316 data_->Fit();
00317 new_cost = MyGetCost(data_, start, i, dc);
00318 }
00319 finish = i;
00320 OutputLine(curves_, start,finish,dc,new_cost);
00321 start = finish; finish = start + min_fit_length_;
00322 if ( finish<=dc->size() )
00323 {
00324 data_->Reset();
00325 for (i=start;i<finish;i++)
00326 data_->IncrByXY(dc->GetX(i),dc->GetY(i));
00327 }
00328 }
00329 else
00330 {
00331 data_->DecrByXY(dc->GetX(start),dc->GetY(start));
00332 start++;
00333
00334 if ( segment_length > min_fit_length_ )
00335 while ( segment_length > min_fit_length_+1 )
00336 {
00337 data_->DecrByXY(dc->GetX(finish),dc->GetY(finish));
00338 finish--;
00339 segment_length--;
00340 }
00341 else if ( finish<dc->size() )
00342 {
00343 data_->IncrByXY(dc->GetX(finish),dc->GetY(finish));
00344 finish++;
00345 }
00346
00347 else
00348 finish++;
00349 }
00350 }
00351 }
00352
00353
00354
00355
00356 unsigned int length = dc->size() - old_finish_;
00357 if ( curves_->size() && length )
00358 {
00359 osl_edgel_chain *ndc = new osl_edgel_chain(length);
00360 for (i=0,j=old_finish_;j<dc->size();i++,j++)
00361 {
00362 ndc->SetX(dc->GetX(j),i);
00363 ndc->SetY(dc->GetY(j),i);
00364 ndc->SetGrad(dc->GetGrad(j),i);
00365 ndc->SetTheta(dc->GetTheta(j),i);
00366 }
00367 curves_->push_front(ndc);
00368 }
00369 }
00370
00371
00372
00373
00374
00375
00376
00377 void osl_fit_lines::SquareIncrementalFit(vcl_list<osl_edgel_chain*> *curves_, osl_edge *edge)
00378 {
00379 #ifdef DEBUG
00380 vcl_cerr << "SquareIncrementalFit()\n";
00381 #endif
00382
00383 osl_edgel_chain *dc = edge;
00384 assert(dc!=0);
00385
00386
00387 if ( dc->size() < min_fit_length_ )
00388 return;
00389
00390 bool added = false;
00391 unsigned int i,j,segment_length;
00392
00393
00394 unsigned int start = ignore_end_edgels_;
00395 old_finish_ = 1;
00396 unsigned int finish = start + min_fit_length_;
00397
00398 data_->Reset();
00399 for (i=start;i<finish;i++)
00400 data_->IncrByXY(dc->GetX(i),dc->GetY(i));
00401
00402
00403
00404 while ( finish <= dc->size() )
00405 {
00406
00407 segment_length = finish - start;
00408
00409
00410 data_->Fit();
00411
00412
00413
00414 if ( data_->GetCost() < threshold_ )
00415 {
00416
00417
00418 if ( finish == dc->size() )
00419 {
00420 OutputLine(curves_, start,finish-ignore_end_edgels_,dc,float(data_->GetCost()));
00421 finish++;
00422 }
00423
00424 else
00425 {
00426
00427
00428
00429
00430
00431 added = false;
00432 data_->SetEstCost(data_->GetCost());
00433 while ( (finish<dc->size()) && (data_->GetEstCost()<threshold_) )
00434 {
00435
00436
00437
00438 double distance =
00439 data_->GetA()*dc->GetX(finish) + data_->GetB()*dc->GetY(finish) + data_->GetC();
00440 data_->SetEstCost( (segment_length*data_->GetEstCost() + distance*distance) / (segment_length+1) );
00441
00442
00443
00444 if ( data_->GetEstCost()<threshold_ )
00445 {
00446 data_->IncrByXY(dc->GetX(finish),dc->GetY(finish));
00447 finish++;
00448 segment_length++;
00449 added = true;
00450 }
00451 }
00452
00453
00454
00455 if ( !added )
00456 {
00457
00458
00459
00460 for (unsigned int ii=0; ii<ignore_end_edgels_; ++ii)
00461 data_->DecrByXY(dc->GetX(finish-1-ii), dc->GetY(finish-1-ii));
00462 data_->Fit();
00463
00464 OutputLine(curves_, start,finish-ignore_end_edgels_,dc,float(data_->GetCost()));
00465 start = finish+ignore_end_edgels_; finish = start + min_fit_length_;
00466 if ( finish<=dc->size() )
00467 {
00468 data_->Reset();
00469 for (i=start;i<finish;i++)
00470 data_->IncrByXY(dc->GetX(i),dc->GetY(i));
00471 }
00472 }
00473 }
00474 }
00475
00476
00477
00478
00479 else
00480 {
00481 data_->DecrByXY(dc->GetX(start),dc->GetY(start));
00482 start++;
00483
00484 if ( segment_length > min_fit_length_ )
00485 while ( (segment_length-1) > min_fit_length_ )
00486 {
00487 data_->DecrByXY(dc->GetX(finish),dc->GetY(finish));
00488 finish--;
00489 segment_length--;
00490 }
00491 else if ( finish<dc->size() )
00492 {
00493 data_->IncrByXY(dc->GetX(finish),dc->GetY(finish));
00494 finish++;
00495 }
00496
00497 else
00498 finish++;
00499 }
00500 }
00501
00502
00503
00504
00505 unsigned int length = dc->size() - old_finish_;
00506 if ( curves_->size() && length )
00507 {
00508 osl_edgel_chain *ndc = new osl_edgel_chain(length);
00509 for (i=0,j=old_finish_;j<dc->size();i++,j++)
00510 {
00511 ndc->SetX(dc->GetX(j),i);
00512 ndc->SetY(dc->GetY(j),i);
00513 ndc->SetGrad(dc->GetGrad(j),i);
00514 ndc->SetTheta(dc->GetTheta(j),i);
00515 }
00516 curves_->push_front(ndc);
00517 }
00518 }
00519
00520
00521
00522
00523 void osl_fit_lines::OutputLine(vcl_list<osl_edgel_chain*> *curves_,
00524 int start, int finish,
00525 osl_edgel_chain *dc,
00526 float )
00527 {
00528
00529
00530 int length = start - old_finish_;
00531 if ( length > 0 )
00532 {
00533 osl_edgel_chain *ndc = new osl_edgel_chain(length);
00534 for (int i=0,j=old_finish_;j<start;i++,j++)
00535 {
00536 ndc->SetX(dc->GetX(j),i);
00537 ndc->SetY(dc->GetY(j),i);
00538 ndc->SetGrad(dc->GetGrad(j),i);
00539 ndc->SetTheta(dc->GetTheta(j),i);
00540 }
00541 curves_->push_front(ndc);
00542 }
00543 old_finish_ = finish;
00544
00545
00546 osl_edgel_chain *line = new osl_edgel_chain(finish-start);
00547 for (int i=0,j=start;j<finish;i++,j++) {
00548 line->SetX(dc->GetX(j),i);
00549 line->SetY(dc->GetY(j),i);
00550 line->SetGrad(dc->GetGrad(j),i);
00551 line->SetTheta(dc->GetTheta(j),i);
00552 }
00553 curves_->push_front(line);
00554
00555
00556 MergeLines(curves_);
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 void osl_fit_lines::MergeLines(vcl_list<osl_edgel_chain*> *curves_)
00570 {
00571 if ( curves_->size() < 2 )
00572 return;
00573
00574
00575
00576 osl_edgel_chain *dc2 = fsm_pop(curves_);
00577 osl_edgel_chain *dc1 = fsm_pop(curves_);
00578
00579 #ifndef fsm_is_cute
00580 osl_ortho_regress fitter;
00581 fitter.reset();
00582 for (unsigned int i=0; i<dc1->size(); ++i)
00583 fitter.add_point(dc1->GetX(i), dc1->GetY(i));
00584 for (unsigned int i=0; i<dc2->size(); ++i)
00585 fitter.add_point(dc2->GetX(i), dc2->GetY(i));
00586 double a, b, c;
00587 fitter.fit(&a, &b, &c);
00588 if (fitter.cost(a, b, c) >= threshold_)
00589 {
00590 curves_->push_front(dc1);
00591 curves_->push_front(dc2);
00592 }
00593 else
00594 {
00595
00596 osl_edgel_chain *dc = new osl_edgel_chain(dc1->size() + dc2->size());
00597 for (unsigned int i=0; i<dc1->size(); ++i)
00598 {
00599 dc->SetX(dc1->GetX(i), i);
00600 dc->SetY(dc1->GetY(i), i);
00601 dc->SetGrad(dc1->GetGrad(i), i);
00602 dc->SetTheta(dc1->GetTheta(i), i);
00603 }
00604 for (unsigned int i=0; i<dc2->size(); ++i)
00605 {
00606 dc->SetX(dc2->GetX(i), i + dc1->size());
00607 dc->SetY(dc2->GetY(i), i + dc1->size());
00608 dc->SetGrad(dc2->GetGrad(i), i + dc1->size());
00609 dc->SetTheta(dc2->GetTheta(i), i + dc1->size());
00610 }
00611 delete dc1;
00612 delete dc2;
00613 curves_->push_front(dc);
00614 }
00615
00616 #else
00617 ImplicitDigitalLine *l1 = (ImplicitDigitalLine*) dc1;
00618 ImplicitDigitalLine *l2 = (ImplicitDigitalLine*) dc2;
00619
00620
00621 double x1[2],y1[2],x2[2],y2[2];
00622 ImplicitDigitalLine *line = l1;
00623 for (int i=0; i<2; i++,line=l2)
00624 {
00625 x1[i] = line->GetStartX(); y1[i] = line->GetStartY();
00626 x2[i] = line->GetEndX(); y2[i] = line->GetEndY();
00627 }
00628
00629
00630
00631
00632 float xstart = vcl_min( vcl_min(x1[0],x1[1]), vcl_min(x2[0],x2[1]) );
00633 float xfinish= vcl_max( vcl_max(x1[0],x1[1]), vcl_max(x2[0],x2[1]) );
00634 float ystart = vcl_min( vcl_min(y1[0],y1[1]), vcl_min(y2[0],y2[1]) );
00635 float yfinish= vcl_max( vcl_max(y1[0],y1[1]), vcl_max(y2[0],y2[1]) );
00636 float phi = vcl_atan2(yfinish-ystart,xfinish-xstart);
00637 double cp = vcl_cos(phi), sp = vcl_sin(phi);
00638
00639 for (int i=0;i<2;i++)
00640 {
00641 float x = x1[i]*cp + y1[i]*sp;
00642 y1[i] = y1[i]*cp - x1[i]*sp;
00643 x1[i] = x;
00644
00645 x = x2[i]*cp + y2[i]*sp;
00646 y2[i] = y2[i]*cp - x2[i]*sp;
00647 x2[i] = x;
00648 }
00649
00650
00651 double a[2],b[2],c[2];
00652 for (int i=0;i<2;i++)
00653 {
00654
00655 a[i] = y1[i] - y2[i];
00656 b[i] = x2[i] - x1[i];
00657 c[i] = x1[i]*y2[i] - x2[i]*y1[i];
00658
00659 double m = vcl_sqrt(a[i]*a[i] + b[i]*b[i]);
00660 if ( b[i] > 0 ) m = -m;
00661
00662 a[i] /= m; b[i] /= m; c[i] /= m;
00663 }
00664
00665
00666 double theta = 180.0*vcl_acos(a[0]*a[1]+b[0]*b[1])/M_PI;
00667
00668
00669 if ( theta > 90.0 )
00670 theta = 180.0 - theta;
00671 if ( theta > theta_ )
00672 {
00673 curves_->push_front(dc1); curves_->push_front(dc2);
00674 return;
00675 }
00676
00677
00678 double x1_2,x1_3,x2_2,x2_3;
00679 vnl_matrix<double> S(3,3,0.0);
00680 vnl_matrix<double> Si(3,3),S1i(3,3),S2i(3,3),S3i(3,3);
00681 vnl_matrix<double> S11(2,2),S12(2,1),S_lambda,vec3(1,1);
00682 double S22;
00683 double normaliser=0.0;
00684
00685
00686 for (int i=0;i<2;i++)
00687 {
00688
00689 S1i.put(0,0,1.0); S1i.put(0,1,-a[i]/b[i]); S1i.put(0,2,0.0);
00690 S1i.put(1,0,-a[i]/b[i]); S1i.put(1,1,(a[i]*a[i])/(b[i]*b[i]));
00691 S1i.put(1,2,0.0);
00692 S1i.put(2,0,0.0); S1i.put(2,1,0.0); S1i.put(2,2,0.0);
00693
00694 S2i.put(0,0,0.0); S2i.put(0,1,-c[i]/(2.0*b[i]));
00695 S2i.put(0,2,0.5);
00696 S2i.put(1,0,-c[i]/(2.0*b[i])); S2i.put(1,1,(a[i]*c[i])/(b[i]*b[i]));
00697 S2i.put(1,2,-a[i]/(2.0*b[i]));
00698 S2i.put(2,0,0.5); S2i.put(2,1,-a[i]/(2.0*b[i]));
00699 S2i.put(2,2,0.0);
00700
00701 S3i.put(0,0,0.0); S3i.put(0,1,0.0); S3i.put(0,2,0.0);
00702 S3i.put(1,0,0.0); S3i.put(1,1,(c[i]*c[i])/(b[i]*b[i]));
00703 S3i.put(1,2,-c[i]/b[i]);
00704 S3i.put(2,0,0.0); S3i.put(2,1,-c[i]/b[i]);
00705 S3i.put(2,2,1.0);
00706
00707 x1_2 = x1[i]*x1[i]; x1_3 = x1_2*x1[i];
00708 x2_2 = x2[i]*x2[i]; x2_3 = x2_2*x2[i];
00709
00710
00711 if ( x2[i] > x1[i] )
00712 {
00713 Si = (x2_3-x1_3)/3.0*S1i;
00714 Si += (x2_2-x1_2)*S2i;
00715 Si += (x2[i]-x1[i])*S3i;
00716 double s = vcl_fabs(b[i]);
00717 Si *= (1.0/s);
00718 }
00719 else
00720 {
00721 Si = ((x1_3-x2_3)*S1i/3.0+(x1_2-x2_2)*S2i+
00722 (x1[i]-x2[i])*S3i);
00723 Si *= 1/vcl_fabs(b[i]);
00724 }
00725
00726
00727 S += Si;
00728
00729
00730 normaliser += vcl_fabs((x2[i]-x1[i])/b[i]);
00731 }
00732
00733
00734 S11.put(0,0,S.get(0,0)); S11.put(0,1,S.get(0,1));
00735 S11.put(1,0,S.get(1,0)); S11.put(1,1,S.get(1,1));
00736 S12.put(0,0,S.get(0,2)); S12.put(1,0,S.get(1,2));
00737 S22 = S.get(2,2);
00738
00739
00740 S_lambda = S11 - S12 * (1.0/S22) * S12.transpose();
00741
00742
00743 vnl_matrix<double> U(2,2),V(2,2),W(2,2);
00744 vnl_matrix<double> eigenvector(2,1);
00745
00746
00747 S_lambda.singular_value_decomposition(U,W,V);
00748
00749
00750 if ((W.get(0,0)<0.0) || (W.get(1,1)<0.0))
00751 {
00752 WARN << "numerical ill-conditioning in MergeLines";
00753 curves_->push_front(l1); curves_->push_front(l2);
00754 return;
00755 }
00756
00757 double cost;
00758 if ( W.get(0,0) < W.get(1,1) )
00759 {
00760 cost = W.get(0,0)/normaliser;
00761 eigenvector.put(0,0,U.get(0,0)); eigenvector.put(1,0,U.get(1,0));
00762 }
00763 else
00764 {
00765 cost = W.get(1,1)/normaliser;
00766 eigenvector.put(0,0,U.get(0,1)); eigenvector.put(1,0,U.get(1,1));
00767 }
00768
00769
00770 if ( cost >= threshold_ )
00771 {
00772 curves_->push_front(l1); curves_->push_front(l2);
00773 return;
00774 }
00775 else
00776 WARN << "Lines merged with a cost " << vcl_sqrt(cost) << vcl_endl;
00777
00778
00779 vec3 = - (1.0/S22) * S12.transpose() * eigenvector;
00780 double la,lb,lc;
00781 la = eigenvector.get(0,0); lb = eigenvector.get(1,0); lc = vec3(0,0);
00782 double m = vcl_sqrt(la*la+lb*lb);
00783
00784
00785 if ( lb < 0.0 )
00786 m *= -1.0;
00787 la /= m; lb /= m; lc /= m;
00788
00789
00790
00791
00792 double xa,ya,xb,yb;
00793 xa = lb*lb*x1[0] - la*lb*y1[0] - la*lc;
00794 ya = la*la*y1[0] - la*lb*x1[0] - lb*lc;
00795 xb = lb*lb*x2[1] - la*lb*y2[1] - la*lc;
00796 yb = la*la*y2[1] - la*lb*x2[1] - lb*lc;
00797
00798
00799
00800 float XA,YA,XB,YB;
00801 XA = xa*cp - ya*sp;
00802 YA = ya*cp + xa*sp;
00803 XB = xb*cp - yb*sp;
00804 YB = yb*cp + xb*sp;
00805
00806
00807 line = new ImplicitDigitalLine(l1->size()+l2->size(),
00808 new IUPoint(XA,YA,0.0),
00809 new IUPoint(XB,YB,0.0));
00810
00811 int i = 0;
00812 for (int j=0;j<l1->size();++i,++j) {
00813 line->SetX(l1->GetX(j),i);
00814 line->SetY(l1->GetY(j),i);
00815 line->SetGrad(l1->GetGrad(j),i);
00816 line->SetTheta(l1->GetTheta(j),i);
00817 }
00818 for (int j=0;j<l2->size();++i,++j) {
00819 line->SetX(l2->GetX(j),i);
00820 line->SetY(l2->GetY(j),i);
00821 line->SetGrad(l2->GetGrad(j),i);
00822 line->SetTheta(l2->GetTheta(j),i);
00823 }
00824
00825
00826 curves_->push_front(line);
00827
00828
00829
00830 osl_IUDelete(l1); osl_IUDelete(l2);
00831 #endif
00832 }
00833
00834
00835
00836
00837 float osl_fit_lines::MyGetCost(osl_OrthogRegress const *fitter,
00838 int start, int finish,
00839 osl_edgel_chain *dc)
00840 {
00841 double A = fitter->GetA();
00842 double B = fitter->GetB();
00843 double C = fitter->GetC();
00844
00845 float distance = 0;
00846
00847 for (int i = start; i < finish; i ++)
00848 distance += (float)vcl_fabs(A*dc->GetX(i) + B*dc->GetY(i) + C);
00849
00850 return distance / (finish - start);
00851 }