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