00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "GoalRecognizer.h"
00010 #include "Tools/Player.h"
00011 #include "Tools/FieldDimensions.h"
00012 #include "Tools/RangeArray.h"
00013 #include "Representations/Perception/ColorTable64.h"
00014
00015 #include "ColorTableReferenceColor.h"
00016
00017
00018
00019 #define COLOR_CLASS(y,u,v) colorTable.getColorClass(y,u,v)
00020
00021 GoalRecognizer::GoalRecognizer
00022 (
00023 const Image& image,
00024 const CameraMatrix& cameraMatrix,
00025 const ColorTable& colorTable,
00026 int goalIndicationAboveHorizon,
00027 int goalIndicationBelowHorizon,
00028 ObstaclesPercept& obstaclesPercept,
00029 LandmarksPercept& landmarksPercept
00030 )
00031 :
00032 image(image),
00033 cameraMatrix(cameraMatrix),
00034 colorTable(colorTable),
00035 goalIndicationAboveHorizon(goalIndicationAboveHorizon),
00036 goalIndicationBelowHorizon(goalIndicationBelowHorizon),
00037 obstaclesPercept(obstaclesPercept),
00038 landmarksPercept(landmarksPercept)
00039 {
00040 useFixedScanLines = false;
00041 }
00042
00043 GoalRecognizer::GoalRecognizer
00044 (
00045 const Image& image,
00046 const CameraMatrix& cameraMatrix,
00047 const ColorTable& colorTable,
00048 ObstaclesPercept& obstaclesPercept,
00049 LandmarksPercept& landmarksPercept
00050 )
00051 :
00052 image(image),
00053 cameraMatrix(cameraMatrix),
00054 colorTable(colorTable),
00055 obstaclesPercept(obstaclesPercept),
00056 landmarksPercept(landmarksPercept)
00057 {
00058 useFixedScanLines = true;
00059 }
00060
00061
00062 GoalRecognizer::~GoalRecognizer()
00063 {
00064 }
00065
00066 void GoalRecognizer::getGoalPercept(LandmarksPercept& landmarksPercept)
00067 {
00068 if(getPlayer().getTeamColor() == Player::blue)
00069 {
00070 colorOfOpponentGoal = yellow;
00071 colorOfOwnGoal = skyblue;
00072 }
00073 else
00074 {
00075 colorOfOpponentGoal = skyblue;
00076 colorOfOwnGoal = yellow;
00077 }
00078
00079 INIT_DEBUG_IMAGE(imageProcessorGoals, image);
00080
00081 horizonLine = Geometry::calculateHorizon(cameraMatrix, image.cameraInfo);
00082 verticalLine.base = horizonLine.base;
00083 verticalLine.direction.x = - horizonLine.direction.y;
00084 verticalLine.direction.y = horizonLine.direction.x;
00085
00086 if(useFixedScanLines)
00087 calculateScanLinesParallelToHorizon();
00088 else
00089 calculateScanLinesParallelToHorizon(goalIndicationAboveHorizon, goalIndicationBelowHorizon, 7);
00090
00091 scanHorizontalForGoals();
00092 calculateVerticalGoalScanLines();
00093 scanLinesForGoals();
00094
00095 SEND_DEBUG_IMAGE(imageProcessorGoals);
00096 }
00097
00098 void GoalRecognizer::calculateScanLinesParallelToHorizon()
00099 {
00100 numberOfHorizontalScanLines = 0;
00101
00102 Geometry::Line lineAboveHorizon;
00103 lineAboveHorizon.direction = horizonLine.direction;
00104
00105 int i;
00106
00107 Vector2<int> bottomLeft(0,0);
00108 Vector2<int> topRight(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3);
00109
00110 for(i = 14; i >= 0; i--)
00111 {
00112 lineAboveHorizon.base = horizonLine.base + verticalLine.direction * ( (i * 4.5) - 25 );
00113
00114 if(Geometry::getIntersectionPointsOfLineAndRectangle(
00115 bottomLeft, topRight, lineAboveHorizon,
00116 leftPoint[numberOfHorizontalScanLines],
00117 rightPoint[numberOfHorizontalScanLines])
00118 )
00119 {
00120 numberOfHorizontalScanLines++;
00121 }
00122 }
00123 }
00124
00125 void GoalRecognizer::calculateScanLinesParallelToHorizon
00126 (
00127 int distanceAboveHorizon,
00128 int distanceBelowHorizon,
00129 int numberOfScanLines
00130 )
00131 {
00132 numberOfHorizontalScanLines = 0;
00133
00134 Geometry::Line scanLine;
00135 scanLine.direction = horizonLine.direction;
00136
00137 int i;
00138
00139 Vector2<int> bottomLeft(0,0);
00140 Vector2<int> topRight(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3);
00141
00142 for(i = 0; i < numberOfScanLines; i++)
00143 {
00144 scanLine.base =
00145 horizonLine.base +
00146 verticalLine.direction * -(distanceBelowHorizon + (distanceAboveHorizon - distanceBelowHorizon) * i / (numberOfScanLines - 1));
00147
00148
00149 if(Geometry::getIntersectionPointsOfLineAndRectangle(
00150 bottomLeft, topRight, scanLine,
00151 leftPoint[numberOfHorizontalScanLines],
00152 rightPoint[numberOfHorizontalScanLines])
00153 )
00154 {
00155 numberOfHorizontalScanLines++;
00156 }
00157 }
00158 }
00159
00160 void GoalRecognizer::scanHorizontalForGoals()
00161 {
00162 enum {yellowGoal = 1, skyblueGoal = 0, numberOfGoalColors = 2};
00163 int colorToCheck;
00164 colorClass colorClassToCheck;
00165
00166 RangeArray<double> goalClusters[numberOfGoalColors];
00167 numberOfGoalIndications = 0;
00168
00169
00170 RangeArray<double> goalClustersForFreePart[numberOfGoalColors];
00171 int numberOfLinesWithLargeParts[numberOfGoalColors] = {0, 0};
00172
00173 int i;
00174 for(i = 0; i < numberOfHorizontalScanLines; i++)
00175 {
00176 Geometry::PixeledLine line(leftPoint[i], rightPoint[i]);
00177
00178
00179
00180 enum { noGoalColorFound,
00181 foundBeginOfGoalColor,
00182 foundEndOfGoalColor
00183 } goalColorState[numberOfGoalColors] = {noGoalColorFound,noGoalColorFound};
00184
00185 int numberOfPixelsSinceLastOccurrenceOfGoalColor[numberOfGoalColors];
00186 int numberOfPixelsSinceFirstOccurrenceOfGoalColor[numberOfGoalColors] = {0,0};
00187
00188 bool colorStartsAtBeginOfImage[numberOfGoalColors] = {false, false};
00189 ColoredPartsCheck goalCheck[numberOfGoalColors];
00190
00191 int x = 0, y = 0;
00192 colorClass color;
00193
00194 if(line.getNumberOfPixels() > 3)
00195 {
00196 for(int z = 2; z < line.getNumberOfPixels(); z++)
00197 {
00198 x = line.getPixelX(z);
00199 y = line.getPixelY(z);
00200
00201 color = COLOR_CLASS(image.image[y][0][x], image.image[y][1][x], image.image[y][2][x]);
00202
00203 for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00204 {
00205 if(colorToCheck == yellowGoal) colorClassToCheck = yellow;
00206 else colorClassToCheck = skyblue;
00207
00208 if(goalColorState[colorToCheck] == noGoalColorFound)
00209 {
00210 DEBUG_IMAGE_SET_PIXEL_BLACK(imageProcessorGoals, x, y + colorToCheck);
00211 if(color == colorClassToCheck)
00212 {
00213 goalCheck[colorToCheck].numberOfColoredPixels = 0;
00214 goalCheck[colorToCheck].rangeOfColor = 0;
00215 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] == 0)
00216 {
00217 goalCheck[colorToCheck].firstPoint.x = x;
00218 goalCheck[colorToCheck].firstPoint.y = y;
00219 }
00220 numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck]++;
00221 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] > 2)
00222 {
00223 goalColorState[colorToCheck] = foundBeginOfGoalColor;
00224 if(z < 5)
00225 {
00226 DOT(imageProcessor_general, x, y, Drawings::green, Drawings::green);
00227 colorStartsAtBeginOfImage[colorToCheck] = true;
00228 }
00229 }
00230 }
00231 else
00232 {
00233 numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] = 0;
00234 }
00235 }
00236 else if(goalColorState[colorToCheck] == foundBeginOfGoalColor)
00237 {
00238 DEBUG_IMAGE_SET_PIXEL_GRAY(imageProcessorGoals, x, y + colorToCheck);
00239 if(color == colorClassToCheck) goalCheck[colorToCheck].numberOfColoredPixels++;
00240 else
00241 {
00242 goalCheck[colorToCheck].lastPoint.x = x;
00243 goalCheck[colorToCheck].lastPoint.y = y;
00244 goalColorState[colorToCheck] = foundEndOfGoalColor;
00245 numberOfPixelsSinceLastOccurrenceOfGoalColor[colorToCheck] = 0;
00246 numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] = 0;
00247 }
00248 goalCheck[colorToCheck].rangeOfColor++;
00249 }
00250 else if(goalColorState[colorToCheck] == foundEndOfGoalColor)
00251 {
00252 DEBUG_IMAGE_SET_PIXEL_WHITE(imageProcessorGoals, x, y + colorToCheck);
00253 numberOfPixelsSinceLastOccurrenceOfGoalColor[colorToCheck]++;
00254 if(color == colorClassToCheck)
00255 {
00256 numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck]++;
00257 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] > 2)
00258 {
00259 goalColorState[colorToCheck] = foundBeginOfGoalColor;
00260 }
00261 }
00262 else if(
00263 numberOfPixelsSinceLastOccurrenceOfGoalColor[colorToCheck] > 5
00264 ||
00265 color == white
00266 )
00267 {
00268 goalColorState[colorToCheck] = noGoalColorFound;
00269 goalCheck[colorToCheck].determineLargePart(10, colorStartsAtBeginOfImage[colorToCheck], false, cameraMatrix, image.cameraInfo);
00270 DOT(imageProcessor_general, x, y, Drawings::green, Drawings::white);
00271 colorStartsAtBeginOfImage[colorToCheck] = false;
00272 }
00273 else
00274 {
00275 numberOfPixelsSinceFirstOccurrenceOfGoalColor[colorToCheck] = 0;
00276 }
00277 goalCheck[colorToCheck].rangeOfColor++;
00278 }
00279 }
00280 }
00281
00282 for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00283 {
00284 if(goalColorState[colorToCheck] == foundBeginOfGoalColor || goalColorState[colorToCheck] == foundEndOfGoalColor)
00285 {
00286 if(goalColorState[colorToCheck] == foundBeginOfGoalColor)
00287 {
00288 goalCheck[colorToCheck].lastPoint.x = x;
00289 goalCheck[colorToCheck].lastPoint.y = y;
00290 }
00291 goalCheck[colorToCheck].determineLargePart(10, colorStartsAtBeginOfImage[colorToCheck], true, cameraMatrix, image.cameraInfo);
00292 }
00293 }
00294 }
00295
00296 for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00297 {
00298
00299 if(goalCheck[colorToCheck].numberOfLargeParts > 0) numberOfLinesWithLargeParts[colorToCheck]++;
00300 int index;
00301 for(index = 0; index < goalCheck[colorToCheck].numberOfLargeParts; index++)
00302 {
00303 goalClusters[colorToCheck].add(
00304 Range<double>(goalCheck[colorToCheck].largePartEndAngles[index].x, goalCheck[colorToCheck].largePartBeginAngles[index].x),
00305 goalCheck[colorToCheck].largePartBeginIsOnBorder[index],
00306 goalCheck[colorToCheck].largePartEndIsOnBorder[index]
00307 );
00308 if(numberOfLinesWithLargeParts[colorToCheck] > 2 && numberOfLinesWithLargeParts[colorToCheck] < 5)
00309 {
00310 goalClustersForFreePart[colorToCheck].add(
00311 Range<double>(goalCheck[colorToCheck].largePartEndAngles[index].x, goalCheck[colorToCheck].largePartBeginAngles[index].x),
00312 goalCheck[colorToCheck].largePartBeginIsOnBorder[index],
00313 goalCheck[colorToCheck].largePartEndIsOnBorder[index]
00314 );
00315 }
00316 }
00317 }
00318 }
00319
00320 for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00321 {
00322 if(colorToCheck == yellowGoal) colorClassToCheck = yellow;
00323 else colorClassToCheck = skyblue;
00324
00325
00326 int index;
00327 for(index = 0; index < goalClusters[colorToCheck].getNumberOfClusters(); index++)
00328 {
00329 Range<double> currentRange = goalClusters[colorToCheck].getCluster(index);
00330 Vector2<int> leftPoint, rightPoint;
00331 Geometry::calculatePointByAngles(Vector2<double>(currentRange.max,0.02 * index), cameraMatrix, image.cameraInfo, leftPoint);
00332 Geometry::calculatePointByAngles(Vector2<double>(currentRange.min,0.02 * index), cameraMatrix, image.cameraInfo, rightPoint);
00333 LINE(imageProcessor_flagsAndGoals, leftPoint.x, leftPoint.y, rightPoint.x, rightPoint.y, 2, Drawings::ps_solid, Drawings::blue);
00334 goalIndicationLeft[numberOfGoalIndications] = leftPoint;
00335 goalIndicationRight[numberOfGoalIndications] = rightPoint;
00336 goalIndicationCenter[numberOfGoalIndications] = (leftPoint + rightPoint) / 2;
00337 leftOfGoalIndicationIsOnBorder[numberOfGoalIndications] = goalClusters[colorToCheck].isLeftOnBorder(index);
00338 rightOfGoalIndicationIsOnBorder[numberOfGoalIndications] = goalClusters[colorToCheck].isRightOnBorder(index);
00339 colorOfGoalIndication[numberOfGoalIndications] = colorClassToCheck;
00340 numberOfGoalIndications++;
00341 }
00342
00343
00344 for(index = 0; index < goalClustersForFreePart[colorToCheck].getNumberOfClusters(); index++)
00345 {
00346 Range<double> currentRange = goalClustersForFreePart[colorToCheck].getCluster(index);
00347 Vector2<int> leftPoint, rightPoint;
00348 Geometry::calculatePointByAngles(Vector2<double>(currentRange.min,-0.1 + 0.02 * index), cameraMatrix, image.cameraInfo, leftPoint);
00349 Geometry::calculatePointByAngles(Vector2<double>(currentRange.max,-0.1 + 0.02 * index), cameraMatrix, image.cameraInfo, rightPoint);
00350 LINE(imageProcessor_flagsAndGoals, leftPoint.x, leftPoint.y, rightPoint.x, rightPoint.y, 2, Drawings::ps_solid, Drawings::green);
00351 }
00352
00353 double center, angle;
00354 bool determinedFreePartOfGoal = false;
00355 if(goalClustersForFreePart[colorToCheck].getNumberOfClusters() == 1)
00356 {
00357 bool leftOfPartIsOnBorder = goalClustersForFreePart[colorToCheck].isLeftOnBorder(0);
00358 bool rightOfPartIsOnBorder = goalClustersForFreePart[colorToCheck].isRightOnBorder(0);
00359 Range<double> freePartRange = goalClustersForFreePart[colorToCheck].getCluster(0);
00360 if(!leftOfPartIsOnBorder && !rightOfPartIsOnBorder || freePartRange.getSize() > 0.7 * image.cameraInfo.openingAngleWidth)
00361 {
00362 determinedFreePartOfGoal = true;
00363 center = (freePartRange.min + freePartRange.max) / 2.0;
00364 angle = freePartRange.max - freePartRange.min;
00365 }
00366 }
00367 else if(goalClustersForFreePart[colorToCheck].getNumberOfClusters() == 2)
00368 {
00369 Range<double> freePartRange[2];
00370 freePartRange[0] = goalClustersForFreePart[colorToCheck].getCluster(0);
00371 freePartRange[1] = goalClustersForFreePart[colorToCheck].getCluster(1);
00372
00373 bool freePartIsSeenCompletely[2];
00374
00375 freePartIsSeenCompletely[0] =
00376 !goalClustersForFreePart[colorToCheck].isLeftOnBorder(0) &&
00377 !goalClustersForFreePart[colorToCheck].isRightOnBorder(0);
00378
00379 freePartIsSeenCompletely[1] =
00380 !goalClustersForFreePart[colorToCheck].isLeftOnBorder(1) &&
00381 !goalClustersForFreePart[colorToCheck].isRightOnBorder(1);
00382
00383 int largePart, smallPart;
00384 if(freePartRange[0].getSize() < freePartRange[1].getSize())
00385 {
00386 largePart = 1;
00387 smallPart = 0;
00388 }
00389 else
00390 {
00391 largePart = 0;
00392 smallPart = 1;
00393 }
00394
00395 if(
00396 freePartIsSeenCompletely[largePart] && freePartIsSeenCompletely[smallPart] ||
00397 !freePartIsSeenCompletely[largePart] && freePartIsSeenCompletely[smallPart]
00398 )
00399 {
00400 determinedFreePartOfGoal = true;
00401 center = (freePartRange[largePart].min + freePartRange[largePart].max) / 2.0;
00402 angle = freePartRange[largePart].max - freePartRange[largePart].min;
00403 }
00404 }
00405
00406 if(determinedFreePartOfGoal)
00407 {
00408 if(colorClassToCheck == colorOfOpponentGoal)
00409 {
00410 obstaclesPercept.angleToFreePartOfGoal[ObstaclesPercept::opponentGoal] = center;
00411 obstaclesPercept.widthOfFreePartOfGoal[ObstaclesPercept::opponentGoal] = angle;
00412 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::opponentGoal] = true;
00413 }
00414 else
00415 {
00416 obstaclesPercept.angleToFreePartOfGoal[ObstaclesPercept::ownGoal] = center;
00417 obstaclesPercept.widthOfFreePartOfGoal[ObstaclesPercept::ownGoal] = angle;
00418 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::ownGoal] = true;
00419 }
00420 }
00421
00422 }
00423 }
00424
00425 void GoalRecognizer::calculateVerticalGoalScanLines()
00426 {
00427 numberOfGoalScanLines = 0;
00428 int i;
00429 Vector2<double> anglesForGoalScanLine;
00430 for(i = 0; i < numberOfGoalIndications; i++)
00431 {
00432
00433 Geometry::calculateAnglesForPoint(goalIndicationCenter[i], cameraMatrix, image.cameraInfo, anglesForGoalScanLine);
00434 anglesForGoalScanLine.y = -1.0;
00435 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, bottomGoalPoint[numberOfGoalScanLines]);
00436 anglesForGoalScanLine.y = 0.3;
00437 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, topGoalPoint[numberOfGoalScanLines]);
00438
00439 if(Geometry::clipLineWithRectangleCohenSutherland(Vector2<int>(0,0), Vector2<int>(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3),
00440 topGoalPoint[numberOfGoalScanLines], bottomGoalPoint[numberOfGoalScanLines]))
00441 {
00442 colorOfGoalScanLine[numberOfGoalScanLines] = colorOfGoalIndication[i];
00443 indexOfGoalIndication[numberOfGoalScanLines] = i;
00444 scanLineToCheckBestAngle[numberOfGoalScanLines] = false;
00445 numberOfGoalScanLines++;
00446 }
00447
00448
00449 Geometry::calculateAnglesForPoint((goalIndicationLeft[i] + goalIndicationCenter[i]) / 2, cameraMatrix, image.cameraInfo, anglesForGoalScanLine);
00450 anglesForGoalScanLine.y = -1.0;
00451 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, bottomGoalPoint[numberOfGoalScanLines]);
00452 anglesForGoalScanLine.y = 0.3;
00453 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, topGoalPoint[numberOfGoalScanLines]);
00454
00455 if(Geometry::clipLineWithRectangleCohenSutherland(Vector2<int>(0,0), Vector2<int>(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3),
00456 topGoalPoint[numberOfGoalScanLines], bottomGoalPoint[numberOfGoalScanLines]))
00457 {
00458 colorOfGoalScanLine[numberOfGoalScanLines] = colorOfGoalIndication[i];
00459 indexOfGoalIndication[numberOfGoalScanLines] = i;
00460 scanLineToCheckBestAngle[numberOfGoalScanLines] = false;
00461 numberOfGoalScanLines++;
00462 }
00463
00464
00465 Geometry::calculateAnglesForPoint((goalIndicationRight[i] + goalIndicationCenter[i]) / 2, cameraMatrix, image.cameraInfo, anglesForGoalScanLine);
00466 anglesForGoalScanLine.y = -1.0;
00467 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, bottomGoalPoint[numberOfGoalScanLines]);
00468 anglesForGoalScanLine.y = 0.3;
00469 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, topGoalPoint[numberOfGoalScanLines]);
00470
00471 if(Geometry::clipLineWithRectangleCohenSutherland(Vector2<int>(0,0), Vector2<int>(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3),
00472 topGoalPoint[numberOfGoalScanLines], bottomGoalPoint[numberOfGoalScanLines]))
00473 {
00474 colorOfGoalScanLine[numberOfGoalScanLines] = colorOfGoalIndication[i];
00475 indexOfGoalIndication[numberOfGoalScanLines] = i;
00476 scanLineToCheckBestAngle[numberOfGoalScanLines] = false;
00477 numberOfGoalScanLines++;
00478 }
00479
00480 }
00481
00482
00483 for(i = 0; i < 2; i++)
00484 {
00485 if(obstaclesPercept.angleToFreePartOfGoalWasDetermined[i] == true)
00486 {
00487 anglesForGoalScanLine.x = obstaclesPercept.angleToFreePartOfGoal[i];
00488 anglesForGoalScanLine.y = -1.0;
00489 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, bottomGoalPoint[numberOfGoalScanLines]);
00490 anglesForGoalScanLine.y = 0.3;
00491 Geometry::calculatePointByAngles(anglesForGoalScanLine, cameraMatrix, image.cameraInfo, topGoalPoint[numberOfGoalScanLines]);
00492
00493 if(Geometry::clipLineWithRectangleCohenSutherland(Vector2<int>(0,0), Vector2<int>(image.cameraInfo.resolutionWidth - 1, image.cameraInfo.resolutionHeight - 3),
00494 topGoalPoint[numberOfGoalScanLines], bottomGoalPoint[numberOfGoalScanLines]))
00495 {
00496 if(i==1) colorOfGoalScanLine[numberOfGoalScanLines] = colorOfOpponentGoal;
00497 else colorOfGoalScanLine[numberOfGoalScanLines] = colorOfOwnGoal;
00498 scanLineToCheckBestAngle[numberOfGoalScanLines] = true;
00499 numberOfGoalScanLines++;
00500 }
00501 }
00502 }
00503 }
00504
00505 void GoalRecognizer::scanLinesForGoals()
00506 {
00507 ConditionalBoundary yellowGoalBoundary, skyblueGoalBoundary;
00508 ConditionalBoundary boundaryOfIndication[maxNumberOfGoalScanLines];
00509 bool useBoundaryOfIndication[maxNumberOfGoalScanLines];
00510 int i;
00511 for(i = 0; i < numberOfGoalIndications; i++) useBoundaryOfIndication[i] = true;
00512
00513 bool foundYellowGoal = false;
00514 bool foundSkyblueGoal = false;
00515 bool pixelHasGoalColor;
00516
00517 for(i = 0; i < numberOfGoalScanLines; i++)
00518 {
00519 Geometry::PixeledLine line(topGoalPoint[i], bottomGoalPoint[i]);
00520
00521
00522
00523 enum { noGoalColorFound,
00524 foundBeginOfGoalColor,
00525 foundEndOfGoalColor,
00526 determinedGoal
00527 } goalColorState = noGoalColorFound;
00528
00529 int numberOfPixelsSinceLastOccurrenceOfGoalColor = 0;
00530 int numberOfPixelsSinceFirstOccurrenceOfGoalColor = 0;
00531 int whiteAndPinkCounter = 0;
00532
00533 bool colorStartsAtBeginOfImage = false;
00534
00535 ColoredPartsCheck goalCheck;
00536
00537 int x = 0, y = 0;
00538 colorClass color;
00539
00540 if(line.getNumberOfPixels() > 3)
00541 {
00542 bool scanLineIsPartOfGoal = true;
00543 for(int z = 2; z < line.getNumberOfPixels(); z++)
00544 {
00545 pixelHasGoalColor = false;
00546 x = line.getPixelX(z);
00547 y = line.getPixelY(z);
00548
00549 if(scanLineToCheckBestAngle[i]){
00550 DEBUG_IMAGE_SET_PIXEL_GRAY(imageProcessorGoals, x, y);
00551 }
00552 else {DEBUG_IMAGE_SET_PIXEL_WHITE(imageProcessorGoals, x, y);}
00553
00554 color = COLOR_CLASS(image.image[y][0][x], image.image[y][1][x], image.image[y][2][x]);
00555
00556 if(colorOfGoalScanLine[i] == skyblue && color == skyblue) pixelHasGoalColor = true;
00557 if(colorOfGoalScanLine[i] == yellow && color == yellow) pixelHasGoalColor = true;
00558
00559 if(goalColorState == noGoalColorFound)
00560 {
00561 if(pixelHasGoalColor)
00562 {
00563 DEBUG_IMAGE_SET_PIXEL_BLACK(imageProcessorGoals, x, y);
00564 goalCheck.numberOfColoredPixels = 0;
00565 goalCheck.rangeOfColor = 0;
00566 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor == 0)
00567 {
00568 goalCheck.firstPoint.x = x;
00569 goalCheck.firstPoint.y = y;
00570 }
00571 numberOfPixelsSinceFirstOccurrenceOfGoalColor++;
00572 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor > 2)
00573 {
00574 goalColorState = foundBeginOfGoalColor;
00575 if(z < 5) colorStartsAtBeginOfImage = true;
00576 }
00577 }
00578 else
00579 {
00580 numberOfPixelsSinceFirstOccurrenceOfGoalColor = 0;
00581 }
00582 }
00583 else if(goalColorState == foundBeginOfGoalColor)
00584 {
00585 DEBUG_IMAGE_SET_PIXEL_GREEN(imageProcessorGoals, x, y);
00586 if(pixelHasGoalColor) goalCheck.numberOfColoredPixels++;
00587 else
00588 {
00589 goalCheck.lastPoint.x = x;
00590 goalCheck.lastPoint.y = y;
00591 goalColorState = foundEndOfGoalColor;
00592 numberOfPixelsSinceLastOccurrenceOfGoalColor = 0;
00593 numberOfPixelsSinceFirstOccurrenceOfGoalColor = 0;
00594 }
00595 goalCheck.rangeOfColor++;
00596 }
00597 else if(goalColorState == foundEndOfGoalColor)
00598 {
00599 numberOfPixelsSinceLastOccurrenceOfGoalColor++;
00600 DEBUG_IMAGE_SET_PIXEL_RED(imageProcessorGoals, x, y);
00601 if(pixelHasGoalColor)
00602 {
00603 numberOfPixelsSinceFirstOccurrenceOfGoalColor++;
00604 if(numberOfPixelsSinceFirstOccurrenceOfGoalColor > 2)
00605 {
00606 goalColorState = foundBeginOfGoalColor;
00607 }
00608 }
00609 else if(numberOfPixelsSinceLastOccurrenceOfGoalColor > 20)
00610 {
00611 DEBUG_IMAGE_SET_PIXEL_BLUE(imageProcessorGoals, x, y);
00612
00613 goalColorState = determinedGoal;
00614 if(goalCheck.determineLargePart(7, colorStartsAtBeginOfImage, false, cameraMatrix, image.cameraInfo))
00615 {
00616 if(whiteAndPinkCounter > 5)
00617 {
00618 scanLineIsPartOfGoal = false;
00619 DOT(imageProcessor_general, x, y, Drawings::blue, Drawings::blue);
00620 }
00621 }
00622 whiteAndPinkCounter = 0;
00623 colorStartsAtBeginOfImage = false;
00624 }
00625 else if(color == white || color == pink)
00626 {
00627 DEBUG_IMAGE_SET_PIXEL_PINK(imageProcessorGoals, x, y);
00628 whiteAndPinkCounter++;
00629 }
00630 else
00631 {
00632 numberOfPixelsSinceFirstOccurrenceOfGoalColor = 0;
00633 }
00634 goalCheck.rangeOfColor++;
00635 }
00636 }
00637 if(goalColorState == foundBeginOfGoalColor || goalColorState == foundEndOfGoalColor)
00638 {
00639 if(goalColorState == foundBeginOfGoalColor)
00640 {
00641 goalCheck.lastPoint.x = x;
00642 goalCheck.lastPoint.y = y;
00643 }
00644 goalCheck.determineLargePart(7, colorStartsAtBeginOfImage, true, cameraMatrix,image.cameraInfo);
00645 }
00646
00647 if(!scanLineIsPartOfGoal && !scanLineToCheckBestAngle[i])
00648 useBoundaryOfIndication[indexOfGoalIndication[i]] = false;
00649
00650 if(goalCheck.numberOfLargeParts > 0)
00651 {
00652 Vector2<double> topAngles, bottomAngles, leftAngles, rightAngles;
00653 Geometry::calculateAnglesForPoint(goalCheck.largePartBegin[0], cameraMatrix, image.cameraInfo, topAngles);
00654 Geometry::calculateAnglesForPoint(goalCheck.largePartEnd[goalCheck.numberOfLargeParts - 1], cameraMatrix, image.cameraInfo, bottomAngles);
00655
00656 if(scanLineToCheckBestAngle[i])
00657 {
00658 if(bottomAngles.y > 0 || !scanLineIsPartOfGoal)
00659 {
00660 if(colorOfOpponentGoal == colorOfGoalScanLine[i])
00661 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::opponentGoal] = false;
00662 else
00663 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::ownGoal] = false;
00664 }
00665 else
00666 {
00667
00668 int distance = Geometry::getDistanceBySize(
00669 image.cameraInfo,
00670 goalHeight,
00671 (goalCheck.largePartBegin[0] - goalCheck.largePartEnd[goalCheck.numberOfLargeParts - 1]).abs()
00672 );
00673
00674
00675
00676
00677
00678 if(colorOfOpponentGoal == colorOfGoalScanLine[i])
00679 obstaclesPercept.distanceToFreePartOfGoal[ObstaclesPercept::opponentGoal] = distance;
00680 else
00681 obstaclesPercept.distanceToFreePartOfGoal[ObstaclesPercept::ownGoal] = distance;
00682 }
00683 }
00684 else
00685 {
00686 Geometry::calculateAnglesForPoint(goalIndicationLeft[indexOfGoalIndication[i]], cameraMatrix, image.cameraInfo, leftAngles);
00687 Geometry::calculateAnglesForPoint(goalIndicationRight[indexOfGoalIndication[i]], cameraMatrix, image.cameraInfo, rightAngles);
00688
00689
00690
00691 {
00692 boundaryOfIndication[indexOfGoalIndication[i]].addY(topAngles.y, goalCheck.largePartBeginIsOnBorder[0]);
00693 boundaryOfIndication[indexOfGoalIndication[i]].addY(bottomAngles.y, goalCheck.largePartEndIsOnBorder[goalCheck.numberOfLargeParts - 1]);
00694 boundaryOfIndication[indexOfGoalIndication[i]].addX(leftAngles.x, leftOfGoalIndicationIsOnBorder[indexOfGoalIndication[i]]);
00695 boundaryOfIndication[indexOfGoalIndication[i]].addX(rightAngles.x, rightOfGoalIndicationIsOnBorder[indexOfGoalIndication[i]]);
00696 }
00697 }
00698 }
00699 else
00700 {
00701 if(scanLineToCheckBestAngle[i])
00702 {
00703 if(colorOfOpponentGoal == colorOfGoalScanLine[i])
00704 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::opponentGoal] = false;
00705 else
00706 obstaclesPercept.angleToFreePartOfGoalWasDetermined[ObstaclesPercept::ownGoal] = false;
00707 }
00708 }
00709 }
00710 }
00711
00712
00713 Vector2<int> corner[4];
00714 int penWidth[4] = {3,3,3,3};
00715
00716 for(i = 0; i < numberOfGoalIndications; i++)
00717 {
00718 Drawings::Color color;
00719 color = Drawings::dark_gray;
00720
00721 if(useBoundaryOfIndication[i])
00722 {
00723 color = Drawings::light_gray;
00724 if(colorOfGoalIndication[i] == yellow)
00725 {
00726 yellowGoalBoundary.add(boundaryOfIndication[i]);
00727 foundYellowGoal = true;
00728 }
00729 if(colorOfGoalIndication[i] == skyblue)
00730 {
00731 skyblueGoalBoundary.add(boundaryOfIndication[i]);
00732 foundSkyblueGoal = true;
00733 }
00734 }
00735
00736 (boundaryOfIndication[i].isOnBorder(boundaryOfIndication[i].y.max))? penWidth[0] = 1 : penWidth[0] = 3;
00737 (boundaryOfIndication[i].isOnBorder(boundaryOfIndication[i].x.min))? penWidth[1] = 1 : penWidth[1] = 3;
00738 (boundaryOfIndication[i].isOnBorder(boundaryOfIndication[i].y.min))? penWidth[2] = 1 : penWidth[2] = 3;
00739 (boundaryOfIndication[i].isOnBorder(boundaryOfIndication[i].x.max))? penWidth[3] = 1 : penWidth[3] = 3;
00740
00741 Geometry::calculatePointByAngles(
00742 Vector2<double>(boundaryOfIndication[i].x.max,boundaryOfIndication[i].y.max),
00743 cameraMatrix, image.cameraInfo,
00744 corner[0]
00745 );
00746
00747 Geometry::calculatePointByAngles(
00748 Vector2<double>(boundaryOfIndication[i].x.min,boundaryOfIndication[i].y.max),
00749 cameraMatrix, image.cameraInfo,
00750 corner[1]
00751 );
00752
00753 Geometry::calculatePointByAngles(
00754 Vector2<double>(boundaryOfIndication[i].x.min,boundaryOfIndication[i].y.min),
00755 cameraMatrix, image.cameraInfo,
00756 corner[2]
00757 );
00758
00759 Geometry::calculatePointByAngles(
00760 Vector2<double>(boundaryOfIndication[i].x.max,boundaryOfIndication[i].y.min),
00761 cameraMatrix, image.cameraInfo,
00762 corner[3]
00763 );
00764
00765 LINE(imageProcessor_flagsAndGoals,
00766 (int)corner[0].x, (int)corner[0].y,
00767 (int)corner[1].x, (int)corner[1].y,
00768 penWidth[0], Drawings::ps_solid, color);
00769 LINE(imageProcessor_flagsAndGoals,
00770 (int)corner[1].x, (int)corner[1].y,
00771 (int)corner[2].x, (int)corner[2].y,
00772 penWidth[1], Drawings::ps_solid, color);
00773 LINE(imageProcessor_flagsAndGoals,
00774 (int)corner[2].x, (int)corner[2].y,
00775 (int)corner[3].x, (int)corner[3].y,
00776 penWidth[2], Drawings::ps_solid, color);
00777 LINE(imageProcessor_flagsAndGoals,
00778 (int)corner[3].x, (int)corner[3].y,
00779 (int)corner[0].x, (int)corner[0].y,
00780 penWidth[3], Drawings::ps_solid, color);
00781 }
00782
00783 bool ownTeamColorIsBlue = getPlayer().getTeamColor() == Player::blue;
00784 if(
00785 foundYellowGoal &&
00786 yellowGoalBoundary.y.min < fromDegrees(0) &&
00787 (
00788 yellowGoalBoundary.x.getSize() > 1.5 * yellowGoalBoundary.y.getSize() ||
00789 yellowGoalBoundary.isOnBorder(yellowGoalBoundary.x.min) ||
00790 yellowGoalBoundary.isOnBorder(yellowGoalBoundary.x.max)
00791 )
00792 )
00793 {
00794 landmarksPercept.addGoal(yellow, ownTeamColorIsBlue, yellowGoalBoundary);
00795 Vector2<double> cameraOffset(cameraMatrix.translation.x, cameraMatrix.translation.y);
00796 landmarksPercept.estimateOffsetForGoals(cameraOffset);
00797 }
00798 if(
00799 foundSkyblueGoal &&
00800 skyblueGoalBoundary.y.min < fromDegrees(0) &&
00801 (
00802 skyblueGoalBoundary.x.getSize() > 1.5 * skyblueGoalBoundary.y.getSize() ||
00803 skyblueGoalBoundary.isOnBorder(skyblueGoalBoundary.x.min) ||
00804 skyblueGoalBoundary.isOnBorder(skyblueGoalBoundary.x.max)
00805 )
00806 )
00807 {
00808 landmarksPercept.addGoal(skyblue, ownTeamColorIsBlue, skyblueGoalBoundary);
00809 Vector2<double> cameraOffset(cameraMatrix.translation.x, cameraMatrix.translation.y);
00810 landmarksPercept.estimateOffsetForGoals(cameraOffset);
00811 }
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886