Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

Modules/ImageProcessor/GT2004ImageProcessor/GT2004GoalRecognizer.cpp

Go to the documentation of this file.
00001 /**
00002 * @file GT2004GoalRecognizer.cpp
00003 *
00004 * Implementation of class GT2004GoalRecognizer
00005 *
00006 * @author <a href="mailto:juengel@informatik.hu-berlin.de">Matthias Juengel</a>
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 //      verticalLine.direction * distanceBelowHorizon;// - (-distanceAboveHorizon + distanceBelowHorizon) * i / numberOfScanLines);
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   // variables needed to determine free part of goal
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     // state machine
00162     // states
00163     enum { noGoalColorFound, 
00164       foundBeginOfGoalColor, 
00165       foundEndOfGoalColor
00166     } goalColorState[numberOfGoalColors] = {noGoalColorFound,noGoalColorFound};
00167     // counter
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         //color = COLOR_CLASS(image.image[y][0][x], image.image[y][1][x], image.image[y][2][x]);
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         }//for(int colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00263       }//for(int z = 2; z < line.getNumberOfPixels(); z++)
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         }//if(goalColorState == foundBeginOfGoalColor || goalColorState == foundEndOfGoalColor)
00276       }//for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00277     }//if(line.getNumberOfPixels() > 3)
00278 
00279     for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00280     {
00281       // Add all large parts found on that line to the structure that determines clusters.
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   }// for(int i = 0; i < numberOfHorizontalScanLines; i++)
00302 
00303   for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00304   {
00305     if(colorToCheck == yellowGoal) colorClassToCheck = yellow;
00306     else colorClassToCheck = skyblue;
00307 
00308     // Add one goal indication for each cluster
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     // Determine the free part of the goal
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   }//for(colorToCheck = 0; colorToCheck < numberOfGoalColors; colorToCheck++)
00406 }//void GridImageProcessor2::scanHorizontalForFlagsAndGoals()
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     // Line through center of indication
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     // Line at the left side
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     // Line at the right side
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   // line for the free part of the goal
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 }// calculateVerticalGoalScanLines()
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     // state machine
00505     // states
00506     enum { noGoalColorFound, 
00507       foundBeginOfGoalColor, 
00508       foundEndOfGoalColor,
00509       determinedGoal
00510     } goalColorState = noGoalColorFound;
00511     // counter
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         //color = COLOR_CLASS(image.image[y][0][x], image.image[y][1][x], image.image[y][2][x]);
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 //            goalColorState = noGoalColorFound;
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       }//for(int z = 0; z < line.getNumberOfPixels(); z++) 
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       }//if(goalColorState == foundBeginOfGoalColor || goalColorState == foundEndOfGoalColor)
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             //calculate distance
00652             int distance = (int)Geometry::getDistanceBySize(
00653               image.cameraInfo,
00654               goalHeight, 
00655               (goalCheck.largePartBegin[0] - goalCheck.largePartEnd[goalCheck.numberOfLargeParts - 1]).abs() 
00656             );
00657             //~ int distance = Geometry::getDistanceBySize(
00658               //~ goalHeight, 
00659               //~ (goalCheck.largePartBegin[0] - goalCheck.largePartEnd[goalCheck.numberOfLargeParts - 1]).abs(), 
00660               //~ image.cameraInfo.resolutionWidth, image.cameraInfo.openingAngleWidth);
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           // if(bottomAngles.y < 0)
00674           //if(topAngles.y > 0)
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         }//!scanLineToCheckBestAngle[i]
00682       }//if(goalCheck.numberOfLargeParts > 0)
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     }//if(line.getNumberOfPixels() > 3)
00694   }//for(int i = 0; i < numberOfGoalScanLines; i++)
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 }//scanLinesForGoals()
00799 
00800 /*
00801 * $Log: GT2004GoalRecognizer.cpp,v $
00802 * Revision 1.3  2004/06/14 23:20:10  spranger
00803 * -changed some functions in Geometry from int to double including ballradius(fieldimensions)
00804 * -maybe all Geometric-functions in Geometry should be as precise as possible, avoiding int to double conversion errors
00805 *
00806 * Revision 1.2  2004/06/05 07:58:21  roefer
00807 * Compensation for motion distortions of images
00808 *
00809 * Revision 1.1.1.1  2004/05/22 17:19:44  cvsadm
00810 * created new repository GT2004_WM
00811 *
00812 * Revision 1.2  2004/05/07 15:16:24  nistico
00813 * All geometry calculations are making use of intrinsic functions.
00814 * I updated most of the images processors to make correct use of this.
00815 * Please test if there are any problems, because i'm going to remove the
00816 * old code soon.
00817 *
00818 * Revision 1.1  2004/05/04 13:40:19  tim
00819 * added GT2004ImageProcessor
00820 *
00821 */

Generated on Thu Sep 23 19:57:28 2004 for GT2004 by doxygen 1.3.6