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

Modules/ImageProcessor/RasterImageProcessor/RBridgeSpecialist.cpp

Go to the documentation of this file.
00001 /**
00002 * @file RBridgeSpecialist.cpp
00003 * 
00004 * This file contains the implementation of class RBridgeSpecialist.
00005 *
00006 * @author <a href="mailto:sadprofessor@web.de">Bernd Schmidt</a>
00007 */
00008 
00009 #include "RBridgeSpecialist.h"
00010 #include "Tools/ColorClasses.h"
00011 #include "Tools/Location.h"
00012 
00013 RBridgeSpecialist::SegmentInfo::SegmentInfo():
00014   lmValidityOrange(0),
00015   lmValidityYellow(0),
00016   orange(0),
00017   yellow(0),
00018   skyblue(0)
00019 {
00020 
00021 }
00022 
00023 
00024 
00025 RBridgeSpecialist::RBridgeSpecialist(RasterImageProcessor &processor,RasterStrategy &strat):
00026   RasterSpecialist(processor),edgeScanner(processor)  
00027 {
00028 
00029   lineColor=red;
00030   strategy = &strat;
00031   preScanNeeded = true;
00032   postScanNeeded = false;
00033 }
00034 
00035 
00036 RBridgeSpecialist::~RBridgeSpecialist(){}
00037 
00038 
00039 int RBridgeSpecialist::getType() {
00040   return __RBridgeSpecialist;
00041 }
00042 
00043 void RBridgeSpecialist::init() {
00044     segments_img.clear();
00045     infos_img.clear();
00046     lst_pts.clear();
00047     //OUTPUT(idText,text,"init started");
00048     edgeScanner.threshold = 20;
00049 }
00050 
00051 //TODO: could be faster
00052 void RBridgeSpecialist::createBBox() {
00053 
00054   SVector::iterator sit;
00055   list<LinePair>::iterator l_it;
00056   
00057   double dist, p_dist;
00058 
00059 
00060   for (sit = segments_img.begin();sit != segments_img.end();sit++){
00061     if (sit->size() < 1) continue;
00062     
00063     //OUTPUT(idText,text,"size of Goal-Seg: "<<  sit->size());
00064     Geometry::Line top,bottom,left,right;
00065     Vector2<int> minHor,maxHor,minPHor,maxPHor;
00066     SegmentInfo si;
00067     double min_dist = 20000, max_dist = -20000, min_p_dist = 20000, max_p_dist = -20000;
00068     
00069     for (l_it = sit->begin();l_it!=sit->end();++l_it) {
00070 
00071       dist = getDistanceToLine(horizon,l_it->v1);
00072       p_dist = getDistanceToLine(pHorizon,l_it->v1);
00073 
00074       if (dist < min_dist) {
00075         min_dist = dist;
00076         minHor = l_it->v1;
00077 
00078       }
00079       if (dist > max_dist) {
00080         max_dist = dist;
00081         maxHor = l_it->v1;
00082       }
00083 
00084       if (p_dist < min_p_dist) {
00085         min_p_dist = p_dist;
00086         minPHor = l_it->v1;
00087       }
00088       if (p_dist > max_p_dist) {
00089         max_p_dist = p_dist;
00090         maxPHor = l_it->v1;
00091       }
00092 
00093       dist = getDistanceToLine(horizon,l_it->v2);
00094       p_dist = getDistanceToLine(pHorizon,l_it->v2);
00095 
00096       if (dist < min_dist) {
00097         min_dist = dist;
00098         minHor = l_it->v2;
00099 
00100       }
00101       if (dist > max_dist) {
00102         max_dist = dist;
00103         maxHor = l_it->v2;
00104       }
00105 
00106       if (p_dist < min_p_dist) {
00107         min_p_dist = p_dist;
00108         minPHor = l_it->v2;
00109       }
00110       if (p_dist > max_p_dist) {
00111         max_p_dist = p_dist;
00112         maxPHor = l_it->v2;
00113       }
00114     }
00115     top.base = Vector2<double>(
00116       (double)maxHor.x,
00117       (double)maxHor.y);
00118     top.direction = horizon.direction;
00119     
00120     bottom.base = Vector2<double>(
00121       (double)minHor.x,
00122       (double)minHor.y);
00123     bottom.direction = horizon.direction;
00124     
00125     left.base = Vector2<double>(
00126       (double)minPHor.x,
00127       (double)minPHor.y);
00128     left.direction = pHorizon.direction;
00129     
00130     right.base = Vector2<double>(
00131       (double)maxPHor.x,
00132       (double)maxPHor.y);
00133     right.direction = pHorizon.direction;
00134     
00135     Geometry::getIntersectionOfLines(top,left,si.rect.upperLeft);
00136     Geometry::getIntersectionOfLines(top,right,si.rect.upperRight);
00137     Geometry::getIntersectionOfLines(bottom,left,si.rect.bottomLeft);
00138     Geometry::getIntersectionOfLines(bottom,right,si.rect.bottomRight);
00139     si.rect.center = (si.rect.upperLeft + si.rect.bottomRight)/2;
00140     si.size = sit->size();
00141     si.segment = &(*sit);
00142     
00143     countColors(si,*(si.segment));
00144     createValidities(si);
00145     infos_img.push_back(si);
00146   }
00147 }
00148 
00149 
00150 
00151 void RBridgeSpecialist::invokeOnPreScan(int x, int y){
00152 
00153   Vector2 <int> cur_pt = Vector2<int>(x,y);
00154 
00155   if (!strategy->insideBridge) left_border = cur_pt;
00156   else {
00157     LinePair lp(left_border,cur_pt);
00158     lp.color = getColor(lp.v1.x,lp.v1.y);
00159     //search for accurate pixels on colortable
00160     lp.v1 = scanWest(lp.v1.x,lp.v1.y);
00161     lp.v2 = scanEast(lp.v2.x,lp.v2.y);
00162 
00163 
00164     if ((lp.v2.x-lp.v1.x)>1) {
00165       //search for edges to widen the pairs to the edges of the object
00166       edgeScanner.scanWest(lp.v1.x,lp.v2.y);
00167       edgeScanner.scanEast(lp.v2.x,lp.v2.y);
00168       
00169       lst_pts.push_back(lp);
00170         
00171       LINE(imageProcessor_general,
00172         lp.v1.x,lp.v1.y, 
00173         lp.v2.x,lp.v2.y, 
00174         0.5, Drawings::ps_solid, Drawings::red);
00175   
00176     }
00177   }
00178 }
00179 
00180 void RBridgeSpecialist::invokeOnPostScan(int x,int y) {
00181   //not needed
00182 }
00183 
00184 void RBridgeSpecialist::executePostProcessing() {
00185   //OUTPUT(idText,text,"size of lst "<<  lst_pts.size());
00186   if (lst_pts.size() < 2) return;
00187   
00188   int allowedXSpace = 2;
00189   int allowedYSpace = 2;
00190   
00191   horizon = rip->getHorizon();
00192 
00193   pHorizon.base = horizon.base;
00194   pHorizon.direction = horizon.direction;
00195   pHorizon.direction.rotateLeft();
00196   
00197   createSegmentsFromLines2(lst_pts,segments_img,allowedXSpace,allowedYSpace);
00198   
00199   //OUTPUT(idText,text,"size of lst "<<  lst_pts.size());
00200   //OUTPUT(idText,text,"size of segments "<<  segments_img.size());
00201 
00202   sort<SVector::iterator>(segments_img.begin(),segments_img.end(),ListSizeOrder());
00203   createBBox();
00204   //int size = infos_img.size();
00205   vector<SegmentInfo>::iterator it;
00206   for(it = infos_img.begin();it != infos_img.end();++it) {
00207     double width = 0.5;
00208     double boxWidth;
00209     findBridgeMark(*it);
00210     //testing for the right filter
00211     if ((it->lmValidityOrange > 0.3 || it->lmValidityYellow > 0.3) &&
00212       (boxWidth = (it->rect.bottomRight - it->rect.bottomLeft).abs()) > 5 &&
00213       (it->rect.upperLeft - it->rect.bottomLeft).abs() * 3 < boxWidth)
00214     {
00215       width = 1;  
00216       LINE(imageProcessor_general,
00217           it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.upperRight.x,it->rect.upperRight.y,
00218           width, Drawings::ps_solid, Drawings::white);
00219       LINE(imageProcessor_general,
00220           it->rect.bottomLeft.x,it->rect.bottomLeft.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00221           width, Drawings::ps_solid, Drawings::green);
00222       LINE(imageProcessor_general,
00223           it->rect.upperLeft.x,it->rect.upperLeft.y,it->rect.bottomLeft.x,it->rect.bottomLeft.y,
00224           width, Drawings::ps_solid, Drawings::yellow);
00225       LINE(imageProcessor_general,
00226           it->rect.upperRight.x,it->rect.upperRight.y,it->rect.bottomRight.x,it->rect.bottomRight.y,
00227           width, Drawings::ps_solid, Drawings::blue);
00228   
00229     }
00230   }
00231 
00232 }
00233 
00234 void RBridgeSpecialist::countColors(RBridgeSpecialist::SegmentInfo& si, list<LinePair>& segment){
00235   list<LinePair>::iterator lines;
00236   si.orange = 0;
00237   si.yellow =0;
00238   si.skyblue = 0;
00239   for(lines = segment.begin();lines != segment.end();++lines){
00240     LinePair& line = *lines;
00241     switch(line.color){ 
00242     case orange: 
00243       si.orange += line.v2.x - line.v1.x;
00244       break;
00245     case yellow: 
00246       si.yellow += line.v2.x - line.v1.x;
00247       break;
00248     case skyblue: 
00249       si.skyblue += line.v2.x - line.v1.x;
00250       break;
00251     }
00252   }
00253 
00254   int max = 0;
00255   int min = 0;
00256   si.orange > si.skyblue? max = si.orange : max = si.skyblue;
00257   if (si.yellow > max) max = si.yellow;
00258   
00259   min = max/8;
00260 
00261   if (si.orange < min) si.orange = 0;
00262   if (si.yellow < min) si.yellow = 0;
00263   if (si.skyblue < min) si.skyblue = 0;
00264 }
00265 
00266 void RBridgeSpecialist::calculateAnglesForPoint
00267 (
00268   const Vector2<double>& point, 
00269   const CameraMatrix& cameraMatrix, 
00270   const CameraInfo& cameraInfo, 
00271   Vector2<double>& angles
00272  )
00273 {
00274   double factor = ((double)cameraInfo.resolutionWidth / 2.0) / tan(cameraInfo.openingAngleWidth / 2.0);
00275   
00276   Vector3<double> vectorToPoint(
00277     factor,
00278     cameraInfo.resolutionWidth / 2 - point.x,
00279     cameraInfo.resolutionHeight / 2 - point.y);
00280   
00281   Vector3<double> vectorToPointWorld = 
00282     cameraMatrix.rotation * vectorToPoint;
00283   
00284   angles.x =
00285     atan2(vectorToPointWorld.y,vectorToPointWorld.x);
00286   
00287   angles.y =
00288     atan2(
00289     vectorToPointWorld.z,
00290     sqrt(sqr(vectorToPointWorld.x) + sqr(vectorToPointWorld.y)) 
00291     );
00292 }
00293 
00294 bool RBridgeSpecialist::calculatePointOnField
00295 (
00296  const double x,
00297  const double y,
00298  const CameraMatrix& cameraMatrix,
00299  const CameraInfo& cameraInfo,
00300  Vector2<int>& pointOnField
00301  )
00302 {
00303 #ifndef _WIN32 // don't recalculate on real robot
00304   static 
00305 #endif
00306   double xFactor = tan(cameraInfo.openingAngleWidth / 2) / (cameraInfo.resolutionWidth / 2),
00307          yFactor = tan(cameraInfo.openingAngleHeight / 2) / (cameraInfo.resolutionHeight / 2);
00308 
00309   Vector3<double> 
00310     vectorToCenter(1, (cameraInfo.resolutionWidth / 2 - 0.5 - x) * xFactor, (cameraInfo.resolutionHeight / 2 - 0.5 - y) * yFactor);
00311   Vector3<double> 
00312     vectorToCenterWorld = cameraMatrix.rotation * vectorToCenter;
00313 
00314   //Is the point above the horizon ? - return
00315   if(vectorToCenterWorld.z > -5 * yFactor) return false;
00316   
00317   double a1 = cameraMatrix.translation.x,
00318          a2 = cameraMatrix.translation.y,
00319          a3 = cameraMatrix.translation.z,
00320          b1 = vectorToCenterWorld.x,
00321          b2 = vectorToCenterWorld.y,
00322          b3 = vectorToCenterWorld.z;
00323   
00324   pointOnField.x = int((a1 * b3 - a3 * b1) / b3 + 0.5);
00325   pointOnField.y = int((a2 * b3 - a3 * b2) / b3 + 0.5);
00326 
00327   return abs(pointOnField.x) < 10000 && abs(pointOnField.y) < 10000;
00328 }
00329 
00330 void RBridgeSpecialist::createValidities(RBridgeSpecialist::SegmentInfo& info){
00331   //only landmark validation done yet
00332   if (info.skyblue== 0 || info.yellow == 0) info.lmValidityYellow = 0;
00333   else info.lmValidityYellow = 1-  2 *  (fabs((double) info.yellow/(double)(info.yellow + info.skyblue) - 0.5)  );
00334 
00335   if (info.orange== 0 || info.skyblue == 0) info.lmValidityOrange = 0;
00336   else info.lmValidityOrange = 1-  2 *  (fabs((double) info.skyblue/(double)(info.skyblue + info.orange) - 0.5)  ); 
00337 }
00338 
00339 void RBridgeSpecialist::findBridgeMark(RBridgeSpecialist::SegmentInfo& si){
00340   //if (si.size < 6) return; //element to small
00341   double boxWidth;
00342   //testing for the right filter
00343   bool isMark = (si.lmValidityOrange > 0.3 || si.lmValidityYellow > 0.3) &&
00344     (boxWidth = (si.rect.bottomRight - si.rect.bottomLeft).abs()) > 5 &&
00345     (si.rect.upperLeft - si.rect.bottomLeft).abs() * 3 < boxWidth;
00346 
00347   if (!isMark) return;
00348   BitePoint::Position pos = getPosition(si);
00349   if (pos == BitePoint::numOfPositions) return; //undefined
00350   Vector2<int> markCenter;
00351 
00352   Rectangle& r = si.rect;
00353    
00354   Vector2<double> leftCenter = (r.upperLeft + r.bottomLeft)/2;
00355   Vector2<double> rightCenter = (r.upperRight + r.bottomRight)/2;
00356   Vector2<double> leftToRight = (rightCenter - leftCenter)/6;
00357   Vector2<int> leftStart(
00358     (int)(leftCenter.x + leftToRight.x),
00359     (int)(leftCenter.y + leftToRight.y));
00360   Vector2<int> rightStart(
00361     (int)(rightCenter.x - leftToRight.x),
00362     (int)(rightCenter.y - leftToRight.y));
00363 
00364   if (boxWidth < 60)
00365   {
00366     markCenter.x = (int)((leftCenter.x + rightCenter.x)/2);
00367     markCenter.y = (int)((leftCenter.y + rightCenter.y)/2);
00368   }
00369   else
00370   {
00371     colorClass c = noColor;
00372     Vector2<int> temp;
00373     edgeScanner.setDirection(leftToRight);
00374       DOT(imageProcessor_general, leftStart.x,leftStart.y,
00375       Drawings::white, Drawings::green);
00376       RasterSpecialist::Box b(1,1,imageWidth-2,imageWidth-2);
00377     while (b.inside(leftStart.x,leftStart.y)){
00378       c = getColor(leftStart);
00379       if (c == si.rightColor){
00380         markCenter = leftStart;
00381         break;
00382       }
00383       edgeScanner.skip(leftStart.x,leftStart.y);
00384     }
00385   }
00386   //mid of main-mark found  
00387   DOT(imageProcessor_general, markCenter.x,markCenter.y,
00388     Drawings::white, Drawings::blue);
00389   Vector2<int> up;
00390   up.x = (int)(rightCenter.y - leftCenter.y);
00391   up.y = (int) -(rightCenter.x - (int)leftCenter.x);
00392   up = up/5;
00393   
00394   
00395   //now searching for offset to black-line
00396   Vector2<int> upper(markCenter + up);
00397   Vector2<int> lower(markCenter - up);
00398   OUTPUT(idText,text,"up: " << up.x << " " << up.y);
00399   
00400   DOT(imageProcessor_general, upper.x,upper.y,
00401     Drawings::white, Drawings::blue); 
00402   DOT(imageProcessor_general, lower.x,lower.y,
00403     Drawings::white, Drawings::red);
00404 
00405   Geometry::Line perp;
00406   perp.base.x = (double)markCenter.x;
00407   perp.base.y = (double)markCenter.y;
00408   perp.direction = pHorizon.direction;
00409 
00410   Vector2<int> lScan,rScan,lineCenter;
00411   int leftAbs = 10000,rightAbs = 10000;
00412   float offset = 0;
00413   lScan = lower;
00414   rScan = lower;
00415   Vector2<int> temp;
00416   if (getColor(lScan.x,lScan.y) == lineColor)
00417   {
00418     edgeScanner.scan(lScan.x,lScan.y,-leftToRight);
00419     edgeScanner.scan(rScan.x,rScan.y,leftToRight);
00420     lineCenter = (lScan + rScan)/2;
00421     offset = getDistanceToLine(perp,lineCenter);
00422   }
00423   else
00424   { 
00425     colorClass c;
00426     edgeScanner.setDirection(-leftToRight);
00427     while(edgeScanner.colorScan(lScan.x,lScan.y,c)){
00428       if (c == lineColor)
00429       {
00430         lScan = (lScan + temp)/2;
00431         leftAbs = (lScan - lower).abs();
00432         break;
00433       }
00434       //edgeScanner.skip(lScan.x,lScan.y);
00435       temp = lScan;       
00436     }
00437 
00438     c = noColor;
00439     edgeScanner.setDirection(leftToRight);
00440     while(edgeScanner.colorScan(rScan.x,rScan.y,c)){
00441       if (c == lineColor)
00442       { 
00443         rScan = (rScan + temp)/2;
00444         rightAbs = (rScan - lower).abs();
00445 
00446         break;
00447       }
00448       //edgeScanner.skip(rScan.x,rScan.y);
00449       temp = rScan;       
00450     }
00451     
00452     if (leftAbs < rightAbs)
00453     {
00454       offset = (float)leftAbs;
00455       lineCenter = lScan;
00456     }
00457     else
00458     { 
00459       offset = (float)-rightAbs;
00460       lineCenter = rScan;
00461     }
00462   }
00463   
00464   offset = offset*100/(float)boxWidth;
00465   DOT(imageProcessor_general, lineCenter.x,lineCenter.y,
00466     Drawings::white, Drawings::pink);
00467   OUTPUT(idText,text,"offset: " << offset);
00468   double distance;
00469   double height = (r.upperLeft -r.bottomLeft).abs();
00470   if (boxWidth > 120)
00471     distance = Geometry::getDistanceBySize(
00472       rip->image.cameraInfo,133,boxWidth,markCenter.x,markCenter.y);
00473   else
00474     distance = Geometry::getDistanceBySize(
00475       rip->image.cameraInfo,13,height,markCenter.x,markCenter.y);
00476   OUTPUT(idText,text,"distance: " << distance);
00477   Vector2<double> angles;
00478   Vector2<double> inImage((double)markCenter.x,(double)markCenter.y);
00479   calculateAnglesForPoint(
00480     inImage,rip->cameraMatrix,rip->image.cameraInfo,angles);
00481   OUTPUT(idText,text,"angle: " << angles.x);
00482   rip->specialPercept.ocBridge.bitePoint[pos].addPercept(angles.x,distance,offset);
00483 }
00484 
00485 BitePoint::Position RBridgeSpecialist::getPosition(RBridgeSpecialist::SegmentInfo& mark){
00486   edgeScanner.setDirection(horizon.direction);
00487   colorClass c,comp;
00488   Vector2<int> scan;
00489   mark.leftColor = noColor;
00490   mark.rightColor = noColor;
00491   Vector2<double> toRight = (mark.rect.upperRight - mark.rect.upperLeft)/7;
00492   scan.x = (int)(mark.rect.upperLeft.x + mark.rect.bottomLeft.x)/2 + (int)toRight.x;
00493   scan.y = (int)(mark.rect.upperLeft.y + mark.rect.bottomLeft.y)/2 + (int)toRight.y;
00494   DOT(imageProcessor_general, scan.x,scan.y,
00495     Drawings::white, Drawings::red);
00496   if (mark.lmValidityOrange > mark.lmValidityYellow)
00497     comp = orange;
00498   else comp = yellow;
00499   c = getColor(scan.x,scan.y);
00500   do{
00501     if(c == skyblue)
00502     {
00503       mark.leftColor = skyblue;
00504       mark.rightColor = comp;
00505       break;
00506     }
00507     else if (c == comp)
00508     {
00509       mark.leftColor = comp;
00510       mark.rightColor = skyblue;
00511       break;
00512     }
00513   }while (edgeScanner.colorScan(scan.x,scan.y,c));
00514 
00515   if (mark.leftColor == noColor) return BitePoint::numOfPositions;
00516   OUTPUT(idText,text,"finished type:" << 
00517     ColorClasses::getColorName(mark.leftColor) << " " << 
00518     ColorClasses::getColorName(mark.rightColor));
00519   if (comp == yellow)
00520   {
00521     if(mark.leftColor == skyblue)
00522       return BitePoint::frontleft;
00523     else
00524       return BitePoint::behindleft;
00525   }
00526   else
00527   {
00528     if(mark.leftColor == skyblue)
00529       return BitePoint::behindright;
00530     else
00531       return BitePoint::frontright;
00532   }
00533 }

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