00001
00002
00003
00004
00005
00006
00007
00008 #include "BoxSpecialist.h"
00009 #include "Tools/ColorClasses.h"
00010 #include "Tools/Location.h"
00011
00012 BoxSpecialist::SegmentInfo::SegmentInfo():
00013 lmValiditySkyblue(0),
00014 lmValidityYellow(0),
00015 goalValidity(0),
00016 pink(0),
00017 yellow(0),
00018 skyblue(0){
00019 }
00020
00021 BoxSpecialist::BoxSpecialist(RasterImageProcessor &processor,RasterStrategy &strat):
00022 RasterSpecialist(processor),edgeScanner(processor) {
00023
00024 strategy = &strat;
00025 preScanNeeded = true;
00026 postScanNeeded = false;
00027
00028
00029 InBinaryFile stream1(getLocation().getFilename("flag.thr"));
00030
00031 if(stream1.exists()) stream1 >> flagThreshold;
00032 else flagThreshold = 20;
00033
00034 InBinaryFile stream2(getLocation().getFilename("goal.thr"));
00035
00036 if(stream2.exists()) stream2 >> goalThreshold;
00037 else goalThreshold = 25;
00038
00039
00040 OUTPUT(idText,text,"goal-thr: " << goalThreshold);
00041 OUTPUT(idText,text,"flag-thr: " << flagThreshold);
00042
00043 }
00044
00045
00046 BoxSpecialist::~BoxSpecialist(){}
00047
00048
00049 int BoxSpecialist::getType() {
00050 return __RBoxSpecialist;
00051 }
00052
00053 void BoxSpecialist::init() {
00054 segments_img.clear();
00055 infos_img.clear();
00056 lst_pts.clear();
00057 bottomPoints.clear();
00058
00059 edgeScanner.threshold = 17;
00060 }
00061
00062
00063 void BoxSpecialist::createBBox() {
00064
00065 SVector::iterator sit;
00066 list<LinePair>::iterator l_it;
00067
00068 double dist, p_dist;
00069
00070
00071 for (sit = segments_img.begin();sit != segments_img.end();sit++){
00072 if (sit->size() < 2) continue;
00073
00074
00075 Geometry::Line top,bottom,left,right;
00076 Vector2<int> minHor,maxHor,minPHor,maxPHor;
00077 SegmentInfo si;
00078 double min_dist = 20000, max_dist = -20000, min_p_dist = 20000, max_p_dist = -20000;
00079
00080 for (l_it = sit->begin();l_it!=sit->end();++l_it) {
00081
00082 dist = getDistanceToLine(horizon,l_it->v1);
00083 p_dist = getDistanceToLine(pHorizon,l_it->v1);
00084
00085 if (dist < min_dist) {
00086 min_dist = dist;
00087 minHor = l_it->v1;
00088
00089 }
00090 if (dist > max_dist) {
00091 max_dist = dist;
00092 maxHor = l_it->v1;
00093 }
00094
00095 if (p_dist < min_p_dist) {
00096 min_p_dist = p_dist;
00097 minPHor = l_it->v1;
00098 }
00099 if (p_dist > max_p_dist) {
00100 max_p_dist = p_dist;
00101 maxPHor = l_it->v1;
00102
00103 }
00104
00105 dist = getDistanceToLine(horizon,l_it->v2);
00106 p_dist = getDistanceToLine(pHorizon,l_it->v2);
00107
00108 if (dist < min_dist) {
00109 min_dist = dist;
00110 minHor = l_it->v2;
00111
00112 }
00113 if (dist > max_dist) {
00114 max_dist = dist;
00115 maxHor = l_it->v2;
00116 }
00117
00118 if (p_dist < min_p_dist) {
00119 min_p_dist = p_dist;
00120 minPHor = l_it->v2;
00121 }
00122 if (p_dist > max_p_dist) {
00123 max_p_dist = p_dist;
00124 maxPHor = l_it->v2;
00125 }
00126 }
00127 top.base = Vector2<double>(
00128 (double)maxHor.x,
00129 (double)maxHor.y);
00130 top.direction = horizon.direction;
00131
00132 bottom.base = Vector2<double>(
00133 (double)minHor.x,
00134 (double)minHor.y);
00135 bottom.direction = horizon.direction;
00136
00137 left.base = Vector2<double>(
00138 (double)minPHor.x,
00139 (double)minPHor.y);
00140 left.direction = pHorizon.direction;
00141
00142 right.base = Vector2<double>(
00143 (double)maxPHor.x,
00144 (double)maxPHor.y);
00145 right.direction = pHorizon.direction;
00146
00147 Geometry::getIntersectionOfLines(top,left,si.rect.upperLeft);
00148 Geometry::getIntersectionOfLines(top,right,si.rect.upperRight);
00149 Geometry::getIntersectionOfLines(bottom,left,si.rect.bottomLeft);
00150 Geometry::getIntersectionOfLines(bottom,right,si.rect.bottomRight);
00151 si.rect.center = (si.rect.upperLeft + si.rect.bottomRight)/2;
00152 si.size = sit->size();
00153 si.segment = &(*sit);
00154
00155 countColors(si,*(si.segment));
00156 si.bottomColor = getColor(minHor.x,minHor.y);
00157 si.topColor = getColor(maxHor.x,maxHor.y);
00158 createValidities(si);
00159 infos_img.push_back(si);
00160 }
00161 }
00162
00163
00164
00165 void BoxSpecialist::invokeOnPreScan(int x, int y){
00166
00167 Vector2 <int> cur_pt(x,y);
00168
00169 if (!strategy->insideBox) left_border = cur_pt;
00170 else {
00171 LinePair lp(left_border,cur_pt);
00172 lp.color = getColor(lp.v1.x,lp.v1.y);
00173
00174
00175 edgeScanner.scanWest(lp.v1.x,lp.v2.y);
00176 edgeScanner.scanEast(lp.v2.x,lp.v2.y);
00177
00178 if ((lp.v2.x-lp.v1.x)>1) {
00179 lst_pts.push_back(lp);
00180
00181 LINE(imageProcessor_general,
00182 lp.v1.x,lp.v1.y,
00183 lp.v2.x,lp.v2.y,
00184 0.5, Drawings::ps_solid, Drawings::red);
00185
00186 }
00187 }
00188 }
00189
00190 bool BoxSpecialist::missingData(bool ulc, bool urc, bool brc, bool blc, int i) {
00191 if (ulc && urc) return segments_img[i].size() >5;
00192 else if (blc && brc) return segments_img[i].size() >5;
00193
00194 return false;
00195 }
00196
00197 bool BoxSpecialist::searchGoal(BoxSpecialist::SegmentInfo& goal) {
00198 int i = 0;
00199
00200 if ((goal.pink != 0) || (goal.yellow != 0) && (goal.skyblue != 0)) return false;
00201 if (!(goal.yellow > 20 || goal.skyblue > 20)) return false;
00202
00203 double centerDistance = fabs(Geometry::getDistanceToLine(horizon,goal.rect.center));
00204 double colorCount = goal.yellow + goal.skyblue;
00205
00206 if (centerDistance/colorCount > 2) return false;
00207 bool ownTeamColorIsBlue = getPlayer().getTeamColor() == Player::blue;
00208 bool opponentGoal = false;
00209 colorClass goalColor = (goal.yellow > goal.skyblue)? yellow : skyblue;
00210
00211 if (ownTeamColorIsBlue){
00212 if(goalColor == yellow) opponentGoal = true;
00213 else opponentGoal = false;
00214 }
00215 else if (goalColor == skyblue) opponentGoal = true;
00216
00217
00218 Vector2<double> south = pHorizon.direction;
00219 Vector2<double> north(-pHorizon.direction.x,-pHorizon.direction.y);
00220 Vector2<double> east = horizon.direction;
00221 Vector2<double> west(-horizon.direction.x,-horizon.direction.y);
00222
00223 int const cols = 12;
00224 int const rows = 8;
00225
00226 vector<Vector2<int> > tops(cols);
00227 vector<Vector2<int> > bottoms(cols);
00228 vector<Vector2<int> > lefts(rows);
00229 vector<Vector2<int> > rights(rows);
00230
00231
00232
00233
00234 bool bottomOnBorder = true;
00235 bool topOnBorder = true;
00236 bool leftOnBorder = true;
00237 bool rightOnBorder = true;
00238
00239 Vector2<double> step = (goal.rect.upperRight - goal.rect.upperLeft)/(cols+2);
00240 Vector2<double> vert = (goal.rect.upperRight - goal.rect.bottomRight)/(rows+2);
00241
00242
00243
00244
00245 if (step.abs() < 1) return false;
00246 if (vert.abs() < 1) return false;
00247
00248 for (i = 0;i<cols;i++){
00249 Vector2<double> top = goal.rect.upperLeft + (step*(i+1)) - vert;
00250 Vector2<double> bottom = goal.rect.bottomLeft + (step*(i+1)) + vert;
00251 tops[i].x = (int)(top.x+0.5);
00252 tops[i].y = (int)(top.y+0.5);
00253 bottoms[i].x = (int)(bottom.x + 0.5);
00254 bottoms[i].y = (int)(bottom.y + 0.5);
00255 if (edgeScanner.scan(bottoms[i].x,bottoms[i].y,south)) bottomOnBorder = false;
00256 if (edgeScanner.scan(tops[i].x,tops[i].y,north)) topOnBorder = false;
00257
00258 DOT(imageProcessor_flagsAndGoals, tops[i].x, tops[i].y,
00259 Drawings::white, Drawings::red);
00260 DOT(imageProcessor_flagsAndGoals, bottoms[i].x, bottoms[i].y,
00261 Drawings::white, Drawings::red);
00262 }
00263
00264 for (i = 0;i<rows;i++){
00265 Vector2<double> left = goal.rect.bottomLeft + step + (vert*(i+1));
00266 Vector2<double> right = goal.rect.bottomRight - step + (vert*(i+1));
00267 lefts[i].x = (int)(left.x + 0.5);
00268 lefts[i].y = (int)(left.y + 0.5);
00269 rights[i].x = (int)(right.x + 0.5);
00270 rights[i].y = (int)(right.y + 0.5);
00271 if(edgeScanner.scan(lefts[i].x,lefts[i].y,west)) leftOnBorder = false;
00272 if(edgeScanner.scan(rights[i].x,rights[i].y,east)) rightOnBorder = false;
00273
00274 DOT(imageProcessor_flagsAndGoals, lefts[i].x, lefts[i].y,
00275 Drawings::white, Drawings::blue);
00276 DOT(imageProcessor_flagsAndGoals, rights[i].x, rights[i].y,
00277 Drawings::white, Drawings::blue);
00278 }
00279
00280
00281 Geometry::Line top;
00282 Geometry::Line bottom;
00283 Geometry::Line left;
00284 Geometry::Line right;
00285 Geometry::Line t1;
00286 Geometry::Line t2;
00287 int r1;
00288 int r2;
00289 float best1;
00290 float best2;
00291 float dist1;
00292 float dist2;
00293
00294 for(i=0;i<10;i++){
00295 r1 = rand()%cols;
00296 do r2 = rand()%cols; while (r1==r2);
00297 t1.base.x += bottoms[r1].x;
00298 t1.base.y += bottoms[r1].y;
00299 t2.base.x += tops[r1].x;
00300 t2.base.y += tops[r1].y;
00301 t1.direction.x = t1.base.x - bottoms[r2].x;
00302 t1.direction.y = t1.base.y - bottoms[r2].y;
00303 t2.direction.x = t1.base.x - tops[r2].x;
00304 t2.direction.y = t1.base.y - tops[r2].y;
00305
00306 dist1 = 0;
00307 dist2 = 0;
00308 best1 = 1000;
00309 best2 = 1000;
00310
00311 for(int j=0;j<cols;j++){
00312 dist1 += getDistanceToLine(t1,bottoms[j]);
00313 dist2 += getDistanceToLine(t2,tops[j]);
00314 }
00315 dist1 = fabs(dist1);
00316 dist2 = fabs(dist2);
00317
00318 if (dist1 < best1){
00319 best1 = dist1;
00320 bottom = t1;
00321 }
00322
00323 if (dist2 < best2){
00324 best2 = dist2;
00325 top = t2;
00326 }
00327 }
00328
00329 t1.direction = pHorizon.direction;
00330 t2.direction = pHorizon.direction;
00331
00332 for(i = 0;i<10;i++){
00333 r1 = rand()%rows;
00334 do r2 = rand()%rows; while (r1==r2);
00335 right.base.x += rights[r1].x;
00336 right.base.y += rights[r1].y;
00337 left.base.x += lefts[r1].x;
00338 left.base.y += lefts[r1].y;
00339 t1.direction.x = t1.base.x - bottoms[r2].x;
00340 t1.direction.y = t1.base.y - bottoms[r2].y;
00341 t2.direction.x = t1.base.x - tops[r2].x;
00342 t2.direction.y = t1.base.y - tops[r2].y;
00343
00344 dist1 = 0;
00345 dist2 = 0;
00346 best1 = 1000;
00347 best2 = 1000;
00348
00349 for(int j=0;j<rows;j++){
00350 dist1 += getDistanceToLine(t1,rights[j]);
00351 dist2 += getDistanceToLine(t2,lefts[j]);
00352 }
00353 dist1 = fabs(dist1);
00354 dist2 = fabs(dist2);
00355
00356 if (dist1 < best1){
00357 best1 = dist1;
00358 bottom = t1;
00359 }
00360 if (dist2 < best2){
00361 best2 = dist2;
00362 top = t2;
00363 }
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373 Rectangle& r = goal.rect;
00374
00375
00376 Geometry::getIntersectionOfLines(bottom,left,goal.rect.bottomLeft);
00377 Geometry::getIntersectionOfLines(bottom,right,goal.rect.bottomRight);
00378 Geometry::getIntersectionOfLines(top,left,goal.rect.upperLeft);
00379 Geometry::getIntersectionOfLines(top,right,goal.rect.upperRight);
00380 goal.rect.center = (goal.rect.upperLeft + goal.rect.bottomRight)/2;
00381
00382 double size = (goal.rect.bottomLeft - goal.rect.bottomRight).abs();
00383 size*= (goal.rect.bottomLeft - goal.rect.bottomRight).abs();
00384
00385 if ( !(size > 100 && Geometry::getDistanceToLine(horizon, goal.rect.center) < 25)
00386 || Geometry::getDistanceToLine(horizon, goal.rect.center) < -10 )
00387 return false;
00388
00389 RasterSpecialist::Box b(1,1,imageWidth-2,imageWidth-2);
00390 bool ulc = !b.inside((int)r.upperLeft.x,(int)r.upperLeft.y);
00391 bool urc = !b.inside((int)r.upperRight.x,(int)r.upperRight.y);
00392 bool brc = !b.inside((int)r.bottomRight.x,(int)r.bottomRight.y);
00393 bool blc = !b.inside((int)r.bottomLeft.x,(int)r.bottomLeft.y);
00394
00395 ConditionalBoundary bound;
00396
00397
00398
00399
00400
00401
00402
00403
00404 Vector2<double> a[4];
00405 Vector2<double> leftCenter = (r.upperLeft + r. bottomLeft)/2;
00406 Vector2<double> rightCenter = (r.upperRight + r. bottomRight)/2;
00407 Vector2<double> bottomCenter = (r.bottomRight + r. bottomLeft)/2;
00408 Vector2<double> topCenter = (r.upperRight + r. upperLeft)/2;
00409
00410 calculateAnglesForPoint(leftCenter,rip->cameraMatrix,rip->image.cameraInfo,a[0]);
00411 calculateAnglesForPoint(rightCenter,rip->cameraMatrix,rip->image.cameraInfo,a[1]);
00412 calculateAnglesForPoint(bottomCenter,rip->cameraMatrix,rip->image.cameraInfo,a[2]);
00413 calculateAnglesForPoint(topCenter,rip->cameraMatrix,rip->image.cameraInfo,a[3]);
00414
00415 bound.addX(a[0].x,blc);
00416 bound.addX(a[1].x,brc);
00417 bound.addX(a[2].x,ulc);
00418 bound.addX(a[3].x,urc);
00419
00420 bound.addY(a[0].y,blc);
00421 bound.addY(a[1].y,brc);
00422 bound.addY(a[2].y,ulc);
00423 bound.addY(a[3].y,urc);
00424
00425 rip->landmarksPercept.addGoal(goalColor, ownTeamColorIsBlue, bound);
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 goal.goalValidity = 1;
00444
00445 LINE(imageProcessor_flagsAndGoals,
00446 goal.rect.upperLeft.x,goal.rect.upperLeft.y,
00447 goal.rect.upperRight.x,goal.rect.upperRight.y,
00448 1.5, Drawings::ps_solid, Drawings::white);
00449
00450 LINE(imageProcessor_flagsAndGoals,
00451 goal.rect.bottomLeft.x,goal.rect.bottomLeft.y,
00452 goal.rect.bottomRight.x,goal.rect.bottomRight.y,
00453 1.5, Drawings::ps_solid, Drawings::white);
00454
00455 LINE(imageProcessor_flagsAndGoals,
00456 goal.rect.upperLeft.x,goal.rect.upperLeft.y,
00457 goal.rect.bottomLeft.x,goal.rect.bottomLeft.y,
00458 1.5, Drawings::ps_solid, Drawings::white);
00459
00460 LINE(imageProcessor_flagsAndGoals,
00461 goal.rect.upperRight.x,goal.rect.upperRight.y,
00462 goal.rect.bottomRight.x,goal.rect.bottomRight.y,
00463 1.5, Drawings::ps_solid, Drawings::white);
00464
00465 return true;
00466
00467 }
00468
00469 bool BoxSpecialist::searchLandmark(BoxSpecialist::SegmentInfo& flag){
00470
00471
00472 if (flag.pink == 0) return false;
00473 if (flag.yellow == 0 && flag.skyblue == 0) return false;
00474 Vector2<double> south = pHorizon.direction;
00475 Vector2<double> north(-pHorizon.direction.x,-pHorizon.direction.y);
00476 Vector2<double> east = horizon.direction;
00477 Vector2<double> west(-horizon.direction.x,-horizon.direction.y);
00478 Rectangle &r = flag.rect;
00479 bool bottomOnBorder = false;
00480 bool topOnBorder = false;
00481
00482 Vector2<int> borderCenter;
00483 Vector2<int> center((int)(r.center.x + 0.5),(int)(r.center.y + 0.5));
00484 Vector2<int> bottomCenter = center;
00485 Vector2<int> topCenter = center;
00486
00487 DOT(imageProcessor_flagsAndGoals, center.x, center.y,
00488 Drawings::black, Drawings::white);
00489
00490 colorClass col = noColor;
00491 colorClass bottomColor = noColor;
00492 colorClass topColor = noColor;
00493
00494 DOT(imageProcessor_flagsAndGoals, bottomCenter.x, bottomCenter.y,
00495 Drawings::red, Drawings::black);
00496 DOT(imageProcessor_flagsAndGoals, topCenter.x, topCenter.y,
00497 Drawings::green, Drawings::black);
00498
00499 int& bx = bottomCenter.x;
00500 int& by = bottomCenter.y;
00501
00502 double space = (r.bottomLeft-r.upperLeft).abs()/4;
00503
00504 if (space<3) space = 3;
00505
00506 while (!bottomOnBorder){
00507 bottomOnBorder = !edgeScanner.scan(bx,by,south);
00508 if(abs(center.x - bx) < space && abs(center.y - by) < space)
00509 edgeScanner.skip(bx,by);
00510 else break;
00511 }
00512
00513 int& tx = topCenter.x;
00514 int& ty = topCenter.y;
00515
00516 while (!topOnBorder){
00517 topOnBorder = !edgeScanner.scan(tx,ty,north);
00518 if(abs(center.x - tx) < space && abs(center.y - ty) < space)
00519 edgeScanner.skip(tx,ty);
00520 else break;
00521 }
00522 Vector2<int> quarter = (topCenter - bottomCenter)/4;
00523 if (quarter.abs() < 1) return false;
00524 Vector2<int> topStart(topCenter.x - quarter.x,topCenter.y - quarter.y);
00525 Vector2<int> bottomStart(bottomCenter.x + quarter.x,bottomCenter.y + quarter.y);
00526 bool found = false;
00527
00528
00529
00530 Vector2<int> scan = topStart;
00531 edgeScanner.setDirection(west);
00532 while(edgeScanner.colorScan(scan.x,scan.y,west,col)){
00533 if (col == pink || col == yellow || col == skyblue){
00534 topColor = col;
00535 found = true;
00536 break;
00537 }
00538 edgeScanner.skip(scan.x,scan.y);
00539 if ((scan - topStart).abs() > 10) break;
00540 }
00541 if (!found){
00542
00543 col = noColor;
00544 scan = topStart;
00545
00546 while(edgeScanner.colorScan(scan.x,scan.y,east,col)){
00547 if (col == pink || col == yellow || col == skyblue){
00548 topColor = col;
00549 found = true;
00550 break;
00551 }
00552 edgeScanner.skip(scan.x,scan.y);
00553 if ((scan - topStart).abs() > 10) break;
00554 }
00555 }
00556 if (!found) return false;
00557 else found = false;
00558
00559
00560 scan = bottomStart;
00561 while(edgeScanner.colorScan(scan.x,scan.y,west,col)){
00562 if (col == pink || col == yellow || col == skyblue){
00563 bottomColor = col;
00564 found = true;
00565 break;
00566 }
00567 edgeScanner.skip(scan.x,scan.y);
00568 if ((scan - bottomStart).abs() > 10) break;
00569 }
00570 if (!found){
00571
00572 col = noColor;
00573 scan = bottomStart;
00574
00575 while(edgeScanner.colorScan(scan.x,scan.y,east,col)){
00576 if (col == pink || col == yellow || col == skyblue){
00577 bottomColor = col;
00578 found = true;
00579 break;
00580 }
00581 edgeScanner.skip(scan.x,scan.y);
00582 if ((scan - bottomStart).abs() > 10) break;
00583 }
00584 }
00585 if (!found) return false;
00586
00587 Flag::FlagType ft= Flag::numberOfFlagTypes;
00588 if (topColor == pink) {
00589 switch (bottomColor) {
00590 case yellow :
00591 ft = Flag::pinkAboveYellow;
00592 break;
00593 case skyblue :
00594 ft = Flag::pinkAboveSkyblue;
00595 break;
00596 default : break;
00597 }
00598 }
00599 else if(bottomColor == pink){
00600 switch (topColor) {
00601 case skyblue :
00602 ft = Flag::skyblueAbovePink;
00603 break;
00604 case yellow :
00605 ft = Flag::yellowAbovePink;
00606 break;
00607 default : break;
00608 }
00609 }
00610
00611
00612
00613 DOT(imageProcessor_flagsAndGoals, bottomStart.x, bottomStart.y,
00614 Drawings::red, Drawings::black);
00615
00616 DOT(imageProcessor_flagsAndGoals, topStart.x, topStart.y,
00617 Drawings::green, Drawings::black);
00618
00619 Vector2<int> left1,left2,right1,right2;
00620
00621 scan = topStart;
00622
00623 edgeScanner.setDirection(west);
00624 edgeScanner.scan(scan.x,scan.y);
00625 left1 = scan;
00626 DOT(imageProcessor_flagsAndGoals, scan.x, scan.y,
00627 Drawings::green, Drawings::blue);
00628
00629 scan = topStart;
00630
00631 edgeScanner.setDirection(east);
00632 edgeScanner.scan(scan.x,scan.y);
00633 right1 = scan;
00634 DOT(imageProcessor_flagsAndGoals, scan.x, scan.y,
00635 Drawings::green, Drawings::blue);
00636
00637 scan = bottomStart;
00638
00639 edgeScanner.setDirection(west);
00640 edgeScanner.scan(scan.x,scan.y);
00641 left2 = scan;
00642 DOT(imageProcessor_flagsAndGoals, scan.x, scan.y,
00643 Drawings::green, Drawings::blue);
00644
00645 scan = bottomStart;
00646 right2 = scan;
00647 edgeScanner.setDirection(east);
00648 edgeScanner.scan(scan.x,scan.y);
00649
00650 DOT(imageProcessor_flagsAndGoals, scan.x, scan.y,
00651 Drawings::green, Drawings::blue);
00652
00653
00654
00655
00656 Vector2<double> left = (r.bottomLeft + r.upperLeft)/2;
00657 Vector2<double> right = (r.bottomRight + r.upperRight)/2;
00658 Vector2<double> top(topCenter.x,topCenter.y);
00659 Vector2<double> bottom(bottomCenter.x,bottomCenter.y);
00660 center = (bottomCenter + topCenter)/2;
00661
00662 DOT(imageProcessor_flagsAndGoals, bottomCenter.x, bottomCenter.y,
00663 Drawings::red, Drawings::black);
00664
00665 DOT(imageProcessor_flagsAndGoals, topCenter.x, topCenter.y,
00666 Drawings::green, Drawings::black);
00667
00668 DOT(imageProcessor_flagsAndGoals, right.x, right.y,
00669 Drawings::red, Drawings::black);
00670
00671 DOT(imageProcessor_flagsAndGoals, left.x, left.y,
00672 Drawings::green, Drawings::black);
00673
00674 rip->addFlag(left,right,top,bottom,ft);
00675 return true;
00676 }
00677
00678 void BoxSpecialist::fitLandmark(BoxSpecialist::SegmentInfo &flag){
00679 Vector2<double> south = pHorizon.direction;
00680 Vector2<double> north(-pHorizon.direction.x,-pHorizon.direction.y);
00681 Vector2<double> east = horizon.direction;
00682 Vector2<double> west(-horizon.direction.x,-horizon.direction.y);
00683
00684 Rectangle& r = flag.rect;
00685 bool bottomOnBorder = false;
00686 bool topOnBorder = false;
00687
00688 Vector2<int> center((int)(r.center.x + 0.5),(int)(r.center.y + 0.5));
00689 Vector2<int> bottomCenter = center;
00690 Vector2<int> topCenter = center;
00691
00692 DOT(imageProcessor_flagsAndGoals, center.x, center.y,
00693 Drawings::black, Drawings::white);
00694
00695 DOT(imageProcessor_flagsAndGoals, bottomCenter.x, bottomCenter.y,
00696 Drawings::red, Drawings::black);
00697 DOT(imageProcessor_flagsAndGoals, topCenter.x, topCenter.y,
00698 Drawings::green, Drawings::black);
00699
00700 int& bx = bottomCenter.x;
00701 int& by = bottomCenter.y;
00702
00703 double space = (r.bottomLeft-r.upperLeft).abs()/4;
00704
00705 if (space<3) space = 3;
00706
00707 while (!bottomOnBorder){
00708 bottomOnBorder = !edgeScanner.scan(bx,by,south);
00709 if(abs(center.x - bx) < space && abs(center.y - by) < space)
00710 edgeScanner.skip(bx,by);
00711 else break;
00712 }
00713
00714 int& tx = topCenter.x;
00715 int& ty = topCenter.y;
00716
00717 while (!topOnBorder){
00718 topOnBorder = !edgeScanner.scan(tx,ty,north);
00719 if(abs(center.x - tx) < space && abs(center.y - ty) < space)
00720 edgeScanner.skip(tx,ty);
00721 else break;
00722 }
00723
00724
00725
00726
00727 }
00728
00729 void BoxSpecialist::invokeOnPostScan(int x,int y) {
00730
00731 bottomPoints.push_back(Vector2<int>(x,y));
00732 }
00733
00734 void BoxSpecialist::executePostProcessing() {
00735
00736 if (lst_pts.size() < 2) return;
00737
00738 int allowedXSpace = 2;
00739 int allowedYSpace = 4;
00740
00741 horizon = rip->getHorizon();
00742
00743 pHorizon.base = horizon.base;
00744 pHorizon.direction = horizon.direction;
00745 pHorizon.direction.rotateLeft();
00746
00747 createSegmentsFromLines2(lst_pts,segments_img,allowedXSpace,allowedYSpace);
00748
00749 sort<SVector::iterator>(segments_img.begin(),segments_img.end(),ListSizeOrder());
00750 createBBox();
00751 int size = infos_img.size();
00752
00753 if (size == 0) return;
00754
00755 edgeScanner.threshold = goalThreshold;
00756
00757 vector<SegmentInfo>::iterator it = infos_img.end();
00758 int goalParts = 0;
00759 do{
00760 it--;
00761 if (searchGoal(*it)) goalParts++;
00762 if (goalParts == 1) break;
00763 }while(it != infos_img.begin());
00764
00765
00766
00767 edgeScanner.threshold = flagThreshold;
00768
00769
00770 it = infos_img.end();
00771 int foundLM = 0;
00772 do{
00773 it--;
00774 if (searchLandmark(*it)){
00775 foundLM++;
00776 }
00777 if (foundLM == 2) break;
00778 }while(it != infos_img.begin());
00779 Vector2<double> cameraOffset(
00780 rip->cameraMatrix.translation.x,
00781 rip->cameraMatrix.translation.y);
00782
00783 if (foundLM>0) rip->landmarksPercept.estimateOffsetForFlags(cameraOffset);
00784 if (goalParts>0){
00785
00786
00787 rip->landmarksPercept.estimateOffsetForGoals(cameraOffset);
00788 };
00789
00790 for(it = infos_img.begin();it!= infos_img.end();++it) {
00791
00792 LINE(imageProcessor_general,
00793 it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.upperRight.x,it->rect.upperRight.y,
00794 0.6, Drawings::ps_solid, Drawings::white);
00795 LINE(imageProcessor_general,
00796 it->rect.bottomLeft.x,it->rect.bottomLeft.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00797 0.6, Drawings::ps_solid, Drawings::green);
00798 LINE(imageProcessor_general,
00799 it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.bottomLeft.x,it->rect.bottomLeft.y,
00800 0.6, Drawings::ps_solid, Drawings::yellow);
00801 LINE(imageProcessor_general,
00802 it->rect.upperRight.x,it->rect.upperRight.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00803 0.6, Drawings::ps_solid, Drawings::blue);
00804 }
00805
00806
00807 }
00808
00809 void BoxSpecialist::mergeBoxes(BoxSpecialist::SegmentInfo& seg1,BoxSpecialist::SegmentInfo& seg2){
00810 Geometry::Line top,bottom,left,right;
00811
00812
00813
00814 if (Geometry::getDistanceToLine(horizon,seg1.rect.upperLeft) <
00815 Geometry::getDistanceToLine(horizon,seg2.rect.upperLeft))
00816 seg1.rect.upperLeft = seg2.rect.upperLeft;
00817
00818 if (Geometry::getDistanceToLine(horizon,seg1.rect.bottomRight) >
00819 Geometry::getDistanceToLine(horizon,seg2.rect.bottomRight))
00820 seg1.rect.bottomRight = seg2.rect.bottomRight;
00821
00822 if (Geometry::getDistanceToLine(pHorizon,seg1.rect.upperRight) <
00823 Geometry::getDistanceToLine(pHorizon,seg2.rect.upperRight))
00824 seg1.rect.upperRight = seg2.rect.upperRight;
00825
00826 if (Geometry::getDistanceToLine(pHorizon,seg1.rect.bottomLeft) >
00827 Geometry::getDistanceToLine(pHorizon,seg2.rect.bottomLeft))
00828 seg1.rect.bottomLeft = seg2.rect.bottomLeft;
00829
00830 top.direction = horizon.direction;
00831 bottom.direction = horizon.direction;
00832 left.direction = pHorizon.direction;
00833 right.direction = pHorizon.direction;
00834
00835 top.base = seg1.rect.upperLeft;
00836 bottom.base = seg1.rect.bottomRight;
00837 right.base = seg1.rect.upperRight;
00838 left.base = seg1.rect.bottomLeft;
00839
00840 Geometry::getIntersectionOfLines(bottom,left,seg1.rect.bottomLeft);
00841 Geometry::getIntersectionOfLines(top,left,seg1.rect.upperLeft);
00842 Geometry::getIntersectionOfLines(bottom,right,seg1.rect.bottomRight);
00843 Geometry::getIntersectionOfLines(top,right,seg1.rect.upperRight);
00844 seg1.rect.center = (seg1.rect.upperLeft + seg1.rect.bottomRight)/2;
00845 seg1.size += seg2.pink;
00846 seg1.pink += seg2.pink;
00847 seg1.yellow += seg2.yellow;
00848 seg1.skyblue += seg2.skyblue;
00849 }
00850
00851 void BoxSpecialist::countColors(BoxSpecialist::SegmentInfo& si, list<LinePair>& segment){
00852 list<LinePair>::iterator lines;
00853 si.pink = 0;
00854 si.yellow =0;
00855 si.skyblue = 0;
00856 for(lines = segment.begin();lines != segment.end();++lines){
00857 LinePair& line = *lines;
00858 switch(line.color){
00859 case pink:
00860 si.pink += line.v2.x - line.v1.x;
00861 break;
00862 case yellow:
00863 si.yellow += line.v2.x - line.v1.x;
00864 break;
00865 case skyblue:
00866 si.skyblue += line.v2.x - line.v1.x;
00867 break;
00868
00869 }
00870 }
00871
00872 int max = 0;
00873 int min = 0;
00874 si.pink > si.skyblue? max = si.pink : max = si.skyblue;
00875 if (si.yellow > max) max = si.yellow;
00876
00877 min = max/8;
00878
00879 if (si.pink < min) si.pink = 0;
00880 if (si.yellow < min) si.yellow = 0;
00881 if (si.skyblue < min) si.skyblue = 0;
00882 }
00883
00884
00885 void BoxSpecialist::fusionGoal(){
00886
00887
00888 vector<SegmentInfo>::iterator it;
00889
00890 it = infos_img.begin();
00891
00892 SegmentInfo& greatest = infos_img.back();
00893
00894 int pos = infos_img.size()-1;
00895
00896 if ((greatest.pink != 0) || (greatest.yellow != 0) && (greatest.skyblue != 0)) return;
00897
00898 double radius = (greatest.rect.center - greatest.rect.bottomRight).abs();
00899
00900 colorClass goalColor = greatest.yellow != 0 ? yellow : skyblue;
00901 searchGoal(greatest);
00902
00903
00904
00905 for(++it;it != infos_img.end();++it){
00906 SegmentInfo& si = *it;
00907 if (si.pink > 0) continue;
00908 colorClass curColor = si.yellow > si.skyblue ? yellow : skyblue;
00909 if (curColor != goalColor) continue;
00910
00911
00912 double curRadius = (si.rect.center - si.rect.bottomRight).abs() + 4 ;
00913 if ((si.rect.center - greatest.rect.center).abs() > curRadius + radius) continue;
00914 if (fabs(Geometry::getDistanceToLine(horizon,si.rect.center)) > 20)continue;
00915 mergeBoxes(greatest,si);
00916 si.goalValidity = 1;
00917 }
00918
00919 if (!((greatest.yellow > 90 || greatest.skyblue > 90) && Geometry::getDistanceToLine(horizon, greatest.rect.center) < 20)) return;
00920
00921 Rectangle& r = greatest.rect;
00922 RasterSpecialist::Box b(1,1,imageWidth-2,imageWidth-2);
00923 bool ulc = b.inside((int)r.upperLeft.x,(int)r.upperLeft.y);
00924 bool urc = b.inside((int)r.upperRight.x,(int)r.upperRight.y);
00925 bool brc = b.inside((int)r.bottomRight.x,(int)r.bottomRight.y);
00926 bool blc = b.inside((int)r.bottomLeft.x,(int)r.bottomLeft.y);
00927
00928 if (missingData(ulc, urc, brc, blc,pos)) return;
00929
00930 ConditionalBoundary bound;
00931 bool ownTeamColorIsBlue = getPlayer().getTeamColor() == Player::blue;
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 Vector2<double> a[4];
00942 calculateAnglesForPoint(r.bottomLeft,rip->cameraMatrix,rip->image.cameraInfo,a[0]);
00943 calculateAnglesForPoint(r.bottomRight,rip->cameraMatrix,rip->image.cameraInfo,a[1]);
00944 calculateAnglesForPoint(r.upperLeft,rip->cameraMatrix,rip->image.cameraInfo,a[2]);
00945 calculateAnglesForPoint(r.upperRight,rip->cameraMatrix,rip->image.cameraInfo,a[3]);
00946
00947 bound.addX(a[0].x,blc);
00948 bound.addX(a[1].x,brc);
00949 bound.addX(a[2].x,ulc);
00950 bound.addX(a[3].x,urc);
00951
00952 bound.addY(a[0].y,blc);
00953 bound.addY(a[1].y,brc);
00954 bound.addY(a[2].y,ulc);
00955 bound.addY(a[3].y,urc);
00956
00957 rip->landmarksPercept.addGoal(greatest.bottomColor, ownTeamColorIsBlue, bound);
00958
00959
00960
00961
00962
00963
00964 greatest.goalValidity = 1;
00965
00966 LINE(imageProcessor_flagsAndGoals,
00967 greatest.rect.upperLeft.x,greatest.rect.upperLeft.y,
00968 greatest.rect.upperRight.x,greatest.rect.upperRight.y,
00969 1.5, Drawings::ps_solid, Drawings::white);
00970
00971 LINE(imageProcessor_flagsAndGoals,
00972 greatest.rect.bottomLeft.x,greatest.rect.bottomLeft.y,
00973 greatest.rect.bottomRight.x,greatest.rect.bottomRight.y,
00974 1.5, Drawings::ps_solid, Drawings::white);
00975
00976 LINE(imageProcessor_flagsAndGoals,
00977 greatest.rect.upperLeft.x,greatest.rect.upperLeft.y,
00978 greatest.rect.bottomLeft.x,greatest.rect.bottomLeft.y,
00979 1.5, Drawings::ps_solid, Drawings::white);
00980
00981 LINE(imageProcessor_flagsAndGoals,
00982 greatest.rect.upperRight.x,greatest.rect.upperRight.y,
00983 greatest.rect.bottomRight.x,greatest.rect.bottomRight.y,
00984 1.5, Drawings::ps_solid, Drawings::white);
00985
00986 }
00987
00988 void BoxSpecialist::calculateAnglesForPoint
00989 (
00990 const Vector2<double>& point,
00991 const CameraMatrix& cameraMatrix,
00992 const CameraInfo& cameraInfo,
00993 Vector2<double>& angles
00994 )
00995 {
00996 double factor = ((double)cameraInfo.resolutionWidth / 2.0) / tan(cameraInfo.openingAngleWidth / 2.0);
00997
00998 Vector3<double> vectorToPoint(
00999 factor,
01000 cameraInfo.resolutionWidth / 2 - point.x,
01001 cameraInfo.resolutionHeight / 2 - point.y);
01002
01003 Vector3<double> vectorToPointWorld =
01004 cameraMatrix.rotation * vectorToPoint;
01005
01006 angles.x =
01007 atan2(vectorToPointWorld.y,vectorToPointWorld.x);
01008
01009 angles.y =
01010 atan2(
01011 vectorToPointWorld.z,
01012 sqrt(sqr(vectorToPointWorld.x) + sqr(vectorToPointWorld.y))
01013 );
01014 }
01015
01016 bool BoxSpecialist::calculatePointOnField
01017 (
01018 const double x,
01019 const double y,
01020 const CameraMatrix& cameraMatrix,
01021 const CameraInfo& cameraInfo,
01022 Vector2<int>& pointOnField
01023 )
01024 {
01025 #ifndef _WIN32 // don't recalculate on real robot
01026 static
01027 #endif
01028 double xFactor = tan(cameraInfo.openingAngleWidth / 2) / (cameraInfo.resolutionWidth / 2),
01029 yFactor = tan(cameraInfo.openingAngleHeight / 2) / (cameraInfo.resolutionHeight / 2);
01030
01031 Vector3<double>
01032 vectorToCenter(1, (cameraInfo.resolutionWidth / 2 - 0.5 - x) * xFactor, (cameraInfo.resolutionHeight / 2 - 0.5 - y) * yFactor);
01033 Vector3<double>
01034 vectorToCenterWorld = cameraMatrix.rotation * vectorToCenter;
01035
01036
01037 if(vectorToCenterWorld.z > -5 * yFactor) return false;
01038
01039 double a1 = cameraMatrix.translation.x,
01040 a2 = cameraMatrix.translation.y,
01041 a3 = cameraMatrix.translation.z,
01042 b1 = vectorToCenterWorld.x,
01043 b2 = vectorToCenterWorld.y,
01044 b3 = vectorToCenterWorld.z;
01045
01046 pointOnField.x = int((a1 * b3 - a3 * b1) / b3 + 0.5);
01047 pointOnField.y = int((a2 * b3 - a3 * b2) / b3 + 0.5);
01048
01049 return abs(pointOnField.x) < 10000 && abs(pointOnField.y) < 10000;
01050 }
01051
01052 void BoxSpecialist::createValidities(BoxSpecialist::SegmentInfo& info){
01053
01054 if (info.pink== 0 || info.yellow == 0) info.lmValidityYellow = 0;
01055 else info.lmValidityYellow = 1- 2 * (fabs((double) info.yellow/(double)(info.yellow + info.pink) - 0.5) );
01056
01057 if (info.pink== 0 || info.skyblue == 0) info.lmValiditySkyblue = 0;
01058 else info.lmValiditySkyblue = 1- 2 * (fabs((double) info.skyblue/(double)(info.skyblue + info.pink) - 0.5) );
01059 }
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 void BoxSpecialist::detectFreePartOfGoal(){
01109 vector<Vector2<int> >::iterator it = bottomPoints.begin();
01110 vector<Vector2<int> >::iterator lit = it;
01111 vector<Vector2<int> >::iterator last = it;
01112
01113 vector<Vector2<int> >::iterator leftBorder = it;
01114 vector<Vector2<int> >::iterator rightBorder = it;
01115
01116 int maxRange = 0;
01117 int clipRange = 5;
01118 int currentRange = 0;
01119
01120 for(it++;it!=bottomPoints.end();it++){
01121 if ((*last - *it).abs() > clipRange){
01122 currentRange = (*last - *lit).abs();
01123 if (currentRange > maxRange){
01124 leftBorder = lit;
01125 rightBorder = last;
01126 maxRange = currentRange;
01127 }
01128 lit = it;
01129 }
01130 }
01131
01132
01133 if (leftBorder==rightBorder)return;
01134
01135 Vector2<double> leftAngle,rightAngle;
01136
01137 LINE(imageProcessor_flagsAndGoals,
01138 leftBorder->x,leftBorder->y,
01139 rightBorder->x,rightBorder->y,
01140 2, Drawings::ps_solid, Drawings::green);
01141
01142 Geometry::calculateAnglesForPoint(
01143 *leftBorder,rip->cameraMatrix,rip->image.cameraInfo,leftAngle);
01144 Geometry::calculateAnglesForPoint(
01145 *rightBorder,rip->cameraMatrix,rip->image.cameraInfo,rightAngle);
01146
01147 Vector2<double> angles;
01148 Geometry::calculateAnglesForPoint(
01149 Vector2<int>(rip->image.cameraInfo.resolutionWidth / 2, rip->image.cameraInfo.resolutionHeight / 2),
01150 rip->cameraMatrix, rip->image.cameraInfo, angles);
01151
01152 Pose2D camera(angles.x, Vector2<double>(
01153 rip->cameraMatrix.translation.x,
01154 rip->cameraMatrix.translation.y));
01155
01156 Vector2<double> middleAngle = (leftAngle + rightAngle)/2;
01157
01158 double midDir = atan2(middleAngle.x,middleAngle.y);
01159 Vector2<double> first2 = (camera + Pose2D(leftAngle)).translation,
01160 last2 = (camera + Pose2D(rightAngle)).translation;
01161
01162 rip->obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::opponentGoal] = true;
01163 rip->obstaclesPercept.angleToFreePartOfGoal[ObstaclesPercept::opponentGoal] = midDir;
01164 double distance = ((first2 + last2) / 2).abs();
01165 rip->obstaclesPercept.distanceToFreePartOfGoal[ObstaclesPercept::opponentGoal] = distance;
01166 rip->obstaclesPercept.widthOfFreePartOfGoal[ObstaclesPercept::opponentGoal] = distance ? 2 * atan((leftAngle - rightAngle).abs() / 2 / distance) : pi;
01167 }
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317