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

Modules/ImageProcessor/RasterImageProcessor/RFieldSpecialist.cpp

Go to the documentation of this file.
00001 /**
00002 * @file Modules/ImageProcessor/RasterImageProcessor/RFieldSpecialist.cpp
00003 * 
00004 * This file contains an class for image processing and object recognition 
00005 *
00006 * @author <A href="damd@free.fr">DEOM Damien</A>
00007 * 
00008 */
00009 
00010 #include "RFieldSpecialist.h"
00011 
00012 
00013 RFieldSpecialist::RFieldSpecialist(RasterImageProcessor &processor,RasterStrategy &strat):
00014   RasterSpecialist(processor), edgeScanner(processor)
00015 {
00016   strategy = &strat;
00017 
00018   segments_img.reserve(3);
00019 
00020   defaultParam = new processParam();
00021 
00022   lineInside = LinesPercept::numberOfLineTypes;
00023 
00024 }
00025 
00026 RFieldSpecialist::~RFieldSpecialist()
00027 {
00028   delete defaultParam;
00029 }
00030 
00031 int RFieldSpecialist::getType()
00032 {
00033   return __RFieldSpecialist;  
00034 }
00035 
00036 void RFieldSpecialist::init()
00037 { 
00038   preScanNeeded = true;
00039   postScanNeeded = false;
00040 
00041   lst_pts.clear();
00042 
00043   int i;
00044   for (i = 0; i< (int)segments_img.size(); ++i)
00045     segments_img[i].clear();
00046 }
00047 
00048 void RFieldSpecialist::invokeOnPreScan(int x,int y){
00049   
00050   if (!strategy->insideField) temp = Vector2<int>(x,y);
00051   else{
00052     
00053     point tmp2 = Vector2<int>(x,y);
00054 
00055     //search for edges to widen the pairs to the edges of the object
00056 
00057     edgeScanner.threshold = 20;
00058     edgeScanner.scanWest(temp.x,temp.y);
00059     edgeScanner.scanEast(tmp2.x,tmp2.y);
00060 
00061     if (tmp2.x - temp.x < 4) return;
00062 
00063     horLinePair* lp= new horLinePair(temp,tmp2);
00064 
00065     lst_pts.push_front(lp);
00066 
00067     LINE(imageProcessor_ground,
00068       lp->pt1().x,lp->pt1().y, lp->pt2().x,lp->pt2().y, 
00069       0.5, Drawings::ps_solid, Drawings::gray);
00070     
00071   }
00072 }
00073 
00074 int RFieldSpecialist::id(LinesPercept::LineType l) {
00075   switch (l) {
00076     case LinesPercept::field :       return 0;
00077     case LinesPercept::border :      return 1;
00078     case LinesPercept::yellowGoal :  return 2;
00079     case LinesPercept::skyblueGoal : return 3;
00080     default : return -1;
00081   }
00082 }
00083 
00084 LinesPercept::LineType RFieldSpecialist::id(int i) {
00085   switch (i) {
00086     case 0 : return LinesPercept::field ;
00087     case 1 : return LinesPercept::border;
00088     case 2 : return LinesPercept::yellowGoal;
00089     case 3 : return LinesPercept::skyblueGoal;
00090     default : return LinesPercept::field;
00091   }
00092 }
00093 
00094 void RFieldSpecialist::invokeOnPostScan(int x,int y) {}
00095 
00096 
00097 void RFieldSpecialist::addLinePoint(LinesPercept::LineType line , point & v, int& p) {
00098 
00099   segments_img[id(line)].push_front(new edge(v,(unsigned short)p));
00100 
00101 }
00102 
00103 
00104 bool isEqual (double & a1, double & a2, float tol) {
00105   return (fabs(a1-a2)<=tol);
00106 }
00107 
00108 
00109 void RFieldSpecialist::fusionLines(lstLinePair& lst) {
00110 
00111   lstLinePair::iterator it, it2;
00112   double angle;
00113 
00114 
00115   for (it = lst.front();!it.end();++it) {
00116 
00117     it2 = lst.front();
00118 
00119     while(!it2.end() && it2->getNext() && it2->getNext()!= *it) {
00120 
00121       angle = (int)theta2(*it, it2->getNext())%180;
00122 
00123       Vector2<double> v = mil (**it2);
00124 
00125       if (angle<=8 || angle >= 172 &&
00126         Geometry::getDistanceToLine(makeLine(*it),v) <1) {
00127 
00128           point p1, p2;
00129 
00130           if (Geometry::distance(it->p1, it2->getNext()->p1) >
00131             Geometry::distance(it->p1, it2->getNext()->p2))
00132             p1 = it2->getNext()->p1;
00133 
00134           else p1 = it2->getNext()->p2;
00135 
00136           if (Geometry::distance(it2->getNext()->p1, it->p1) >
00137             Geometry::distance(it2->getNext()->p1, it->p2))
00138             p2 = it->p1;
00139 
00140           else p2 = it->p2;
00141 
00142           it->p1 = p1;
00143           it->p2 = p2;
00144 
00145           lst.erase(*it2);
00146 
00147       } else
00148         if(!++it2) break;
00149 
00150     }
00151   }
00152 }
00153 
00154 bool RFieldSpecialist::makeLines(lstFig& lst, lstLinePair& lines,
00155                  const processParam* prParam) {
00156 
00157   int size_t = -1;
00158   unsigned int min_size = prParam->min_size;
00159   unsigned int step_alpha = prParam->step_alpha;
00160   unsigned int tol_alpha = prParam->tol_alpha;
00161 
00162   unsigned int i;
00163 
00164   lstFig::iterator first(lst.front());
00165   lstFig::iterator next = first;
00166   
00167 
00168   if (!(next+=step_alpha)) return false;
00169 
00170   unsigned c = lst.getSize(); 
00171 
00172   double * tab_angle = new double[c];
00173   unsigned int * tab_nb = new unsigned int[c];
00174   LinePair2** tab_line = new LinePair2*[c];
00175 
00176 
00177   for(i= 0;i<c;++i) {tab_line[i] = 0;tab_angle[i]=0;tab_nb[i]=0;}
00178 
00179   do {
00180     
00181     point p1 = first->toConsider();
00182     point p2 = next->toConsider();
00183 
00184     double angle = theta2(p1,p2);
00185 
00186     bool too_inclined = (size_t>=0) ?
00187       !isEqual(tab_angle[size_t],angle,(float)tol_alpha) : false;
00188 
00189     if (size_t==-1) {  // initial state
00190 
00191         ++size_t;
00192         tab_line[size_t] = new LinePair2(p1,p2);
00193         tab_angle[size_t] = angle;
00194         tab_nb[size_t] = 1;
00195 
00196     } else if (!too_inclined) { // if aligned to the precedent line
00197 
00198       ++tab_nb[size_t];
00199       tab_line[size_t]->p2 = p1;  
00200 
00201     } else {  // add a new line
00202 
00203       if (tab_nb[size_t]<min_size) {
00204         delete tab_line[size_t];
00205       } else {
00206         ++size_t;
00207       }
00208         
00209       tab_line[size_t] = new LinePair2(p1, p2);
00210       tab_angle[size_t] = angle;
00211       tab_nb[size_t] = 1;
00212     }
00213 
00214     next = ++first;
00215 
00216   } while (next+=step_alpha);
00217 
00218  
00219   bool valid = false;
00220   for (i = 0;i<=(unsigned)size_t;++i) {
00221     
00222     if (tab_nb[i] >= min_size) {
00223       
00224       valid = true;
00225       lines.push_front(tab_line[i]);
00226     } else {
00227 
00228       delete tab_line[i];
00229 
00230     }
00231   }
00232 
00233   delete [] tab_angle;
00234   delete [] tab_line;
00235   delete [] tab_nb;
00236 
00237   return valid;
00238 
00239 }
00240 
00241 
00242 void RFieldSpecialist::executePostProcessing(){
00243 
00244   if (lst_pts.getSize() < 4) return;
00245 
00246   createLinearSegment(lst_pts);
00247 
00248   lstFig::iterator it = lst_pts.front();
00249 
00250   lstLinePair res;
00251 
00252   if (!makeLines(lst_pts, res, defaultParam)) return;
00253 
00254   lstLinePair::iterator cur2 = res.front();
00255   
00256   while (!cur2.end()) {
00257 
00258     LINE(imageProcessor_ground,
00259     cur2->p1.x, cur2->p1.y, cur2->p2.x,cur2->p2.y,
00260     1, Drawings::ps_solid,
00261     Drawings::white);
00262 
00263     ++cur2;
00264   } 
00265 
00266   fusionLines(res);
00267 
00268   checkRamp(res);
00269 
00270   res.clear();
00271 }
00272 
00273 void RFieldSpecialist::drawCross(goal_line g, point& v) {
00274 
00275   switch(g) {
00276     case YELLOW :
00277       LINE(imageProcessor_ground,
00278         v.x-4,v.y-4,v.x+4, v.y+4, 
00279         2, Drawings::ps_solid, Drawings::yellow);
00280       LINE(imageProcessor_ground,
00281             v.x-4,v.y+4,v.x+4, v.y-4, 
00282         2, Drawings::ps_solid, Drawings::yellow);
00283       break;
00284     case SKYBLUE:
00285       LINE(imageProcessor_ground,
00286         v.x-4,v.y-4,v.x+4, v.y+4, 
00287         2, Drawings::ps_solid, Drawings::blue);
00288       LINE(imageProcessor_ground,
00289             v.x-4,v.y+4,v.x+4, v.y-4, 
00290         2, Drawings::ps_solid, Drawings::blue);
00291       break;
00292     default: 
00293       LINE(imageProcessor_ground,
00294         v.x-4,v.y-4,v.x+4, v.y+4, 
00295         2, Drawings::ps_solid, Drawings::black);
00296       LINE(imageProcessor_ground,
00297         v.x-4,v.y+4,v.x+4, v.y-4, 
00298         2, Drawings::ps_solid, Drawings::black);
00299   }
00300 
00301 }
00302 void RFieldSpecialist::drawCircle(goal_line g, point& v) {
00303   switch(g) {
00304     case YELLOW :
00305       CIRCLE(imageProcessor_ground,v.x, v.y, 5, 1, 
00306       Drawings::ps_solid, Drawings::yellow);
00307       break;
00308     case SKYBLUE:
00309       CIRCLE(imageProcessor_ground,v.x, v.y, 5, 1, 
00310       Drawings::ps_solid, Drawings::blue);
00311       break;
00312     default: 
00313       CIRCLE(imageProcessor_ground,v.x, v.y, 5, 1, 
00314       Drawings::ps_solid, Drawings::black);
00315   }
00316 }
00317 
00318 void RFieldSpecialist::drawLine(goal_line g, LinePair2& lp) {
00319   switch(g) {
00320     case YELLOW :
00321       LINE(imageProcessor_ground,lp.p1.x, lp.p1.y, lp.p2.x, lp.p2.y, 1,
00322       Drawings::ps_solid, Drawings::yellow);
00323       break;
00324     case SKYBLUE:
00325       LINE(imageProcessor_ground,lp.p1.x, lp.p1.y, lp.p2.x, lp.p2.y, 1,
00326       Drawings::ps_solid, Drawings::blue);
00327       break;
00328     default: 
00329       LINE(imageProcessor_ground,lp.p1.x, lp.p1.y, lp.p2.x, lp.p2.y, 1,
00330       Drawings::ps_solid, Drawings::black);
00331   }
00332 }
00333 
00334 unsigned int RFieldSpecialist::analyzeLines() {
00335 
00336   lstLinePair::iterator it;
00337   double angle;
00338   unsigned i;
00339 
00340   // calculate the most representative lines exept borders
00341   double max_length;
00342   LinePair2** max_lines = new LinePair2*[vecLines.size()];
00343 
00344   for (i = 1; i<vecLines.size();++i) {
00345 
00346     max_lines[i] = 0;
00347     max_length = 0;
00348 
00349     for (it = vecLines[i].front();!it.end() ;++it) {
00350 
00351       double length = it->getLength();
00352 
00353       if (length>max_length) {
00354         max_length = length;
00355         max_lines[i] = *it;
00356       }
00357     }
00358   }
00359 
00360   max_lines[0] = 0;
00361   angle = 180;
00362   if (max_lines[1])
00363     for (it = vecLines[0].front();!it.end() ;++it) {
00364 
00365       double tmp = 90 - (int)theta2(*it, max_lines[1])%180;
00366       OUTPUT(idText,text, "analyse mil  " << tmp);
00367       if (tmp<angle) {
00368         angle = tmp;
00369         max_lines[0] = *it;
00370       }
00371     }
00372   
00373   OUTPUT(idText,text, "max analyse mil  " << angle);
00374   goal_line seen_goal;
00375 
00376   if (max_lines[2]) {
00377     seen_goal = YELLOW;
00378   }
00379   else if (max_lines[3]) {
00380     seen_goal = SKYBLUE;
00381   } else seen_goal = NONE; 
00382 
00383 
00384   for (i = 0; i< vecLines.size(); ++i) {
00385 
00386     lstLinePair& lst = vecLines[i];
00387 
00388     for (it = lst.front();!it.end() && it->getNext();++it) {
00389 
00390       angle = (int)theta2(*it, it->getNext())%180;
00391 
00392       if (angle>10 && angle<170) {
00393     
00394         point v;
00395         Geometry::Line l1 = makeLine(*it);
00396         Geometry::Line l2 = makeLine(it->getNext());
00397 
00398         Geometry::getIntersectionOfLines(l1, l2, v);
00399 
00400         drawCross(seen_goal, v);
00401       
00402       }
00403     }
00404   }
00405 
00406   double size_fact;
00407 
00408   if (max_lines[1] ) {
00409 
00410     size_fact = (seen_goal==NONE) ? 0 : max_lines[1]->getLength()/max_lines[seen_goal==YELLOW ? 2 : 3]->getLength();
00411 
00412     OUTPUT(idText,text, "size fact " << size_fact);
00413 
00414     if (size_fact<2.6) {
00415       drawLine(seen_goal, (*max_lines[1]));
00416     } else {
00417       LINE(imageProcessor_ground,
00418       max_lines[1]->p1.x, max_lines[1]->p1.y, 
00419       max_lines[1]->p2.x, max_lines[1]->p2.y, 
00420       1, Drawings::ps_solid, Drawings::green);
00421     }
00422 
00423     if (max_lines[0]) {
00424       point v;
00425 
00426       Geometry::getIntersectionOfLines(makeLine(max_lines[0]),makeLine(max_lines[1]), v);
00427 
00428       drawCircle(seen_goal, v);
00429     }
00430   }
00431 
00432 
00433   delete [] max_lines;
00434 
00435 
00436   return 0;
00437 
00438 
00439 }
00440 
00441 void RFieldSpecialist::checkRamp(lstLinePair & ramp) {
00442 
00443   lstLinePair::iterator it2;
00444 
00445   double max_length = 0;
00446   LinePair2* max_line = 0;
00447 
00448   for (it2 = ramp.front();!it2.end() ;++it2) {
00449 
00450     double length = it2->getLength();
00451 
00452     if (length>max_length) {
00453       max_length = length;
00454       max_line = *it2;
00455     }
00456   }
00457 
00458   if (max_line) 
00459   { 
00460     LINE(imageProcessor_ground,
00461     max_line->p1.x, max_line->p1.y, max_line->p2.x,max_line->p2.y,
00462     3, Drawings::ps_solid,
00463     Drawings::green);
00464 
00465     OUTPUT(idText,text, "angle " << (int)theta2(max_line->p1,max_line->p2)%180);
00466 
00467     int px = max_line->p1.y > max_line->p2.y ? max_line->p1.x : max_line->p2.x;
00468     float d = (float)px/(float)rip->maxX;
00469 
00470     point pStart;
00471     point pEnd;
00472 
00473     if (max_line->p1.y > max_line->p2.y){
00474       pStart=max_line->p1;
00475       pEnd=max_line->p2;
00476     } else {
00477       pStart=max_line->p2;
00478       pEnd=max_line->p1;
00479     }
00480 
00481     Vector2<int> relativeStart;
00482     Geometry::calculatePointOnField(
00483       pStart.x,pStart.y,
00484       rip->cameraMatrix,
00485       rip->image.cameraInfo,relativeStart);
00486 
00487     Vector2<int> relativeEnd;
00488 
00489     Geometry::calculatePointOnField(
00490       pEnd.x,pEnd.y,
00491       rip->cameraMatrix,
00492       rip->image.cameraInfo,
00493       relativeEnd);
00494 
00495 
00496     rip->specialPercept.ocRedLine.addPercept(
00497       relativeStart,relativeEnd
00498       ,pStart,pEnd,
00499       (int)theta2(max_line->p1,max_line->p2)%180);
00500 
00501     
00502     OUTPUT(idText,text, "relative position : " << d);
00503 
00504   }
00505 
00506 }
00507 
00508 /*
00509  * Changelog:
00510  *
00511  * $Log: RFieldSpecialist.cpp,v $
00512  * Revision 1.8  2004/09/08 13:31:57  wachter
00513  * - Fixed some warnings
00514  *
00515  * Revision 1.7  2004/09/08 12:41:43  wachter
00516  * - Fixed some warnings
00517  * - Fixed some documentation in network-code
00518  *
00519  * Revision 1.6  2004/09/07 16:01:15  deom
00520  * Documentation corrected
00521  *
00522  * Revision 1.5  2004/09/06 12:02:26  schmidtb
00523  * commented almost all members, removed warnings in documentation
00524 
00525  * did further code clean up
00526  *
00527  * Revision 1.4  2004/09/02 09:31:19  deom
00528  * commented rfieldspecialist
00529  *
00530  * Revision 1.3  2004/09/02 07:59:29  schmidtb
00531  * Added RasterImageProcessor to repository, because we used it for the OpenChallenge.
00532  *
00533  * Revision 1.42  2004/06/17 14:18:22  kerdels
00534  * fixed bug in rfieldspecialist, changed threshold for bridge-detection
00535  *
00536  * Revision 1.41  2004/06/11 12:43:40  deom
00537  * no message
00538  *
00539  * Revision 1.40  2004/06/04 12:43:05  deom
00540  * optimized
00541  *
00542  * Revision 1.39  2004/06/03 14:22:51  deom
00543  * debugged
00544  *
00545  * Revision 1.38  2004/06/02 16:03:53  deom
00546  * merged different versions of FieldSpecialist
00547  *
00548  * Revision 1.37  2004/06/01 18:52:52  deom
00549  * memory leak problem solved
00550  *
00551  * Revision 1.36  2004/05/31 17:19:30  deom
00552  * *** empty log message ***
00553  *
00554  * Revision 1.35  2004/05/27 16:49:30  deom
00555  * new parameter set + some minor changes
00556  *
00557  * Revision 1.34  2004/05/26 14:40:36  schumann
00558  * detection of red line and special percept
00559  *
00560  * Revision 1.33  2004/05/25 13:27:34  schmidtb
00561  * modified version of rip for open-challenge
00562  *
00563  * Revision 1.32  2004/05/22 19:03:40  deom
00564  * -now recognizes the red line
00565  * -all the data required for the positionning are computed
00566  *
00567  * Revision 1.28  2004/05/22 16:56:39  pg_dade
00568  * -now recognizes the red line
00569  * -all the data required for the positionning are computed
00570  *
00571  * Revision 1.26  2004/04/15 19:08:34  pg_besc
00572  * merged code
00573  *
00574  * Revision 1.29  2004/03/30 13:51:38  schmidtb
00575  * integrated input stream from file
00576  *
00577  * Revision 1.28  2004/03/29 15:25:16  deom
00578  * - the basical segmentation tools are now fast completely debbuged.
00579  * - seem to work pretty good now
00580  * - somes parameters need to be tuned
00581  *
00582  * Revision 1.27  2004/03/23 15:50:26  deom
00583  * now uses two scan methods
00584  *
00585  * Revision 1.26  2004/03/21 21:59:06  deom
00586  * The new scan functions intergrated to RfieldSpecialist. The lines recognition works at 90%
00587  *
00588  * Revision 1.25  2004/03/19 22:06:49  deom
00589  * now based on  the segmentationTools class
00590  *
00591  * Revision 1.24  2004/03/15 15:47:51  roefer
00592  * Warnings removed
00593  *
00594  * Revision 1.23  2004/03/15 11:21:45  deom
00595  * optimized
00596  *
00597  * Revision 1.22  2004/03/15 01:17:35  deom
00598  * debugged, now recognizes all predetermined forms
00599  *
00600  * Revision 1.21  2004/03/14 12:51:58  deom
00601  * added an accurate scan method
00602  *
00603  * Revision 1.20  2004/03/12 14:39:12  deom
00604  * debugged
00605  *
00606  * Revision 1.19  2004/03/12 01:37:58  deom
00607  * added some functions required for the lines analysis
00608  *
00609  * Revision 1.18  2004/03/11 19:21:01  deom
00610  * pursued debugging and parametrisation
00611  *
00612  * Revision 1.17  2004/03/11 12:19:00  deom
00613  * debbuged RFieldspecialist
00614  *
00615  * Revision 1.16  2004/03/01 14:17:25  koh
00616  * added new strategy "RFlexibleStrategy" + new specialist "EnemyOnlySpecialist";
00617  * changed references to "RDefaultStrategy" to references to "RasterStrategy" in RFieldSpecialist
00618  * added Geometry::Line horizon to "RasterStrategy"
00619  *
00620  * Revision 1.15  2004/03/01 12:16:28  wachter
00621  * Bug commented out.
00622  *
00623  * Revision 1.14  2004/02/29 20:06:16  deom
00624  * detects complex lines ( but need to be debuged)
00625  *
00626  * Revision 1.13  2004/02/24 20:01:41  wachter
00627  * urgent message for damien added
00628  *
00629  * Revision 1.12  2004/02/23 12:47:07  roefer
00630  * Warnings removed
00631  *
00632  * Revision 1.11  2004/02/22 19:12:54  deom
00633  * now recognize simple lines
00634  *
00635  * Revision 1.9  2004/02/16 05:00:48  deom
00636  * basical version that show edges
00637  *
00638  * Revision 1.8  2004/01/26 22:21:09  schmidtb
00639  * bugfixed BoxSpecialist
00640  *
00641  * Revision 1.7  2004/01/26 14:50:08  wachter
00642  * Changelog added
00643  *
00644  *
00645  */
00646 

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