00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef TwoHalfDSketch_C_DEFINED
00039 #define TwoHalfDSketch_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/TwoHalfDSketch.H"
00042 #include "Image/DrawOps.H"
00043 #include "Image/MathOps.H"
00044 #include "Image/Kernels.H"
00045 #include "Image/FilterOps.H"
00046 #include "Image/Transforms.H"
00047 #include "Image/fancynorm.H"
00048 #include "Image/Convolutions.H"
00049 #include "Image/MatrixOps.H"
00050 #include "Simulation/SimEventQueue.H"
00051 #include "GUI/DebugWin.H"
00052 #include <math.h>
00053 #include <fcntl.h>
00054 #include <limits>
00055 #include <string>
00056
00057 const ModelOptionCateg MOC_TwoHalfDSketch = {
00058 MOC_SORTPRI_3, "TwoHalfDSketch-Related Options" };
00059
00060
00061 const ModelOptionDef OPT_TwoHalfDSketchShowDebug =
00062 { MODOPT_ARG(bool), "TwoHalfDSketchShowDebug", &MOC_TwoHalfDSketch, OPTEXP_CORE,
00063 "Show debug img",
00064 "twohalfdsketch-debug", '\0', "<true|false>", "false" };
00065
00066
00067 SIMMODULEINSTFUNC(TwoHalfDSketch);
00068
00069
00070
00071 TwoHalfDSketch::TwoHalfDSketch(OptionManager& mgr, const std::string& descrName,
00072 const std::string& tagName) :
00073 SimModule(mgr, descrName, tagName),
00074 SIMCALLBACK_INIT(SimEventV2Output),
00075 SIMCALLBACK_INIT(SimEventContoursOutput),
00076 SIMCALLBACK_INIT(SimEventSaveOutput),
00077 SIMCALLBACK_INIT(SimEventUserInput),
00078 itsShowDebug(&OPT_TwoHalfDSketchShowDebug, this),
00079 itsProposalThreshold(-1500),
00080 itsAcceptedThreshold(-50)
00081
00082 {
00083 itsCurrentProb = -1e10;
00084 itsCurrentIdx = 0;
00085 itsBiasMode = false;
00086 itsBias = -1;
00087 itsBiasId = -1;
00088
00089 initRandomNumbers();
00090
00091 itsUserProposal.e=0.8;
00092 itsUserProposal.a=10;
00093 itsUserProposal.b=11;
00094 itsUserProposal.k1=0;
00095 itsUserProposal.k2=0;
00096 itsUserProposal.rot = 0;
00097 itsUserProposal.pos = Point2D<float>(257, 141);
00098 itsUserProposal.start = -M_PI;
00099 itsUserProposal.end = M_PI;
00100 itsUserProposal.gibs=0;
00101
00102
00103 itsModel.addLine(Line(7, 71, 17, 88));
00104 itsModel.addLine(Line(19, 90, 27, 95));
00105 itsModel.addLine(Line(29, 95, 38, 91));
00106 itsModel.addLine(Line(39, 91, 55, 95));
00107 itsModel.addLine(Line(56, 95, 61, 93));
00108 itsModel.addLine(Line(62, 93, 74, 73));
00109 itsModel.addLine(Line(74, 72, 65, 62));
00110 itsModel.addLine(Line(65, 61, 63, 57));
00111 itsModel.addLine(Line(63, 56, 65, 42));
00112 itsModel.addLine(Line(66, 42, 71, 36));
00113 itsModel.addLine(Line(70, 35, 68, 33));
00114 itsModel.addLine(Line(67, 32, 53, 29));
00115 itsModel.addLine(Line(52, 30, 45, 32));
00116 itsModel.addLine(Line(44, 27, 56, 15));
00117 itsModel.addLine(Line(56, 14, 57, 7));
00118 itsModel.addLine(Line(56, 6, 53, 7));
00119 itsModel.addLine(Line(52, 7, 40, 19));
00120 itsModel.addLine(Line(40, 20, 42, 26));
00121 itsModel.addLine(Line(44, 33, 25, 29));
00122 itsModel.addLine(Line(24, 29, 17, 31));
00123 itsModel.addLine(Line(15, 32, 6, 43));
00124 itsModel.addLine(Line(5, 45, 5, 64));
00125 itsModel.addLine(Line(6, 65, 7, 70));
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 itsModel.setCOM();
00156 itsModel.quantize(60);
00157
00158 }
00159
00160
00161 TwoHalfDSketch::~TwoHalfDSketch()
00162 {
00163 }
00164
00165
00166 void TwoHalfDSketch::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e)
00167 {
00168
00169 LINFO("Got event --%s-- %ix%i key=%i",
00170 e->getWinName(),
00171 e->getMouseClick().i,
00172 e->getMouseClick().j,
00173 e->getKey());
00174
00175 if (strcmp(e->getWinName(), "TwoHalfDSketch"))
00176 return;
00177 SurfaceState& surface = itsUserProposal;
00178
00179 switch(e->getKey())
00180 {
00181 case 111:
00182 surface.pos.i -= 1;
00183 break;
00184 case 116:
00185 surface.pos.i += 1;
00186 break;
00187 case 113:
00188 surface.pos.j -= 1;
00189 break;
00190 case 114:
00191 surface.pos.j += 1;
00192 break;
00193 case 21:
00194 break;
00195 case 20:
00196 break;
00197 case 38:
00198 break;
00199 case 52:
00200 break;
00201 case 39:
00202 break;
00203 case 53:
00204 break;
00205 case 40:
00206 break;
00207 case 54:
00208 break;
00209 case 10:
00210 surface.a += 1.0;
00211 break;
00212 case 24:
00213 surface.a -= 1.0;
00214 break;
00215 case 11:
00216 surface.b += 1.0;
00217 break;
00218 case 25:
00219 surface.b -= 1.0;
00220 break;
00221 case 12:
00222 surface.e += 0.1;
00223 break;
00224 case 26:
00225 surface.e -= 0.1;
00226 break;
00227 case 13:
00228 surface.k1 += 0.1;
00229 break;
00230 case 27:
00231 surface.k1 -= 0.1;
00232 break;
00233 case 14:
00234 surface.k2 += 0.1;
00235 break;
00236 case 28:
00237 surface.k2 -= 0.1;
00238 break;
00239 case 15:
00240 surface.rot += 1*M_PI/180;
00241 break;
00242 case 29:
00243 surface.rot -= 1*M_PI/180;
00244 break;
00245 }
00246
00247 LINFO("Pos(%f,%f), param((%0.2f,%0.2f,%0.2f)",
00248 surface.pos.i, surface.pos.j,
00249 surface.a, surface.b, surface.e);
00250
00251
00252 evolve(q);
00253
00254 }
00255
00256
00257
00258 void TwoHalfDSketch::onSimEventV2Output(SimEventQueue& q, rutz::shared_ptr<SimEventV2Output>& e)
00259 {
00260
00261
00262
00263
00264
00265 itsLines = e->getLines();
00266 Dims dims = e->getDims();
00267
00268 itsLinesMag = Image<float>(dims, ZEROS);
00269 itsLinesOri = Image<float>(dims, NO_INIT);
00270 for(uint i=0; i<itsLinesOri.size(); i++)
00271 itsLinesOri[i] = NOTDEF;
00272
00273 std::vector<Line> lines;
00274 for(uint i=0; i<itsLines.size(); i++)
00275 {
00276 V2::LineSegment& ls = itsLines[i];
00277 drawLine(itsLinesMag, Point2D<int>(ls.p1), Point2D<int>(ls.p2), 255.0F);
00278 drawLine(itsLinesOri, Point2D<int>(ls.p1), Point2D<int>(ls.p2), ls.ori);
00279 lines.push_back(Line(ls.p1, ls.p2));
00280 }
00281
00282
00283 itsOriChamferMatcher.setLines(lines,
00284 60,
00285 5,
00286 itsLinesMag.getDims());
00287
00288 evolve(q);
00289
00290 }
00291
00292 void TwoHalfDSketch::onSimEventContoursOutput(SimEventQueue& q, rutz::shared_ptr<SimEventContoursOutput>& e)
00293 {
00294 LINFO("Contours output");
00295
00296 itsContours = e->getContours();
00297
00298 itsLinesMag = Image<float>(e->getImg().getDims(), ZEROS);
00299 itsLinesOri = Image<float>(e->getImg().getDims(), NO_INIT);
00300 for(uint i=0; i<itsLinesOri.size(); i++)
00301 itsLinesOri[i] = NOTDEF;
00302
00303 std::vector<Line> lines;
00304
00305 for(uint i=0; i<itsContours.size(); i++)
00306 {
00307 std::vector<Point2D<int> > polygon = approxPolyDP(itsContours[i].points, 2);
00308 for(uint j=0; j<polygon.size()-1; j++)
00309 {
00310 drawLine(itsLinesMag, polygon[j], polygon[(j+1)], 255.0F);
00311
00312 float ori = atan2(polygon[j].j-polygon[(j+1)].j, polygon[(j+1)].i - polygon[j].i);
00313 if (ori < 0) ori += M_PI;
00314 if (ori >= M_PI) ori -= M_PI;
00315 drawLine(itsLinesOri, polygon[j], polygon[(j+1)], ori);
00316
00317 lines.push_back(Line(polygon[j], polygon[(j+1)]));
00318 }
00319 }
00320
00321
00322 itsOriChamferMatcher.setLines(lines,
00323 60,
00324 0.5,
00325 itsLinesMag.getDims());
00326
00327 evolve(q);
00328
00329 }
00330
00331 double TwoHalfDSketch::getCost(OriChamferMatching& cm,
00332 Polygon& poly, Point2D<float> loc, bool biasMode)
00333 {
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 double totalProb = 0;
00350
00351
00352 for (uint i=0 ; i<poly.getNumLines(); i++)
00353 {
00354 Line l = poly.getLine(i);
00355 l.trans(loc);
00356
00357 Point2D<int> p1 = (Point2D<int>)l.getP1();
00358 Point2D<int> p2 = (Point2D<int>)l.getP2();
00359 double sum = cm.getCost(l.getDirectionIdx(), p1, p2);
00360
00361 double prob = exp(-sum/double(2*l.getLength()));
00362 if (sum < 0)
00363 {
00364 LINFO("Invalid sum %f", sum);
00365 prob = 0;
00366 }
00367 if (!biasMode)
00368 {
00369 if (prob < exp(-500/10))
00370 {
00371
00372
00373 }
00374 } else {
00375
00376 }
00377
00378 prob = pow(prob, 1-l.getWeight());
00379
00380
00381
00382
00383
00384 totalProb += log(prob);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 return totalProb;
00396 }
00397
00398
00399 double TwoHalfDSketch::calcNFA(Line& line)
00400 {
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 return 0;
00462 }
00463
00464
00465 float TwoHalfDSketch::inter_low(float x, float x1, float y1, float x2, float y2)
00466 {
00467 if( x1 > x2 || x < x1 || x > x2 )
00468 {
00469 LFATAL("inter_low: x %g x1 %g x2 %g.\n",x,x1,x2);
00470 LFATAL("Impossible situation.");
00471 }
00472 if( x1 == x2 && y1<y2 ) return y1;
00473 if( x1 == x2 && y1>y2 ) return y2;
00474 return y1 + (x-x1) * (y2-y1) / (x2-x1);
00475 }
00476
00477
00478 float TwoHalfDSketch::inter_hi(float x, float x1, float y1, float x2, float y2)
00479 {
00480 if( x1 > x2 || x < x1 || x > x2 )
00481 {
00482 LFATAL("inter_hi: x %g x1 %g x2 %g.\n",x,x1,x2);
00483 LFATAL("Impossible situation.");
00484 }
00485 if( x1 == x2 && y1<y2 ) return y2;
00486 if( x1 == x2 && y1>y2 ) return y1;
00487 return y1 + (x-x1) * (y2-y1) / (x2-x1);
00488 }
00489
00490
00491 void TwoHalfDSketch::ri_del(rect_iter * iter)
00492 {
00493 free(iter);
00494 }
00495
00496
00497 int TwoHalfDSketch::ri_end(rect_iter * i)
00498 {
00499 return (float)(i->x) > i->vx[2];
00500 }
00501
00502
00503 void TwoHalfDSketch::ri_inc(rect_iter * i)
00504 {
00505 if( (float) (i->x) <= i->vx[2] ) i->y++;
00506
00507 while( (float) (i->y) > i->ye && (float) (i->x) <= i->vx[2] )
00508 {
00509
00510 i->x++;
00511
00512 if( (float) (i->x) > i->vx[2] ) return;
00513
00514
00515 if( (float) i->x < i->vx[3] )
00516 i->ys = inter_low((float)i->x,i->vx[0],i->vy[0],i->vx[3],i->vy[3]);
00517 else i->ys = inter_low((float)i->x,i->vx[3],i->vy[3],i->vx[2],i->vy[2]);
00518
00519
00520 if( (float)i->x < i->vx[1] )
00521 i->ye = inter_hi((float)i->x,i->vx[0],i->vy[0],i->vx[1],i->vy[1]);
00522 else i->ye = inter_hi( (float)i->x,i->vx[1],i->vy[1],i->vx[2],i->vy[2]);
00523
00524
00525 i->y = (int)((float) ceil( (double) i->ys ));
00526 }
00527 }
00528
00529
00530 TwoHalfDSketch::rect_iter * TwoHalfDSketch::ri_ini(struct rect * r)
00531 {
00532 float vx[4],vy[4];
00533 int n,offset;
00534 rect_iter * i;
00535
00536 i = (rect_iter *) malloc(sizeof(rect_iter));
00537 if(!i) LFATAL("ri_ini: Not enough memory.");
00538
00539 vx[0] = r->x1 - r->dy * r->width / 2.0;
00540 vy[0] = r->y1 + r->dx * r->width / 2.0;
00541 vx[1] = r->x2 - r->dy * r->width / 2.0;
00542 vy[1] = r->y2 + r->dx * r->width / 2.0;
00543 vx[2] = r->x2 + r->dy * r->width / 2.0;
00544 vy[2] = r->y2 - r->dx * r->width / 2.0;
00545 vx[3] = r->x1 + r->dy * r->width / 2.0;
00546 vy[3] = r->y1 - r->dx * r->width / 2.0;
00547
00548 if( r->x1 < r->x2 && r->y1 <= r->y2 ) offset = 0;
00549 else if( r->x1 >= r->x2 && r->y1 < r->y2 ) offset = 1;
00550 else if( r->x1 > r->x2 && r->y1 >= r->y2 ) offset = 2;
00551 else offset = 3;
00552
00553
00554 for(n=0; n<4; n++)
00555 {
00556 i->vx[n] = vx[(offset+n)%4];
00557 i->vy[n] = vy[(offset+n)%4];
00558 }
00559
00560 #define BIG_NUMBER 1.0e+300
00561
00562
00563 i->x = (int)(ceil( (double) (i->vx[0]) ) - 1);
00564 i->y = (int)(ceil( (double) (i->vy[0]) ));
00565 i->ys = i->ye = -BIG_NUMBER;
00566
00567
00568 ri_inc(i);
00569
00570 return i;
00571 }
00572
00573
00574
00575 int TwoHalfDSketch::isaligned(Point2D<int> loc, Image<float>& angles, float theta, float prec)
00576 {
00577 float a = angles.getVal(loc);
00578
00579 printf("IsAligned %f %f %f ", a*180/M_PI, theta*180/M_PI, prec*180/M_PI);
00580 if( a == NOTDEF ) return false;
00581
00582
00583 theta -= a;
00584 if( theta < 0.0 ) theta = -theta;
00585 if( theta > M_3_2_PI )
00586 {
00587 theta -= M_2__PI;
00588 if( theta < 0.0 ) theta = -theta;
00589 }
00590
00591 printf(" %f < %f \n", theta*180/M_PI, prec*180/M_PI);
00592 return theta < prec;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 double TwoHalfDSketch::log_gamma_lanczos(double x)
00621 {
00622 static double q[7] = { 75122.6331530, 80916.6278952, 36308.2951477,
00623 8687.24529705, 1168.92649479, 83.8676043424,
00624 2.50662827511 };
00625 double a = (x+0.5) * log(x+5.5) - (x+5.5);
00626 double b = 0.0;
00627 int n;
00628
00629 for(n=0;n<7;n++)
00630 {
00631 a -= log( x + (double) n );
00632 b += q[n] * pow( x, (double) n );
00633 }
00634 return a + log(b);
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 double TwoHalfDSketch::log_gamma_windschitl(double x)
00653 {
00654 return 0.918938533204673 + (x-0.5)*log(x) - x
00655 + 0.5*x*log( x*sinh(1/x) + 1/(810.0*pow(x,6.0)) );
00656 }
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679 double TwoHalfDSketch::nfa(int n, int k, double p, double logNT)
00680 {
00681 static double inv[TABSIZE];
00682 double tolerance = 0.1;
00683 double log1term,term,bin_term,mult_term,bin_tail,err;
00684 double p_term = p / (1.0-p);
00685 int i;
00686
00687 if( n<0 || k<0 || k>n || p<0.0 || p>1.0 )
00688 LFATAL("Wrong n, k or p values in nfa()");
00689
00690 if( n==0 || k==0 ) return -logNT;
00691 if( n==k ) return -logNT - (double) n * log10(p);
00692
00693 log1term = log_gamma((double)n+1.0) - log_gamma((double)k+1.0)
00694 - log_gamma((double)(n-k)+1.0)
00695 + (double) k * log(p) + (double) (n-k) * log(1.0-p);
00696
00697 term = exp(log1term);
00698 if( term == 0.0 )
00699 {
00700 if( (double) k > (double) n * p )
00701 return -log1term / M_LN10 - logNT;
00702 else
00703 return -logNT;
00704 }
00705
00706 bin_tail = term;
00707 for(i=k+1;i<=n;i++)
00708 {
00709 bin_term = (double) (n-i+1) * ( i<TABSIZE ?
00710 ( inv[i] == 0.0 ? inv[i] : (inv[i]=1.0/(double)i))
00711 : 1.0/(double)i );
00712 mult_term = bin_term * p_term;
00713 term *= mult_term;
00714 bin_tail += term;
00715 if(bin_term<1.0)
00716 {
00717
00718
00719
00720
00721 err = term * ( ( 1.0 - pow( mult_term, (double) (n-i+1) ) ) /
00722 (1.0-mult_term) - 1.0 );
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732 if( err < tolerance * fabs(-log10(bin_tail)-logNT) * bin_tail ) break;
00733 }
00734 }
00735 return -log10(bin_tail) - logNT;
00736 }
00737
00738
00739
00740
00741
00742 void TwoHalfDSketch::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00743 {
00744 if (itsShowDebug.getVal())
00745 {
00746
00747
00748 nub::ref<FrameOstream> ofs =
00749 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00750 Layout<PixRGB<byte> > disp = getDebugImage(q);
00751 if (disp.initialized())
00752 ofs->writeRgbLayout(disp, "TwoHalfDSketch", FrameInfo("TwoHalfDSketch", SRC_POS));
00753 }
00754 }
00755
00756
00757
00758 void TwoHalfDSketch::evolve(SimEventQueue& q)
00759 {
00760
00761 if (!itsBiasMode)
00762 {
00763 Image<SurfaceState> surfaces = proposeSurfaces(false);
00764
00765 itsProposals.clear();
00766 for(uint i=0; i<50; i++)
00767 {
00768 Point2D<int> maxLoc; SurfaceState maxSurface;
00769 findMax(surfaces, maxLoc, maxSurface);
00770
00771 if (maxSurface.prob == INVALID_PROB)
00772 break;
00773
00774 itsProposals.push_back(maxSurface);
00775
00776
00777 double radius = maxSurface.polygon.getRadius()*0.75;
00778 drawDisk(surfaces, maxLoc, (int)radius);
00779 }
00780 } else {
00781 optimizePolygon(itsProposals[itsBiasId]);
00782 LINFO("Optimized match %f\n", itsProposals[itsBiasId].prob);
00783 }
00784
00785 printResults(itsBias);
00786
00787
00788
00789 itsSurfaces.clear();
00790 for(uint i=0; i<itsProposals.size(); i++)
00791 {
00792 if (itsProposals[i].prob > itsAcceptedThreshold)
00793 itsSurfaces.push_back(itsProposals[i]);
00794 }
00795
00796
00797
00798
00799
00800 if (itsSurfaces.size() > 0)
00801 q.post(rutz::make_shared(new SimEventTwoHalfDSketchOutput(this, itsSurfaces)));
00802
00803 if (itsProposals.size() > 0 && !itsBiasMode)
00804 {
00805 itsBiasMode = true;
00806 LINFO("Biasing");
00807
00808 for(float bias=0; bias<0.30; bias += 0.10)
00809 {
00810 for(uint sid=0; sid<itsProposals.size(); sid++)
00811 {
00812 itsBias = bias;
00813 itsBiasId = sid;
00814 std::vector<V1::SpatialBias> v1Bias;
00815
00816 Polygon& polygon = itsProposals[sid].polygon;
00817 for(uint j=0; j<polygon.getNumLines(); j++)
00818 {
00819 Line l = itsProposals[sid].getLine(j);
00820
00821 Point2D<int> p1 = (Point2D<int>)l.getP1();
00822 Point2D<int> p2 = (Point2D<int>)l.getP2();
00823
00824 Point2D<int> bP1 = p1;
00825 Point2D<int> bP2 = (p1+p2)/2;
00826 Point2D<int> bP3 = (p1+bP2)/2;
00827 Point2D<int> bP4 = (p2+bP2)/2;
00828
00829
00830 {
00831 V1::SpatialBias sb;
00832 sb.loc = bP1;
00833 sb.threshold = bias ;
00834 sb.dims = Dims(15,15);
00835 v1Bias.push_back(sb);
00836 }
00837
00838 {
00839 V1::SpatialBias sb;
00840 sb.loc = bP2;
00841 sb.threshold = bias ;
00842 sb.dims = Dims(15,15);
00843 v1Bias.push_back(sb);
00844 }
00845
00846 {
00847 V1::SpatialBias sb;
00848 sb.loc = bP3;
00849 sb.threshold = bias ;
00850 sb.dims = Dims(15,15);
00851 v1Bias.push_back(sb);
00852 }
00853
00854 {
00855 V1::SpatialBias sb;
00856 sb.loc = bP4;
00857 sb.threshold = bias ;
00858 sb.dims = Dims(15,15);
00859 v1Bias.push_back(sb);
00860 }
00861 }
00862 LINFO("Bias %f for %i\n", itsBias, sid);
00863 q.post(rutz::make_shared(new SimEventV1Bias(this, v1Bias)));
00864 }
00865
00866 }
00867 }
00868
00869 }
00870
00871
00872 Image<float> TwoHalfDSketch::getSurfaceProbImage(Image<SurfaceState>& surfaceState)
00873 {
00874
00875 Image<float> probImg(surfaceState.getDims(), NO_INIT);
00876 for(uint i=0; i<probImg.size(); i++)
00877 {
00878 if (surfaceState[i].prob < -1000)
00879 probImg[i] = 0;
00880 else
00881 probImg[i] = surfaceState[i].prob;
00882 }
00883
00884 return probImg;
00885 }
00886
00887 void TwoHalfDSketch::optimizePolygon(TwoHalfDSketch::SurfaceState& surfaceState)
00888 {
00889
00890 float matchingScale = 1;
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900 double maxProb = getCost(itsOriChamferMatcher, surfaceState.polygon,surfaceState.pos, true);
00901 if (maxProb > -200 || maxProb < -400)
00902 {
00903 surfaceState.prob = maxProb;
00904 return;
00905 }
00906 LINFO("Optimize Polygon %f", maxProb);
00907
00908 for(float aspectx = surfaceState.aspect.i; aspectx < surfaceState.aspect.i+0.5; aspectx +=0.2)
00909 {
00910 for(float aspecty = surfaceState.aspect.j; aspecty < surfaceState.aspect.j+0.5; aspecty +=0.2)
00911 {
00912 LINFO("Aspectx %f %f", aspectx, aspecty);
00913 if (aspectx <= 0.5 || aspecty <= 0.5)
00914 continue;
00915 for(double scale = surfaceState.scale-0.2 ; scale< surfaceState.scale+0.2 ; scale += 0.01)
00916 {
00917 for(float rot = surfaceState.rot-5 ; rot< surfaceState.rot+5 ; rot+= 1)
00918 {
00919 Polygon model = surfaceState.polygon;
00920
00921
00922 model.rotate(rot*M_PI/180.0);
00923 model.scale(scale*matchingScale*aspectx, scale*matchingScale*aspecty);
00924
00925 model.setWeights();
00926
00927 for (int x=surfaceState.pos.i-5 ; x<surfaceState.pos.i+5; x++)
00928 {
00929 for (int y=surfaceState.pos.j-5 ; y<surfaceState.pos.j+5; y++)
00930 {
00931 double prob = getCost(itsOriChamferMatcher, model,Point2D<float>(x,y), true);
00932
00933 if (prob>maxProb)
00934 {
00935 maxProb = prob;
00936 surfaceState.pos = Point2D<float>(x,y);
00937 surfaceState.aspect = Point2D<float>(aspectx, aspecty);
00938 surfaceState.scale = scale;
00939 surfaceState.rot = rot;
00940 surfaceState.prob = prob;
00941 surfaceState.polygon = model;
00942 surfaceState.matchingScale = matchingScale;
00943 }
00944 }
00945 }
00946 }
00947 }
00948 }
00949
00950 }
00951 }
00952
00953
00954 Image<TwoHalfDSketch::SurfaceState> TwoHalfDSketch::proposeSurfaces(bool biasMode)
00955 {
00956
00957 LINFO("Propose surfaces");
00958
00959 float matchingScale = 1;
00960
00961 Image<SurfaceState> surfacesImg(itsLinesMag.getDims(), NO_INIT);
00962
00963
00964
00965
00966
00967
00968
00969 for(int aspectx = 0; aspectx < 4; aspectx++)
00970 {
00971 for(int aspecty = 0; aspecty < 4; aspecty++)
00972 {
00973 for(double scale = 0.2 ; scale< 6.0 ; scale+= 0.1)
00974 {
00975 float rot = 0;
00976
00977 {
00978 Polygon model = itsModel;
00979 double ax = pow(1.1, aspectx);
00980 double ay = pow(1.1, aspecty);
00981 LINFO("Rot %f Scale %f aspect %f %f\n", rot, scale, ax, ay);
00982
00983 model.rotate(rot*M_PI/180.0);
00984 model.scale(scale*matchingScale*ax, scale*matchingScale*ay);
00985
00986 model.setWeights();
00987
00988 double minx, miny, maxx, maxy;
00989 model.getBoundary(minx, miny, maxx, maxy);
00990
00991 int width = surfacesImg.getWidth();
00992 int height = surfacesImg.getHeight();
00993
00994
00995
00996 for (int x=-(int)(minx-4) ; x<width-((int)maxx+4) ; x += 4)
00997 {
00998 for (int y=-(int)(miny-4); y<height-((int)maxy+4); y += 4)
00999 {
01000
01001 double prob = getCost(itsOriChamferMatcher, model,Point2D<float>(x,y), biasMode);
01002
01003 if (prob>itsProposalThreshold)
01004 {
01005 if (surfacesImg.coordsOk(x,y))
01006 if (prob > surfacesImg.getVal(x,y).prob)
01007 {
01008 SurfaceState ss;
01009 ss.pos = Point2D<float>(x,y);
01010 ss.aspect = Point2D<float>(ax, ay);
01011 ss.scale = scale;
01012 ss.rot = rot;
01013 ss.prob = prob;
01014 ss.polygon = model;
01015 ss.matchingScale = matchingScale;
01016 surfacesImg.setVal(x,y, ss);
01017
01018 }
01019 }
01020 }
01021 }
01022 }
01023 }
01024
01025 }
01026
01027 }
01028
01029 return surfacesImg;
01030 }
01031
01032 void TwoHalfDSketch::calcSurfaceLikelihood(SurfaceState& surface)
01033 {
01034 Image<float> edges;
01035 Image<float> lumSurface;
01036 double edgeProb = calcSurfaceEdgeLikelihood(surface, edges, lumSurface);
01037
01038 surface.prob = edgeProb;
01039 }
01040
01041 double TwoHalfDSketch::calcSurfaceLumLikelihood(SurfaceState& surface, Image<float>& edges, Image<float>& surfaceLum)
01042 {
01043
01044 for(uint i=0; i<surfaceLum.size(); i++)
01045 if (edges[i] > 0)
01046 surfaceLum[i] = 0;
01047
01048 return getSurfaceLumProb(itsEdgesDT,surfaceLum);
01049
01050 }
01051
01052 double TwoHalfDSketch::getSurfaceLumProb(Image<float>& data, Image<float>& model)
01053 {
01054
01055 double prob = 0;
01056 int pixCount = 0;
01057
01058 for(int y=0; y < model.getHeight(); y++)
01059 for(int x=0; x < model.getWidth(); x++)
01060 if (model.getVal(x,y) > 0)
01061 {
01062 prob += (10-data.getVal(x,y));
01063 pixCount++;
01064 }
01065 prob /= (10*pixCount);
01066
01067 return exp(-prob);
01068 }
01069
01070
01071
01072
01073
01074 double TwoHalfDSketch::calcSurfaceEdgeLikelihood(SurfaceState& surface, Image<float>& edges, Image<float>& surfaceLum)
01075 {
01076 int pixCount = 0;
01077 double prob = 0;
01078
01079 if (surface.polygon.getNumLines() > 0)
01080 {
01081
01082 for(uint j=0; j<surface.polygon.getNumLines(); j++)
01083 {
01084 Point2D<int> p1;
01085 Point2D<int> p2;
01086
01087
01088 float ori = atan2(p1.j-p2.j, p2.i - p1.i);
01089 if (ori < 0) ori += M_PI;
01090 if (ori >= M_PI) ori -= M_PI;
01091
01092 prob += getLineProb(p1, p2, ori, pixCount);
01093
01094
01095
01096 }
01097 pixCount *= 2;
01098
01099 } else {
01100
01101 float nSeg = 20;
01102 const float dTheta = 2*M_PI / (float)nSeg;
01103
01104 float a = surface.a;
01105 float b = surface.b;
01106 float e = surface.e;
01107 float k1 = surface.k1;
01108 float k2 = surface.k2;
01109 float rot = surface.rot;
01110
01111 Point2D<float> p = surface.pos;
01112
01113 for (float theta=surface.start; theta < surface.end; theta += dTheta)
01114 {
01115 Point2D<float> p1 = ellipsoid(a,b, e, theta);
01116 Point2D<float> p2 = ellipsoid(a,b, e, theta + dTheta);
01117
01118 Point2D<float> tmpPos1;
01119 Point2D<float> tmpPos2;
01120
01121
01122 tmpPos1.i = p1.i + p1.j*k1;
01123 tmpPos1.j = p1.i*k2 + p1.j;
01124
01125 tmpPos2.i = p2.i + p2.j*k1;
01126 tmpPos2.j = p2.i*k2 + p2.j;
01127
01128
01129 p1.i = (cos(rot)*tmpPos1.i - sin(rot)*tmpPos1.j) + p.i;
01130 p1.j = (sin(rot)*tmpPos1.i + cos(rot)*tmpPos1.j) + p.j;
01131
01132 p2.i = (cos(rot)*tmpPos2.i - sin(rot)*tmpPos2.j) + p.i;
01133 p2.j = (sin(rot)*tmpPos2.i + cos(rot)*tmpPos2.j) + p.j;
01134
01135
01136 Point2D<float> center = (p1 + p2)/2;
01137 float ori = atan2(p1.j-p2.j, p2.i - p1.i);
01138 if (ori < 0) ori += M_PI;
01139 if (ori >= M_PI) ori -= M_PI;
01140
01141 prob += getEdgeProb(Point2D<int>(p1), ori);
01142 prob += getEdgeProb(Point2D<int>(center), ori);
01143 pixCount += 2;
01144 }
01145 pixCount *= 1;
01146 }
01147
01148
01149
01150
01151 return exp(-prob/ double(pixCount))*2;
01152
01153
01154
01155 }
01156
01157 double TwoHalfDSketch::getEdgeProb(Point2D<int> loc, float ori)
01158 {
01159
01160 int numOfEntries = itsOriEdgesDT.size();
01161
01162 double lambda = (1/6)*M_PI/180;
01163
01164 double D = M_PI/numOfEntries;
01165 int oriIdx = (int)floor(ori/D);
01166
01167 float minDist = 10000;
01168 if (itsOriEdgesDT[0].coordsOk(loc))
01169 {
01170 for(int i=0; i<numOfEntries; i++)
01171 {
01172 float v1 = itsOriEdgesDT[i].getVal(loc) + lambda*angDiff(oriIdx*D, i*D);
01173 if (v1 < minDist)
01174 minDist = v1;
01175 }
01176 }
01177
01178 return minDist;
01179 }
01180
01181 double TwoHalfDSketch::getLineProb(Point2D<int> p1, Point2D<int> p2, float ori, int& pixCount)
01182 {
01183
01184 int numOfEntries = itsOriEdgesDT.size();
01185
01186 double lambda = (1/2)*M_PI/180;
01187
01188 double D = M_PI/numOfEntries;
01189 int oriIdx = (int)floor(ori/D);
01190
01191 int dx = p2.i - p1.i, ax = abs(dx) << 1, sx = signOf(dx);
01192 int dy = p2.j - p1.j, ay = abs(dy) << 1, sy = signOf(dy);
01193 int x = p1.i, y = p1.j;
01194
01195 double prob = 0;
01196 int wSize = 1;
01197 if (ax > ay)
01198 {
01199 int d = ay - (ax >> 1);
01200 for (;;)
01201 {
01202
01203 for(int yy = y-wSize; yy < y+wSize; yy++)
01204 for(int xx = x-wSize; xx < x+wSize; xx++)
01205 {
01206 float minDist = 10000;
01207 if (itsOriEdgesDT[0].coordsOk(xx,yy))
01208 {
01209 for(int i=0; i<numOfEntries; i++)
01210 {
01211 float v1 = itsOriEdgesDT[i].getVal(xx,yy) + lambda*angDiff(oriIdx*D, i*D);
01212 if (v1 < minDist)
01213 minDist = v1;
01214 }
01215 }
01216 prob += minDist;
01217 pixCount++;
01218 }
01219
01220 if (x == p2.i) return prob;
01221 if (d >= 0) { y += sy; d -= ax; }
01222 x += sx; d += ay;
01223 }
01224 } else {
01225 int d = ax - (ay >> 1);
01226 for (;;)
01227 {
01228 for(int yy = y-wSize; yy < y+wSize; yy++)
01229 for(int xx = x-wSize; xx < x+wSize; xx++)
01230 {
01231 float minDist = 10000;
01232 if (itsOriEdgesDT[0].coordsOk(xx,yy))
01233 {
01234 for(int i=0; i<numOfEntries; i++)
01235 {
01236 float v1 = itsOriEdgesDT[i].getVal(xx,yy) + lambda*angDiff(oriIdx*D, i*D);
01237 if (v1 < minDist)
01238 minDist = v1;
01239 }
01240 }
01241 prob += minDist;
01242 pixCount++;
01243 }
01244 if (y == p2.j) return prob;
01245
01246 if (d >= 0) { x += sx; d -= ay; }
01247 y += sy; d += ax;
01248 }
01249 }
01250
01251 return prob;
01252
01253 }
01254
01255
01256 void TwoHalfDSketch::printResults(float bias)
01257 {
01258 for(uint i=0; i<itsProposals.size(); i++)
01259 {
01260 Rectangle bb = itsProposals[i].getBB();
01261
01262 if (i == (uint)itsBiasId)
01263 bias = itsBias;
01264 else
01265 bias = -1;
01266
01267 printf("Result: %i %i %f %i %i %i %i %f %f %f\n",
01268 i, (uint)itsBiasId,
01269 bias,
01270 bb.topLeft().i,
01271 bb.topLeft().j,
01272 bb.bottomRight().i,
01273 bb.bottomRight().j,
01274 itsProposals[i].prob,
01275 itsProposals[i].pos.i,
01276 itsProposals[i].pos.j
01277
01278 );
01279 }
01280
01281 }
01282
01283
01284 Layout<PixRGB<byte> > TwoHalfDSketch::getDebugImage(SimEventQueue& q)
01285 {
01286 Layout<PixRGB<byte> > outDisp;
01287
01288 Image<float> input = itsLinesMag;
01289 inplaceNormalize(input, 0.0F, 255.0F);
01290
01291 Image<PixRGB<byte> > worldFrame = input;
01292 for(uint i=0; i<itsSurfaces.size(); i++)
01293 {
01294 if (itsSurfaces[i].polygon.getNumLines()> 0)
01295 {
01296 Polygon& polygon = itsSurfaces[i].polygon;
01297
01298 for(uint j=0; j<polygon.getNumLines(); j++)
01299 {
01300 Line l = itsProposals[i].getLine(j);
01301 Point2D<int> p1 = (Point2D<int>)l.getP1();
01302 Point2D<int> p2 = (Point2D<int>)l.getP2();
01303 drawLine(worldFrame, p1, p2, PixRGB<byte>(0,255,0));
01304 }
01305
01306 } else {
01307 drawSuperquadric(worldFrame,
01308 Point2D<int>(itsSurfaces[i].pos),
01309 itsSurfaces[i].a, itsSurfaces[i].b, itsSurfaces[i].e,
01310 PixRGB<byte>(0,255,0),
01311 itsSurfaces[i].rot, itsSurfaces[i].k1, itsSurfaces[i].k2,
01312 itsSurfaces[i].start,itsSurfaces[i].end);
01313 }
01314
01315
01316
01317
01318
01319
01320 }
01321
01322 Image<PixRGB<byte> > proposalsFrame = input;
01323 float maxProb = -100000;
01324 for(uint i=0; i<itsProposals.size(); i++)
01325 {
01326 LINFO("Propsal %i p:%fx%f s:%f a:%fx%f r:%f p:%f", i,
01327 itsProposals[i].pos.i, itsProposals[i].pos.j,
01328 itsProposals[i].scale,
01329 itsProposals[i].aspect.i, itsProposals[i].aspect.j,
01330 itsProposals[i].rot,
01331 itsProposals[i].prob);
01332
01333 {
01334 if (itsProposals[i].prob > maxProb)
01335 maxProb = itsProposals[i].prob;
01336
01337 if (itsProposals[i].polygon.getNumLines() > 0)
01338 {
01339 Polygon& polygon = itsProposals[i].polygon;
01340
01341 for(uint j=0; j<polygon.getNumLines(); j++)
01342 {
01343 Line l = itsProposals[i].getLine(j);
01344 Point2D<int> p1 = (Point2D<int>)l.getP1();
01345 Point2D<int> p2 = (Point2D<int>)l.getP2();
01346 drawLine(proposalsFrame, p1,p2, PixRGB<byte>(255,0,0));
01347 }
01348 } else {
01349
01350 float nSeg = 20;
01351 const float dTheta = 2*M_PI / (float)nSeg;
01352
01353 float a = itsProposals[i].a;
01354 float b = itsProposals[i].b;
01355 float e = itsProposals[i].e;
01356 float k1 = itsProposals[i].k1;
01357 float k2 = itsProposals[i].k2;
01358 float rot = itsProposals[i].rot;
01359 float start = itsProposals[i].start;
01360 float end = itsProposals[i].end;
01361
01362 Point2D<float> p = itsProposals[i].pos;
01363
01364 for (float theta=start; theta < end; theta += dTheta)
01365 {
01366 Point2D<float> p1 = ellipsoid(a,b, e, theta);
01367 Point2D<float> tmpPos;
01368
01369
01370 tmpPos.i = p1.i + p1.j*k1;
01371 tmpPos.j = p1.i*k2 + p1.j;
01372
01373
01374 p1.i = (cos(rot)*tmpPos.i - sin(rot)*tmpPos.j) + p.i;
01375 p1.j = (sin(rot)*tmpPos.i + cos(rot)*tmpPos.j) + p.j;
01376
01377 drawCircle(proposalsFrame, (Point2D<int>)p1, 3, PixRGB<byte>(255,0,0));
01378 }
01379 }
01380
01381 char msg[255];
01382 sprintf(msg, "%0.2f", itsProposals[i].prob);
01383 writeText(proposalsFrame, (Point2D<int>)itsProposals[i].getPos(), msg,
01384 PixRGB<byte>(255,255,255),
01385 PixRGB<byte>(0,0,0));
01386 }
01387
01388 }
01389 char msg[255];
01390 sprintf(msg, "Max: %0.2f", maxProb);
01391 writeText(proposalsFrame, Point2D<int>(0,proposalsFrame.getHeight()-20), msg,
01392 PixRGB<byte>(255,255,255),
01393 PixRGB<byte>(0,0,0));
01394
01395
01396 outDisp = proposalsFrame;
01397 outDisp = hcat(outDisp, worldFrame);
01398
01399 return outDisp;
01400
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410 #endif
01411