00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Representations/Perception/Image.h"
00012 #ifdef CT32K_LAYOUT
00013 #include "Representations/Perception/ColorTable32K.h"
00014 #else
00015 #include "Representations/Perception/ColorTable64.h"
00016 #endif
00017 #include "Representations/Perception/CameraMatrix.h"
00018 #include "Representations/Perception/LandmarksPercept.h"
00019 #include "Tools/FieldDimensions.h"
00020 #include "Tools/RingBuffer.h"
00021 #include "Tools/Math/Vector2.h"
00022 #include "Modules/ImageProcessor/ImageProcessorTools/ColorCorrector.h"
00023 #include "GT2004ImageProcessorTools.h"
00024 #include "GT2004BeaconDetector.h"
00025
00026
00027 const int Y(0),
00028 U(cameraResolutionWidth_ERS7),
00029 V(2 * cameraResolutionWidth_ERS7);
00030
00031
00032 GT2004BeaconDetector::GT2004BeaconDetector(const Image& image,
00033 const CameraMatrix& cameraMatrix,
00034 const CameraMatrix& prevCameraMatrix,
00035 const ImageInfo& imageInf,
00036 const ColorTable& colorTable,
00037 const ColorCorrector& colorCorrector,
00038 LandmarksPercept& landmarksPercept):
00039 image(image), cameraMatrix(cameraMatrix),
00040 prevCameraMatrix(prevCameraMatrix),
00041 imageInf(imageInf), colorTable(colorTable),
00042 colorCorrector(colorCorrector),
00043 landmarksPercept(landmarksPercept),
00044 flagSpecialist(colorCorrector),
00045 horizontalBaseOffset(1.6),
00046 numOfHorizontalScanLineAbove(10),
00047 numOfHorizontalScanLineBelow(3),
00048 horizontalOffsetModifier(0.9),
00049 clusteringDistanceTolerance(6),
00050 minPinkRunLength(2),
00051 clusteringAspectRatio(1.5),
00052 projectionAspectRatio(0.4),
00053 minFlagConfidence(0.5),
00054 edgeScanDepth(6),
00055 edgeDetectionU(edgeThresholdU),
00056 edgeDetectionV(edgeThresholdV)
00057 {}
00058
00059
00060 void GT2004BeaconDetector::execute()
00061 {
00062 flagSpecialist.init(image);
00063 numOfBeaconCandidates = 0;
00064 double dist(horizontalBaseOffset);
00065 Geometry::Line scanLine;
00066 scanLine.direction = imageInf.horizon.direction;
00067 scanLine.base = imageInf.horizon.base;
00068 int i;
00069 for(i=0; i < numOfHorizontalScanLineBelow; i++)
00070 {
00071 scanLine.base += imageInf.vertLine.direction*dist;
00072 dist += horizontalOffsetModifier;
00073 Vector2<int> startPoint, endPoint;
00074 if(Geometry::getIntersectionPointsOfLineAndRectangle(
00075 Vector2<int>(0,0), imageInf.maxImageCoordinates, scanLine, startPoint, endPoint))
00076 {
00077 LINE(imageProcessor_general, startPoint.x, startPoint.y, endPoint.x, endPoint.y, 1, Drawings::ps_dash, Drawings::gray);
00078 scanForPink(startPoint, endPoint);
00079 }
00080 else
00081 {
00082 break;
00083 }
00084 }
00085 dist = horizontalBaseOffset;
00086 scanLine.base = imageInf.horizon.base;
00087 for(i=0; i < numOfHorizontalScanLineAbove; i++)
00088 {
00089 scanLine.base -= imageInf.vertLine.direction*dist;
00090 dist += horizontalOffsetModifier;
00091 Vector2<int> startPoint, endPoint;
00092 if(Geometry::getIntersectionPointsOfLineAndRectangle(
00093 Vector2<int>(0,0), imageInf.maxImageCoordinates, scanLine, startPoint, endPoint))
00094 {
00095 LINE(imageProcessor_general, startPoint.x, startPoint.y, endPoint.x, endPoint.y, 1, Drawings::ps_dash, Drawings::yellow);
00096 scanForPink(startPoint, endPoint);
00097 }
00098 else
00099 {
00100 break;
00101 }
00102 }
00103 if(numOfBeaconCandidates)
00104 {
00105 clusterPinkBeaconParts();
00106 }
00107 flagSpecialist.getFlagPercept(cameraMatrix, prevCameraMatrix, image.cameraInfo, imageInf.horizon, landmarksPercept);
00108 }
00109
00110
00111 void GT2004BeaconDetector::scanForPink(const Vector2<int>& start,
00112 const Vector2<int>& end)
00113 {
00114 BresenhamLineScan bresenham(start, end);
00115 bresenham.init();
00116 Vector2<int> pixel(start), lastPixel(start);
00117 int Y(0),U(0),V(0),lastY(0),lastU(0),lastV(0);
00118 Run currentRun;
00119 bool isPinkRun(false);
00120 bool currentPixelPink(false);
00121 for(int i=0; i<bresenham.numberOfPixels; i++)
00122 {
00123 U = image.image[pixel.y][1][pixel.x];
00124 U = ColorCorrector::correct(pixel.x, pixel.y, 1, U);
00125 if(U > minPinkUValue)
00126 {
00127 Y = image.image[pixel.y][0][pixel.x];
00128 Y = ColorCorrector::correct(pixel.x, pixel.y, 0, Y);
00129 V = image.image[pixel.y][2][pixel.x];
00130 V = ColorCorrector::correct(pixel.x, pixel.y, 2, V);
00131 currentPixelPink = (COLOR_CLASS(Y,U,V) == pink);
00132 }
00133 else
00134 {
00135 currentPixelPink = false;
00136 }
00137 if(!isPinkRun)
00138 {
00139 if(currentPixelPink)
00140 {
00141 currentRun.scanLineStart = start;
00142 currentRun.start = pixel;
00143 currentRun.length = 1;
00144 isPinkRun = true;
00145 }
00146 }
00147 else
00148 {
00149 if(currentPixelPink)
00150 {
00151 currentRun.length++;
00152 lastY = Y;
00153 lastU = U;
00154 lastV = V;
00155 }
00156 else
00157 {
00158 isPinkRun = false;
00159 if(currentRun.length >= minPinkRunLength)
00160 {
00161 currentRun.end = lastPixel;
00162 if(!addCandidate(currentRun)) break;
00163 LINE(imageProcessor_general, currentRun.start.x, currentRun.start.y,
00164 currentRun.end.x, currentRun.end.y, 1, Drawings::ps_solid, Drawings::pink);
00165 }
00166 }
00167 }
00168
00169 lastPixel = pixel;
00170 bresenham.getNext(pixel);
00171 }
00172
00173 if(isPinkRun)
00174 {
00175 currentRun.end = pixel;
00176 addCandidate(currentRun);
00177 LINE(imageProcessor_general, currentRun.start.x, currentRun.start.y,
00178 currentRun.end.x, currentRun.end.y, 1, Drawings::ps_solid, Drawings::pink);
00179 }
00180 }
00181
00182
00183 bool GT2004BeaconDetector::addCandidate(const Run& pinkRun)
00184 {
00185 bool returnValue(numOfBeaconCandidates<MAX_NUMBER_OF_PINK_RUNS);
00186 if(returnValue)
00187 {
00188 if((numOfBeaconCandidates>0) &&
00189 (pinkRun.scanLineStart == beaconCandidates[numOfBeaconCandidates-1].scanLineStart) &&
00190 ((beaconCandidates[numOfBeaconCandidates-1].end - pinkRun.start).abs()<4))
00191 {
00192 beaconCandidates[numOfBeaconCandidates-1].end = pinkRun.end;
00193 }
00194 else
00195 {
00196 beaconCandidates[numOfBeaconCandidates++] = pinkRun;
00197 }
00198 }
00199 return returnValue;
00200 }
00201
00202
00203 void GT2004BeaconDetector::clusterPinkBeaconParts()
00204 {
00205
00206 double rotation(imageInf.horizon.direction.angle());
00207 double ca(cos(-rotation));
00208 double sa(sin(-rotation));
00209 Matrix2x2<double> rotMat(Vector2<double>(ca,sa),Vector2<double>(-sa,ca));
00210 Matrix2x2<double> invRotMat = rotMat.transpose();
00211 for(int i=0; i<numOfBeaconCandidates; i++)
00212 {
00213 transformedCandidates[i].transform(beaconCandidates[i], rotMat, i);
00214 }
00215
00216 for(int j=0; j<numOfBeaconCandidates; j++)
00217 {
00218 int leftest(j);
00219 for(int k=j; k<numOfBeaconCandidates; k++)
00220 {
00221 if(transformedCandidates[k].start.x<transformedCandidates[leftest].start.x)
00222 {
00223 leftest = k;
00224 }
00225 }
00226 if(leftest != j)
00227 {
00228 TransformedRun help(transformedCandidates[j]);
00229 transformedCandidates[j] = transformedCandidates[leftest];
00230 transformedCandidates[leftest] = help;
00231 }
00232 }
00233
00234 int beginOfBeacon(0), endOfBeacon(0);
00235 double xRight(transformedCandidates[0].end.x);
00236 double xLeft(transformedCandidates[0].start.x);
00237 double yRight(transformedCandidates[0].end.y);
00238 double yLeft(transformedCandidates[0].start.y);
00239 double runLength(xRight-xLeft);
00240 double yMax, yMin;
00241 double originMinY, originMaxY;
00242 if (yRight > yLeft)
00243 {
00244 yMax = yRight;
00245 yMin = yLeft;
00246 }
00247 else
00248 {
00249 yMax = yLeft;
00250 yMin = yRight;
00251 }
00252 originMinY = beaconCandidates[0].scanLineStart.y;
00253 originMaxY = beaconCandidates[0].scanLineStart.y;
00254 for(int l=1; l<numOfBeaconCandidates; l++)
00255 {
00256 if(transformedCandidates[l].start.x < xRight + (double)clusteringDistanceTolerance)
00257 {
00258 if(transformedCandidates[l].end.x > xRight)
00259 {
00260 double candidateLength = transformedCandidates[l].end.x-xLeft;
00261 bool newRunHigher = (transformedCandidates[l].end.y-yLeft > 0.0);
00262 double candidateHeight = newRunHigher ? (transformedCandidates[l].end.y-yLeft) : (yLeft-transformedCandidates[l].end.y);
00263 if (candidateHeight < candidateLength*clusteringAspectRatio)
00264 {
00265 xRight = transformedCandidates[l].end.x;
00266 yRight = transformedCandidates[l].end.y;
00267 endOfBeacon = l;
00268 if (transformedCandidates[l].end.y-yMax > 0.0)
00269 {
00270 yMax = transformedCandidates[l].end.y;
00271 originMaxY = beaconCandidates[l].scanLineStart.y;
00272 }
00273 else if (yMin - transformedCandidates[l].end.y > 0.0)
00274 {
00275 yMin = transformedCandidates[l].end.y;
00276 originMinY = beaconCandidates[l].scanLineStart.y;
00277 }
00278 }
00279 else
00280 {
00281 double newLength = transformedCandidates[l].end.x - transformedCandidates[l].start.x;
00282 if (newLength > runLength)
00283 {
00284 xRight = transformedCandidates[l].end.x;
00285 xLeft = transformedCandidates[l].start.x;
00286 yRight = transformedCandidates[l].end.y;
00287 yLeft = transformedCandidates[l].start.y;
00288 endOfBeacon = l;
00289 beginOfBeacon = l;
00290 runLength = newLength;
00291 if (yRight > yLeft)
00292 {
00293 yMax = yRight;
00294 yMin = yLeft;
00295 }
00296 else
00297 {
00298 yMax = yLeft;
00299 yMin = yRight;
00300 }
00301 originMinY = beaconCandidates[l].scanLineStart.y;
00302 originMaxY = beaconCandidates[l].scanLineStart.y;
00303 }
00304 }
00305 }
00306 else
00307 {
00308 double newRunHeight = (transformedCandidates[l].end.y + transformedCandidates[l].start.y)/2.0;
00309 bool candidateMax = (newRunHeight-yMax > 0.0);
00310 bool candidateMin = (yMin - newRunHeight > 0.0);
00311 if (candidateMax)
00312 {
00313 double candidateHeight = newRunHeight - yMin;
00314 double candidateLength = xRight-xLeft;
00315 if (candidateHeight < candidateLength*clusteringAspectRatio)
00316 {
00317 yMax = newRunHeight;
00318 originMaxY = beaconCandidates[l].scanLineStart.y;
00319 }
00320 }
00321 else if (candidateMin)
00322 {
00323 double candidateHeight = yMax - newRunHeight;
00324 double candidateLength = xRight-xLeft;
00325 if (candidateHeight < candidateLength*clusteringAspectRatio)
00326 {
00327 yMin = newRunHeight;
00328 originMinY = beaconCandidates[l].scanLineStart.y;
00329 }
00330 }
00331 }
00332 }
00333 else
00334 {
00335 double originX = (beaconCandidates[beginOfBeacon].scanLineStart.x + beaconCandidates[endOfBeacon].scanLineStart.x)/2.0;
00336
00337 double originY = (originMinY + originMaxY)/2;
00338 double mergedScanLineLength = xRight-xLeft;
00339 Vector2<double> leftOfBeacon, rightOfBeacon;
00340 leftOfBeacon.x = xLeft - originX;
00341 rightOfBeacon.x = xRight - originX;
00342 leftOfBeacon.y = (yMax+yMin)/2.0 - originY;
00343 rightOfBeacon.y = leftOfBeacon.y;
00344 leftOfBeacon = (invRotMat*leftOfBeacon);
00345 rightOfBeacon = (invRotMat*rightOfBeacon);
00346 leftOfBeacon.x += originX;
00347 leftOfBeacon.y += originY;
00348 rightOfBeacon.x += originX;
00349 rightOfBeacon.y += originY;
00350 LINE(imageProcessor_general, int(leftOfBeacon.x+0.5), int(leftOfBeacon.y+0.5),
00351 int(rightOfBeacon.x+0.5), int(rightOfBeacon.y+0.5), 1, Drawings::ps_dash, Drawings::red);
00352 analyzeBeacon(leftOfBeacon, mergedScanLineLength);
00353 beginOfBeacon = l;
00354 endOfBeacon = l;
00355 xRight = transformedCandidates[l].end.x;
00356 yRight = transformedCandidates[l].end.y;
00357 xLeft = transformedCandidates[l].start.x;
00358 yLeft = transformedCandidates[l].start.y;
00359 if (yRight > yLeft)
00360 {
00361 yMax = yRight;
00362 yMin = yLeft;
00363 }
00364 else
00365 {
00366 yMax = yLeft;
00367 yMin = yRight;
00368 }
00369 originMinY = beaconCandidates[l].scanLineStart.y;
00370 originMaxY = beaconCandidates[l].scanLineStart.y;
00371 }
00372 }
00373 double originX = (beaconCandidates[beginOfBeacon].scanLineStart.x + beaconCandidates[endOfBeacon].scanLineStart.x)/2.0;
00374
00375 double originY = (originMinY + originMaxY)/2;
00376 double mergedScanLineLength = xRight-xLeft;
00377 Vector2<double> leftOfBeacon, rightOfBeacon;
00378 leftOfBeacon.x = xLeft - originX;
00379 rightOfBeacon.x = xRight - originX;
00380 leftOfBeacon.y = (yMax+yMin)/2.0 - originY;
00381 rightOfBeacon.y = leftOfBeacon.y;
00382 leftOfBeacon = (invRotMat*leftOfBeacon);
00383 rightOfBeacon = (invRotMat*rightOfBeacon);
00384 leftOfBeacon.x += originX;
00385 leftOfBeacon.y += originY;
00386 rightOfBeacon.x += originX;
00387 rightOfBeacon.y += originY;
00388 LINE(imageProcessor_general, int(leftOfBeacon.x+0.5), int(leftOfBeacon.y+0.5),
00389 int(rightOfBeacon.x+0.5), int(rightOfBeacon.y+0.5), 1, Drawings::ps_dash, Drawings::red);
00390 analyzeBeacon(leftOfBeacon, mergedScanLineLength);
00391 }
00392
00393 void GT2004BeaconDetector::analyzeBeacon(const Vector2<double>& left, const double pinkRunWidth)
00394 {
00395 if (pinkRunWidth >= 3.0)
00396 {
00397 double rotation(imageInf.horizon.direction.angle());
00398 double ca(cos(rotation));
00399 double sa(sin(rotation));
00400 Matrix2x2<double> rotMat(Vector2<double>(ca,sa),Vector2<double>(-sa,ca));
00401 int flagReliability[4] = {0, 0, 0, 0};
00402 Flag::FlagType flagFound;
00403 Vector2<int> topEdge[4];
00404 Vector2<int> bottomEdge[4];
00405 int i;
00406 int totalWeight = 0;
00407 int highestReliability = 0;
00408 int mostReliableFlag = -1;
00409 for (i=0; i<4; i++)
00410 {
00411 topEdge[i].x = 0;
00412 topEdge[i].y = 0;
00413 bottomEdge[i].x = 0;
00414 bottomEdge[i].y = 0;
00415 }
00416 Vector2<double> currentPos;
00417 Vector2<double> step;
00418 int numberOfScanCol;
00419 if (pinkRunWidth <= 8.0)
00420 {
00421 Vector2<double> displacement((pinkRunWidth-3.0)/2.0, 0);
00422 Vector2<double> init(1.0, 0.0);
00423 displacement = rotMat*displacement;
00424 init = rotMat*init;
00425 step = displacement;
00426 currentPos = left+init;
00427 numberOfScanCol = 3;
00428 }
00429 else
00430 {
00431 Vector2<double> displacement((pinkRunWidth-5.0)/3.0, 0);
00432 Vector2<double> init(2.0, 0.0);
00433 displacement = rotMat*displacement;
00434 init = rotMat*init;
00435 step = displacement;
00436 currentPos = left+init;
00437 numberOfScanCol = 4;
00438 }
00439 for (i=0; i<numberOfScanCol; i++)
00440 {
00441 Vector2<int> top, bottom;
00442 int reliability = scanForBeaconEdges(Vector2<int>(int(currentPos.x+0.5), int(currentPos.y+0.5)),
00443 pinkRunWidth, flagFound, top, bottom);
00444 if (reliability != 0)
00445 {
00446 flagReliability[(int)flagFound] += reliability;
00447 topEdge[(int)flagFound] += top;
00448 bottomEdge[(int)flagFound] += bottom;
00449 }
00450 currentPos += step;
00451 }
00452 for (i=0; i<4; i++)
00453 {
00454 totalWeight += flagReliability[i];
00455 if (flagReliability[i] > highestReliability)
00456 {
00457 highestReliability = flagReliability[i];
00458 mostReliableFlag = i;
00459 }
00460 }
00461 if (mostReliableFlag != -1)
00462 {
00463 double confidence = highestReliability/totalWeight;
00464 if (confidence >= minFlagConfidence)
00465 {
00466 int posX = (int)((topEdge[mostReliableFlag].x + bottomEdge[mostReliableFlag].x)/(2*flagReliability[mostReliableFlag]) + 0.5);
00467 int posY = (int)((topEdge[mostReliableFlag].y + bottomEdge[mostReliableFlag].y)/(2*flagReliability[mostReliableFlag]) + 0.5);
00468 Vector2<int> center(posX, posY);
00469 const Vector2<int> border(0,0);
00470 Geometry::clipPointInsideRectange(border, imageInf.maxImageCoordinates-border, center);
00471 DOT(imageProcessor_ball4, center.x, center.y, Drawings::black, Drawings::blue);
00472 switch ((Flag::FlagType)mostReliableFlag)
00473 {
00474 case Flag::pinkAboveYellow:
00475 flagSpecialist.searchFlags(image, colorTable, cameraMatrix, yellow, true, imageInf.horizon, center.x, center.y);
00476 break;
00477 case Flag::pinkAboveSkyblue:
00478 flagSpecialist.searchFlags(image, colorTable, cameraMatrix, skyblue, true, imageInf.horizon, center.x, center.y);
00479 break;
00480 case Flag::yellowAbovePink:
00481 flagSpecialist.searchFlags(image, colorTable, cameraMatrix, yellow, false, imageInf.horizon, center.x, center.y);
00482 break;
00483 case Flag::skyblueAbovePink:
00484 flagSpecialist.searchFlags(image, colorTable, cameraMatrix, skyblue, false, imageInf.horizon, center.x, center.y);
00485 break;
00486 }
00487 }
00488 }
00489 }
00490 }
00491
00492 int GT2004BeaconDetector::scanForBeaconEdges(const Vector2<int>& position, const double pinkRunWidth,
00493 Flag::FlagType& flagType, Vector2<int>& topEdge, Vector2<int>& bottomEdge)
00494 {
00495 Vector2<int> beaconCenter(position);
00496 Vector2<int> start, end;
00497 Geometry::Line vertLine;
00498 vertLine.direction = imageInf.vertLine.direction;
00499 vertLine.base.x = (double)beaconCenter.x;
00500 vertLine.base.y = (double)beaconCenter.y;
00501 Geometry::getIntersectionPointsOfLineAndRectangle(Vector2<int>(1,1),
00502 imageInf.maxImageCoordinates-Vector2<int>(1,1), vertLine, start, end);
00503 Vector2<int> pos, pos2, pinkBottomEdge, pinkTopEdge, colorBottomEdge, colorTopEdge;
00504 colorClass bottomColor(noColor),topColor(noColor), baseColor(noColor), dontCare(noColor);
00505 bool topColorEdgeFound(false), pinkTopFound(false);
00506 bool unreliable(false);
00507 Flag::FlagType beaconType(Flag::pinkAboveYellow);
00508 int reliability;
00509
00510 if(scanForBeaconPart(beaconCenter, end, pos, pinkBottomEdge, bottomColor))
00511 {
00512 if(bottomColor == white || bottomColor == gray)
00513 {
00514
00515 if(scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor))
00516 {
00517 if(topColor == skyblue)
00518 {
00519 beaconType = Flag::skyblueAbovePink;
00520 topColorEdgeFound = scanForBeaconPart(pos, start, pos2, colorTopEdge, dontCare);
00521 }
00522 else if(topColor == yellow)
00523 {
00524 beaconType = Flag::yellowAbovePink;
00525 topColorEdgeFound = scanForBeaconPart(pos, start, pos2, colorTopEdge, dontCare);
00526 }
00527 else
00528 {
00529 return 0;
00530 }
00531 }
00532 else
00533 {
00534 return 0;
00535 }
00536 }
00537 else if((bottomColor == skyblue) || (bottomColor == yellow))
00538 {
00539 if(scanForBeaconPart(pos, end, pos2, colorBottomEdge, baseColor))
00540 {
00541 if(baseColor == white || baseColor == gray)
00542 {
00543 if(bottomColor == skyblue)
00544 {
00545 beaconType = Flag::pinkAboveSkyblue;
00546 pinkTopFound = scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor);
00547 }
00548 else
00549 {
00550 beaconType = Flag::pinkAboveYellow;
00551 pinkTopFound = scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor);
00552 }
00553 }
00554 else
00555 {
00556 if (scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor))
00557 {
00558 Vector2<int> toPink(pinkTopEdge - pinkBottomEdge);
00559 double distanceToPink = toPink.abs();
00560 double similarityPink;
00561 if (distanceToPink > pinkRunWidth)
00562 similarityPink = (pinkRunWidth/distanceToPink);
00563 else
00564 similarityPink = (distanceToPink/pinkRunWidth);
00565 if (similarityPink > projectionAspectRatio)
00566 {
00567 colorBottomEdge = pinkBottomEdge + (pinkBottomEdge - pinkTopEdge);
00568 pinkTopFound = true;
00569 if(bottomColor == skyblue)
00570 beaconType = Flag::pinkAboveSkyblue;
00571 else
00572 beaconType = Flag::pinkAboveYellow;
00573 }
00574 else
00575 return 0;
00576 }
00577 else
00578 return 0;
00579 }
00580 }
00581 else
00582 {
00583
00584 if (scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor))
00585 {
00586 Vector2<int> toPink(pinkTopEdge - pinkBottomEdge);
00587 double distanceToPink = toPink.abs();
00588 double similarityPink;
00589 if (distanceToPink > pinkRunWidth)
00590 similarityPink = (pinkRunWidth/distanceToPink);
00591 else
00592 similarityPink = (distanceToPink/pinkRunWidth);
00593 if (similarityPink > projectionAspectRatio)
00594 {
00595 colorBottomEdge = pinkBottomEdge + (pinkBottomEdge - pinkTopEdge);
00596 pinkTopFound = true;
00597 if(bottomColor == skyblue)
00598 beaconType = Flag::pinkAboveSkyblue;
00599 else
00600 beaconType = Flag::pinkAboveYellow;
00601 }
00602 else
00603 return 0;
00604 }
00605 else
00606 return 0;
00607 }
00608 }
00609 else
00610 {
00611 return 0;
00612 }
00613 }
00614 else
00615 {
00616 if(scanForBeaconPart(beaconCenter, start, pos, pinkTopEdge, topColor))
00617 {
00618 DOT(imageProcessor_ball4, pinkTopEdge.x, pinkTopEdge.y, Drawings::black, Drawings::pink);
00619 if(topColor == skyblue)
00620 {
00621 beaconType = Flag::skyblueAbovePink;
00622 topColorEdgeFound = scanForBeaconPart(pos, start, pos2, colorTopEdge, dontCare);
00623 if (!topColorEdgeFound)
00624 return 0;
00625 DOT(imageProcessor_ball4, colorTopEdge.x, colorTopEdge.y, Drawings::black, Drawings::red);
00626 }
00627 else if(topColor == yellow)
00628 {
00629 beaconType = Flag::yellowAbovePink;
00630 topColorEdgeFound = scanForBeaconPart(pos, start, pos2, colorTopEdge, dontCare);
00631 if (!topColorEdgeFound)
00632 return 0;
00633 DOT(imageProcessor_ball4, colorTopEdge.x, colorTopEdge.y, Drawings::black, Drawings::red);
00634 }
00635 else
00636 {
00637 Vector2<double> projectedLenght(0, pinkRunWidth+3.0);
00638 double rotation(imageInf.horizon.direction.angle());
00639 double ca(cos(rotation));
00640 double sa(sin(rotation));
00641 Matrix2x2<double> rotMat(Vector2<double>(ca,sa),Vector2<double>(-sa,ca));
00642 Vector2<double> topToBottomDisplacement = rotMat*projectedLenght;
00643 Vector2<int> displacement((int)(topToBottomDisplacement.x+0.5), (int)(topToBottomDisplacement.y+0.5));
00644 pinkBottomEdge = pinkTopEdge + displacement;
00645 const Vector2<int> border(0,0);
00646 Geometry::clipPointInsideRectange(border, imageInf.maxImageCoordinates-border, pinkBottomEdge);
00647 unsigned char colorY(ColorCorrector::correct(pinkBottomEdge.x,pinkBottomEdge.y,0,image.image[pinkBottomEdge.y][0][pinkBottomEdge.x]));
00648 unsigned char colorU(ColorCorrector::correct(pinkBottomEdge.x,pinkBottomEdge.y,1,image.image[pinkBottomEdge.y][1][pinkBottomEdge.x]));
00649 unsigned char colorV(ColorCorrector::correct(pinkBottomEdge.x,pinkBottomEdge.y,2,image.image[pinkBottomEdge.y][2][pinkBottomEdge.x]));
00650 bottomColor = COLOR_CLASS(colorY,colorU,colorV);
00651 DOT(imageProcessor_ball4, pinkBottomEdge.x, pinkBottomEdge.y, Drawings::gray, ColorClasses::colorClassToDrawingsColor(bottomColor));
00652 if((bottomColor == skyblue) || (bottomColor == yellow))
00653 {
00654 colorBottomEdge = pinkBottomEdge + displacement;
00655 Geometry::clipPointInsideRectange(border, imageInf.maxImageCoordinates-border, colorBottomEdge);
00656 colorY = ColorCorrector::correct(colorBottomEdge.x,colorBottomEdge.y,0,image.image[colorBottomEdge.y][0][colorBottomEdge.x]);
00657 colorU = ColorCorrector::correct(colorBottomEdge.x,colorBottomEdge.y,1,image.image[colorBottomEdge.y][1][colorBottomEdge.x]);
00658 colorV = ColorCorrector::correct(colorBottomEdge.x,colorBottomEdge.y,2,image.image[colorBottomEdge.y][2][colorBottomEdge.x]);
00659 baseColor = COLOR_CLASS(colorY,colorU,colorV);
00660 DOT(imageProcessor_ball4, colorBottomEdge.x, colorBottomEdge.y, Drawings::white, ColorClasses::colorClassToDrawingsColor(baseColor));
00661 if (baseColor == white || baseColor == gray)
00662 {
00663 if (bottomColor == skyblue)
00664 {
00665 beaconType = Flag::pinkAboveSkyblue;
00666 pinkTopFound = true;
00667 unreliable = true;
00668 }
00669 else if (bottomColor == yellow)
00670 {
00671 beaconType = Flag::pinkAboveYellow;
00672 pinkTopFound = true;
00673 unreliable = true;
00674 }
00675 else
00676 return 0;
00677 }
00678 else if (baseColor == pink)
00679 {
00680 if (bottomColor == skyblue)
00681 {
00682 beaconType = Flag::skyblueAbovePink;
00683 pinkTopEdge = pinkBottomEdge;
00684 pinkBottomEdge = colorBottomEdge;
00685 topColor = skyblue;
00686 bottomColor = pink;
00687 unreliable = true;
00688 }
00689 else if (bottomColor == yellow)
00690 {
00691 beaconType = Flag::yellowAbovePink;
00692 pinkTopEdge = pinkBottomEdge;
00693 pinkBottomEdge = colorBottomEdge;
00694 topColor = yellow;
00695 bottomColor = pink;
00696 unreliable = true;
00697 }
00698 else
00699 return 0;
00700 }
00701 else
00702 return 0;
00703 }
00704 else
00705 {
00706 return 0;
00707 }
00708 }
00709 }
00710 else
00711 {
00712 return 0;
00713 }
00714 }
00715
00716
00717
00718
00719 if(beaconType == Flag::pinkAboveYellow || beaconType == Flag::pinkAboveSkyblue)
00720 {
00721 if(pinkTopFound)
00722 {
00723
00724
00725
00726 Vector2<int> topPosition(pinkBottomEdge);
00727 Vector2<int> toColor(pinkBottomEdge - colorBottomEdge);
00728 Vector2<int> toPink(pinkTopEdge - pinkBottomEdge);
00729 double distanceToColor = toColor.abs();
00730 double distanceToPink = toPink.abs();
00731 double similarityColor, similarityPink;
00732 if (distanceToColor > pinkRunWidth)
00733 similarityColor = (pinkRunWidth/distanceToColor);
00734 else
00735 similarityColor = (distanceToColor/pinkRunWidth);
00736 if (distanceToPink > pinkRunWidth)
00737 similarityPink = (pinkRunWidth/distanceToPink);
00738 else
00739 similarityPink = (distanceToPink/pinkRunWidth);
00740 if (similarityColor > similarityPink)
00741 topPosition += toColor;
00742 else
00743 topPosition += toPink;
00744
00745
00746 if (unreliable)
00747 reliability = lowReliability;
00748 else
00749 reliability = highReliability;
00750 flagType = beaconType;
00751 topEdge = topPosition*reliability;
00752 bottomEdge = pinkBottomEdge*reliability;
00753 return reliability;
00754 }
00755 else
00756 {
00757
00758 Vector2<int> topPosition(pinkBottomEdge);
00759 Vector2<int> relVec(pinkBottomEdge - colorBottomEdge);
00760 topPosition += relVec;
00761
00762
00763
00764 reliability = mediumReliability;
00765 flagType = beaconType;
00766 topEdge = topPosition*reliability;
00767 bottomEdge = pinkBottomEdge*reliability;
00768 return reliability;
00769 }
00770 }
00771 else
00772 {
00773 if (bottomColor == noColor && topColorEdgeFound)
00774 {
00775 Vector2<int> bottomPosition(pinkTopEdge);
00776 Vector2<int> relVec(pinkTopEdge - colorTopEdge);
00777 bottomPosition += relVec;
00778 flagSpecialist.searchFlags(image, colorTable, cameraMatrix, topColor, false,
00779 imageInf.horizon, (int)((pinkTopEdge.x+bottomPosition.x+1.0)/2), (int)((pinkTopEdge.y+bottomPosition.y+1.0)/2));
00780 DOT(imageProcessor_ball4, pinkTopEdge.x, pinkTopEdge.y, Drawings::white, Drawings::black);
00781 DOT(imageProcessor_ball4, bottomPosition.x, bottomPosition.y, Drawings::black, Drawings::yellow);
00782 DOT(imageProcessor_ball4, (int)((pinkTopEdge.x+bottomPosition.x+1.0)/2), (int)((pinkTopEdge.y+bottomPosition.y+1.0)/2), Drawings::black, Drawings::blue);
00783 reliability = mediumReliability;
00784 flagType = beaconType;
00785 topEdge = pinkTopEdge*reliability;
00786 bottomEdge = bottomPosition*reliability;
00787 return reliability;
00788 }
00789 else{
00790 Vector2<int> bottomPosition;
00791 if (topColorEdgeFound)
00792 {
00793 bottomPosition = pinkTopEdge;
00794 Vector2<int> toColor(pinkTopEdge - colorTopEdge);
00795 Vector2<int> toPink(pinkBottomEdge - pinkTopEdge);
00796 double distanceToColor = toColor.abs();
00797 double distanceToPink = toPink.abs();
00798 double similarityColor, similarityPink;
00799 if (distanceToColor > pinkRunWidth)
00800 similarityColor = (pinkRunWidth/distanceToColor);
00801 else
00802 similarityColor = (distanceToColor/pinkRunWidth);
00803 if (distanceToPink > pinkRunWidth)
00804 similarityPink = (pinkRunWidth/distanceToPink);
00805 else
00806 similarityPink = (distanceToPink/pinkRunWidth);
00807 if (similarityColor > similarityPink)
00808 bottomPosition += toColor;
00809 else
00810 bottomPosition += toPink;
00811 if (unreliable)
00812 reliability = lowReliability;
00813 else
00814 reliability = highReliability;
00815 flagType = beaconType;
00816 topEdge = pinkTopEdge*reliability;
00817 bottomEdge = bottomPosition*reliability;
00818 return reliability;
00819 }
00820 else
00821 {
00822 if (unreliable)
00823 reliability = lowReliability;
00824 else
00825 reliability = mediumReliability;
00826 flagType = beaconType;
00827 topEdge = pinkTopEdge*reliability;
00828 bottomEdge = pinkBottomEdge*reliability;
00829 return reliability;
00830 }
00831 }
00832 }
00833 return true;
00834 }
00835
00836
00837 bool GT2004BeaconDetector::scanForBeaconPart(const Vector2<int>& start, const Vector2<int>& end,
00838 Vector2<int>& position, Vector2<int>& edge, colorClass& color)
00839 {
00840
00841
00842 BresenhamLineScan bresenham(start, end);
00843 bresenham.init();
00844 Vector2<int> pixel(start);
00845 for(int i=0; i<bresenham.numberOfPixels; i++)
00846 {
00847
00848 bool edgeU = edgeDetectionU.isEdgePoint(image, pixel.x, pixel.y, SUSANEdgeDetectionLite::componentB);
00849 bool edgeV = edgeDetectionV.isEdgePoint(image, pixel.x, pixel.y, SUSANEdgeDetectionLite::componentC);
00850 DOT(imageProcessor_ball4, pixel.x, pixel.y, Drawings::black, Drawings::orange);
00851
00852 if (edgeU || edgeV)
00853 {
00854 position = pixel;
00855 edge = pixel;
00856 color = noColor;
00857 unsigned char colorY(ColorCorrector::correct(edge.x,edge.y,0,image.image[edge.y][0][edge.x]));
00858 unsigned char colorU(ColorCorrector::correct(edge.x,edge.y,1,image.image[edge.y][1][edge.x]));
00859 unsigned char colorV(ColorCorrector::correct(edge.x,edge.y,2,image.image[edge.y][2][edge.x]));
00860 colorClass edgeColor = COLOR_CLASS(colorY,colorU,colorV);
00861 color = edgeColor;
00862 int counter;
00863 for (counter = 0; counter < edgeScanDepth &&
00864 ((color == noColor)||(color==edgeColor)||(color==orange)||edgeU||edgeV); counter++)
00865 {
00866 bresenham.getNext(position);
00867 unsigned char colorY(ColorCorrector::correct(position.x,position.y,0,image.image[position.y][0][position.x]));
00868 unsigned char colorU(ColorCorrector::correct(position.x,position.y,1,image.image[position.y][1][position.x]));
00869 unsigned char colorV(ColorCorrector::correct(position.x,position.y,2,image.image[position.y][2][position.x]));
00870 color = COLOR_CLASS(colorY,colorU,colorV);
00871 edgeU = edgeDetectionU.isEdgePoint(image, position.x, position.y, SUSANEdgeDetectionLite::componentB);
00872 edgeV = edgeDetectionV.isEdgePoint(image, position.x, position.y, SUSANEdgeDetectionLite::componentC);
00873 }
00874 if (counter != edgeScanDepth)
00875 return true;
00876 }
00877
00878 bresenham.getNext(pixel);
00879 }
00880 return 0;
00881 }
00882
00883 void GT2004BeaconDetector::analyzeColorTable()
00884 {
00885 Vector3<int> nearPoint,farPoint;
00886 #ifdef CT32K_LAYOUT
00887 ((ColorTable32K&) colorTable).getBoxAroundColorClass(pink,nearPoint,farPoint);
00888 #else
00889 ((ColorTable64&) colorTable).getBoxAroundColorClass(pink,nearPoint,farPoint);
00890 #endif
00891 minPinkUValue = nearPoint.y;
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973