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

Modules/ImageProcessor/RasterImageProcessor/REdgeDetection.h

Go to the documentation of this file.
00001 /**
00002 * @file Modules/ImageProcessor/RasterImageProcessor/REdgeDetection.h
00003 * 
00004 * This file contains an utility-class for detecting edges in digital images. 
00005 *
00006 * @author <A href="mailto:sadprofessor@web.de">Bernd Schmidt</A>
00007 */
00008 
00009 #ifndef __REdgeDetection_h_
00010 #define __REdgeDetection_h_
00011 
00012 #include "Representations/Perception/Image.h"
00013 #include "Modules/ImageProcessor/ImageProcessor.h"
00014 #include "Modules/ImageProcessor/ImageProcessorTools/ColorCorrector.h"
00015 #include "Modules/ImageProcessor/ImageProcessorTools/SUSANEdgeDetectionLite.h"
00016 
00017 /**
00018 * @class REdgeDetection
00019 * Utility-class for edge-detection.
00020 */
00021 class REdgeDetection
00022 {  
00023 
00024 public:
00025 
00026   /**
00027   * Default constructor.
00028   * @param processor The image processor interfaces.
00029   */
00030   REdgeDetection(ImageProcessor& processor);
00031   
00032   /**Destructor*/
00033   ~REdgeDetection();
00034   /** Threshold for edge scans */
00035   int threshold;
00036 
00037   /** Holds the last visited x-coordinate of a scan */
00038   int tempX;
00039 
00040   /** Holds the last visited y-coordinate of a scan */
00041   int tempY;
00042 
00043   /** Scans to the right side of the image and detects edges.
00044   * The position of the edge is stored in x,y. 
00045   * @param x Starting x-coordinate of the scan.
00046   * @param y Starting y-coordinate of the scan.
00047   * @return Tells if an edge was found at the last run.
00048   */
00049   bool scanEast(int& x, int& y);
00050   /** Scans to the left side of the image and detects edges.
00051   * The position of the edge is stored in x,y. 
00052   * @param x Starting x-coordinate of the scan.
00053   * @param y Starting y-coordinate of the scan.
00054   * @return Tells if an edge was found at the last run.
00055   */
00056   bool scanWest(int& x, int& y);
00057   /** Scans to the top and detects edges.
00058   * The position of the edge is stored in x,y. 
00059   * @param x Starting x-coordinate of the scan.
00060   * @param y Starting y-coordinate of the scan.
00061   * @return Tells if an edge was found at the last run.
00062   */
00063   bool scanNorth(int& x, int& y);
00064   
00065   /** Scans to the bottom and detects edges.
00066   * The position of the edge is stored in x,y. 
00067   * @param x Starting x-coordinate of the scan.
00068   * @param y Starting y-coordinate of the scan.
00069   * @return Tells if an edge was found at the last run.
00070   */
00071   bool scanSouth(int& x, int& y);
00072 
00073   /** Scans to the right side and detects edges of balls.
00074   * The position of the edge is stored in x,y.
00075   * @param x Starting x-coordinate of the scan.
00076   * @param y Starting y-coordinate of the scan.
00077   * @return Tells if an edge was found at the last run.
00078   */
00079   bool ballScanEast(int& x, int& y);
00080   
00081   /** Scans to the left side and detects edges of balls.
00082   * The position of the edge is stored in x,y.
00083   * @param x Starting x-coordinate of the scan.
00084   * @param y Starting y-coordinate of the scan.
00085   * @return Tells if an edge was found at the last run.
00086   */
00087   bool ballScanWest(int& x, int& y);
00088 
00089   /** Follows the given direction,
00090   * and determines edges by the sum of all three channels.
00091   * The position of the edge is stored in x and y.
00092   * @param x The starting x-value.
00093   * @param y The starting y-value.
00094   * @param direction The direction of the scan.
00095   * @return edge was found*/
00096   bool scan(int& x,int& y,Vector2<double> direction);
00097 
00098   /** Follows the given direction,
00099   * and determines edges by the sum of all three channels.
00100   * The position of the edge is stored in x and y.
00101   * Fills the colorBuffer while scanning, so the client
00102   * can determine with the colorBuffer-Array what kind of
00103   * object was found.
00104   *
00105   * @param x The starting x-value.
00106   * @param y The starting y-value.
00107   * @param direction The direction of the scan.
00108   * @return edge was found*/
00109   bool bufferedScan(int& x,int& y,Vector2<double> direction);
00110 
00111   /** Follows the last given direction. Skips 3 pixels at the beginning
00112   * of each scan, while filling the buffer.
00113   *
00114   * @param x x-coordinate
00115   * @param y y-coordinate
00116   */ 
00117   bool bufferedScan(int& x,int& y);
00118 
00119   /** Follows the given direction,and searches for field-edge-points. 
00120   * Determines edges by the sum of the first two channels.
00121   * The position of the edge is stored in x and y.
00122   * @param x The starting x-value.
00123   * @param y The starting y-value.
00124   * @param direction The direction of the scan.
00125   * @return edge was found*/
00126   bool scanField(int& x,int& y,Vector2<double> direction);
00127 
00128   /** Follows the last given direction,and searches for field-edge-points. 
00129   * Determines edges by the sum of the first two channels.
00130   * The position of the edge is stored in x and y.
00131   * @param x The starting x-value.
00132   * @param y The starting y-value.
00133   * @return edge was found*/
00134   bool scanField(int& x,int& y);
00135 
00136   /** Follows the last given direction,
00137   * and determines edges by the sum of all three channels 
00138   *
00139   * @param x x-coordinate
00140   * @param y y-coordinate
00141   */
00142   bool scan(int& x,int& y);
00143 
00144   /** Follows the given direction,
00145   * and determines edges by looking for 
00146   * differences of the colorClass of two following pixels.
00147   * @param x The starting x-value.
00148   * @param y The starting y-value.
00149   * @param direction Teh direction of the color scan.
00150   * @param lastColor The color of the last scan.
00151   * @return edge was found
00152   */
00153   bool colorScan(int& x,int& y,Vector2<double> direction,colorClass& lastColor);
00154   
00155   /** Follows the current direction,
00156   * and determines edges by looking for 
00157   * differences of the colorClass of two following pixels.
00158   * @param x The starting x-value.
00159   * @param y The starting y-value.
00160   * @param lastColor The color of the last scan.
00161   * @return edge was found
00162   */
00163   bool colorScan(int& x,int& y,colorClass& lastColor);
00164   /** Follows the given direction,
00165   * and determines edges with help of the SUSANEdgeDetection.
00166   * The position of the edge is stored in x and y.
00167   * @param x The starting x-value.
00168   * @param y The starting y-value.
00169   * @param direction The direction of the scan.
00170   * @return edge was found*/  
00171   bool susanScan(int& x,int& y,Vector2<double> direction);
00172   /** Follows the given direction,
00173   * and determines edges by the sum of all three channels.
00174   * The position of the edge is stored in x and y.
00175   * @param x The starting x-coordinate.
00176   * @param y The starting y-coordinate.
00177   * @param x1 The x-coordinate of the end.
00178   * @param y1 The y-coordinate of the end.
00179   * @return edge was found*/  
00180   bool scan(int& x,int& y,int x1,int y1);
00181   /** Follows the given direction,
00182   * and determines edges by the sum of all three channels.
00183   * The position of the edge is stored in x and y.
00184   * @param x The starting x-coordinate.
00185   * @param y The starting y-coordinate.
00186   * @param x1 The x-coordinate of the end.
00187   * @param y1 The y-coordinate of the end.
00188   * @param lastColor The color of the last run.
00189   * @return edge was found*/  
00190   bool colorScan(int& x,int& y,int x1,int y1,colorClass& lastColor);
00191   /** Setter for member direction.
00192   *   @param dir The new direction.
00193   */
00194   inline void setDirection(Vector2<double> dir){
00195     cx = (dir.x<0)? -1 : 1;
00196     cy = (dir.y<0)? -1 : 1;
00197     dx = abs((int)(dir.x * 500.0f));
00198     dy = abs((int)(dir.y * 500.0f));
00199     if (dx>dy){
00200       e = dx - 2*dy;
00201       f = 2*(dx - dy);
00202       g = -2*dy;
00203     }
00204     else{
00205       e = dy - 2*dx;
00206       f = 2*(dy - dx);
00207       g = -2*dx;
00208     }
00209     direction = dir;
00210   }
00211   /** Returns a color from the color buffer.
00212   * @param index The index of the color.  
00213   * @return The color for the index.
00214   */
00215   inline colorClass getColor(int index){
00216     return colorBuffer[index];
00217   }
00218   /** Returns a range from the range buffer.
00219   * @param index The index of the range.  
00220   * @return The range for the index.
00221   */
00222   inline int getRange(int index){
00223     return ranges[index];
00224   }
00225   /** This function implements a edge filter for horizontal edges. 
00226   *   @param x x-coordinate.
00227   *   @param y y-coordinate.
00228   *   @return True, if vote for the edgness is greater than threshold.
00229   */
00230   inline bool isHorizontalEdge(int x, int y){
00231     return horizontalEdgeVote(x,y) > threshold;
00232   }
00233   /** This function implements a edge filter for horizontal edges. 
00234   *   @param x x-coordinate.
00235   *   @param y y-coordinate.
00236   *   @return A vote for the edgness.
00237   */
00238   inline int horizontalEdgeVote(int x,int y){
00239     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
00240     int cx1 = x-1;
00241     int cx2 = x+1;
00242     int a1 = ip.image.image[y][0][cx1];
00243     int b1 = ip.image.image[y][1][cx1];
00244     int c1 = ip.image.image[y][2][cx1];
00245     int a2 = ip.image.image[y][0][cx2];
00246     int b2 = ip.image.image[y][1][cx2];
00247     int c2 = ip.image.image[y][2][cx2];
00248 
00249     return abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00250   }
00251   /** This function implements a edge filter for vertical edges. 
00252   *   @param x x-coordinate.
00253   *   @param y y-coordinate.
00254   *   @return True, if vote for the edgness is greater than threshold.
00255   */
00256   inline bool isVerticalEdge(int x, int y){
00257     return verticalEdgeVote(x,y) > threshold;
00258   }
00259   /** This function implements a edge filter for vertical edges. 
00260   *   @param x x-coordinate.
00261   *   @param y y-coordinate.
00262   *   @return A vote for the edgness.
00263   */
00264   inline int verticalEdgeVote(int x,int y){
00265     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
00266     int cy1 = y-1;
00267     int cy2 = y+1;
00268     int a1 = ip.image.image[cy1][0][x];
00269     int b1 = ip.image.image[cy1][1][x];
00270     int c1 = ip.image.image[cy1][2][x];
00271     int a2 = ip.image.image[cy2][0][x];
00272     int b2 = ip.image.image[cy2][1][x];
00273     int c2 = ip.image.image[cy2][2][x];
00274 
00275     return abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00276   }
00277   /** This function implements a edge filter for the ball. 
00278   *   @param x x-coordinate.
00279   *   @param y y-coordinate.
00280   *   @return A vote for the edgness.
00281   */
00282   inline int ballEdgeVote(int x,int y){
00283     //could be different code as in crossEdgeVote()
00284     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
00285     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
00286     int vertical = 0;
00287     int horizontal = 0;
00288     int p1 = x-1;
00289     int p2 = x+1;
00290     int a1 = ip.image.image[y][0][p1];
00291     int b1 = ip.image.image[y][1][p1];
00292     int c1 = ip.image.image[y][2][p1];
00293     int a2 = ip.image.image[y][0][p2];
00294     int b2 = ip.image.image[y][1][p2];
00295     int c2 = ip.image.image[y][2][p2];
00296     
00297     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00298     
00299     p1 = y-1;
00300     p2 = y+1;
00301     a1 = ip.image.image[p1][0][x];
00302     b1 = ip.image.image[p1][1][x];
00303     c1 = ip.image.image[p1][2][x];
00304     a2 = ip.image.image[p2][0][x];
00305     b2 = ip.image.image[p2][1][x];
00306     c2 = ip.image.image[p2][2][x];
00307     
00308     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00309     
00310     return (vertical > horizontal) ? vertical : horizontal; 
00311   }
00312   /** This function implements a edge filter. 
00313   *   @param x x-coordinate.
00314   *   @param y y-coordinate.
00315   *   @return A vote for the edgness.
00316   */
00317   inline int crossEdgeVote(int x,int y){
00318     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
00319     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
00320     int vertical = 0;
00321     int horizontal = 0;
00322     int p1 = x-1;
00323     int p2 = x+1;
00324     int a1 = ip.image.image[y][0][p1];
00325     int b1 = ip.image.image[y][1][p1];
00326     int c1 = ip.image.image[y][2][p1];
00327     int a2 = ip.image.image[y][0][p2];
00328     int b2 = ip.image.image[y][1][p2];
00329     int c2 = ip.image.image[y][2][p2];
00330     
00331     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00332     
00333     p1 = y-1;
00334     p2 = y+1;
00335     a1 = ip.image.image[p1][0][x];
00336     b1 = ip.image.image[p1][1][x];
00337     c1 = ip.image.image[p1][2][x];
00338     a2 = ip.image.image[p2][0][x];
00339     b2 = ip.image.image[p2][1][x];
00340     c2 = ip.image.image[p2][2][x];
00341     
00342     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00343     
00344     return (vertical > horizontal) ? vertical : horizontal; 
00345   }
00346   /** This function implements a edge filter.
00347   *   Only looking at the gradients of the channels Y and U.
00348   *   @param x x-coordinate.
00349   *   @param y y-coordinate.
00350   *   @return A vote for the edgness.
00351   */
00352   inline int fieldEdgeVote(int x,int y){
00353     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
00354     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
00355     int vertical = 0;
00356     int horizontal = 0;
00357     int p1 = x-1;
00358     int p2 = x+1;
00359     int a1 = ip.image.image[y][0][p1];
00360     int b1 = ip.image.image[y][1][p1];
00361     int a2 = ip.image.image[y][0][p2];
00362     int b2 = ip.image.image[y][1][p2];
00363 
00364     
00365     horizontal = abs(a1 - a2) + abs(b1 - b2);
00366     
00367     p1 = y-1;
00368     p2 = y+1;
00369     a1 = ip.image.image[p1][0][x];
00370     b1 = ip.image.image[p1][1][x];
00371     a2 = ip.image.image[p2][0][x];
00372     b2 = ip.image.image[p2][1][x];
00373     
00374     vertical = abs(a1 - a2) + abs(b1 - b2);
00375     
00376     return (vertical > horizontal) ? vertical : horizontal; 
00377   }
00378   
00379   /** Implemented with ColorTable interface.
00380   * Corrects the color before classifying.
00381   * @param x x-coordinate of the requested pixel
00382   * @param y y-coordinate of the requested pixel
00383   * @return The classified color of the pixel.*/
00384   inline colorClass getColor(int x,int y){
00385     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return (colorClass)-1;
00386     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return (colorClass)-1;
00387 
00388     unsigned char cy = ip.image.image[y][0][x];
00389     unsigned char cu = ip.image.image[y][1][x];
00390     unsigned char cv = ip.image.image[y][2][x];
00391     ColorCorrector::correct(x,y,cy,cu,cv);
00392     return ip.colorTable.getColorClass(cy,cu,cv); 
00393   }
00394 
00395   /** Gives the next pixel of last scan. This is only for the scans that
00396     * use Bresenham's algorithm.
00397     *
00398     * @param x The x-coordinate.
00399     * @param y The y-coordinate.    
00400     */
00401   inline void skip(int& x,int& y){
00402     if (dx>dy){
00403       x+=cx;
00404       if (e<0) {
00405         y+=cy;
00406         e+=f;
00407       }
00408       else {
00409         e+=g;
00410       }
00411     }
00412     else{
00413       y+=cy;
00414       if (e<0) {
00415         x+=cx;
00416         e+=f;
00417       }
00418       else {
00419         e+=g;
00420       }
00421     }
00422   }
00423 
00424   /** Determines the first valid point on a run.
00425   *
00426   *   @param start The original start point.
00427   *   @param dir The direction.
00428   *   @return If the scan line intersects the image.
00429   */
00430   inline bool findStart(Vector2<int>& start,const Vector2<double>& dir){
00431     int dx = (int)(dir.x*300 + 0.5);
00432       int dy = (int)(dir.y*300 + 0.5);
00433 
00434     Vector2<int> rightBorder(start.x + dx,start.y + dy);
00435 
00436     return Geometry::clipLineWithRectangleCohenSutherland(
00437       Vector2<int>(1,1),
00438       Vector2<int>(ip.image.cameraInfo.resolutionWidth -2,ip.image.cameraInfo.resolutionHeight -2),
00439       start,
00440       rightBorder
00441       );
00442   }
00443 
00444   /** Getter for the size of the color-buffer 
00445   * @return size of the color-buffer*/
00446   inline int getBufferSize(){
00447     return bufferSize;
00448   }
00449 
00450 //Bresenham
00451 //inline void draw_line(int x0, int y0, int x1, int y1){
00452 //  int x,y=y0,dx = 2*(x1-x0),dy = 2*(y1-y0);
00453 //  int dydx = dy - dx, d = dy - dx/2;
00454 //  for(x=x0;x<=x1;x++){
00455 //    DOT(imageProcessor_general,x,y,
00456 //      Drawings::white, Drawings::red);
00457 //    if(d<0) {d+= dy;}
00458 //    else {y+=1; d += dydx;}
00459 //  }
00460 //}
00461 
00462 
00463 private:
00464 
00465   /** the image processor interfaces */
00466   ImageProcessor& ip;
00467   
00468   /** an external edgeDetector */
00469   SUSANEdgeDetectionLite susanDetector; 
00470   /** current scan direction */
00471   Vector2<double> direction;
00472 
00473   /** a value for bresenham algorithm*/
00474   int e;
00475   /** a value for bresenham algorithm*/
00476   int f;
00477   /** a value for bresenham algorithm*/
00478   int g;
00479   /** a value for bresenham algorithm*/
00480   int dx;
00481   /** a value for bresenham algorithm*/
00482   int dy;
00483   /** a value for bresenham algorithm*/
00484   int cx;
00485   /** a value for bresenham algorithm*/
00486   int cy;
00487   /** current buffer size */
00488   int bufferSize;
00489   /** holds the color of the active pixel*/
00490   colorClass currentColor;
00491   /** holds the color of the previous pixel*/
00492   colorClass lastColor;
00493   
00494   /** The last range of a color scan. */
00495   int colorRange;
00496 
00497   /** This buffer is used to store the colors 
00498   * passed by a buffered scan-method during the last scan
00499   */
00500   colorClass colorBuffer[20];
00501 
00502   /** This buffer is used to store the ranges of the colors */
00503   int ranges[20];
00504 
00505   /** This function implements a edge filter. 
00506   *   @param x x-coordinate.
00507   *   @param y y-coordinate.
00508   *   @return A vote for the edgness.
00509   */
00510   inline int fastCrossEdgeVote(int x,int y){
00511     int vertical = 0;
00512     int horizontal = 0;
00513     int p1 = x-1;
00514     int p2 = x+1;
00515     int a1 = ip.image.image[y][0][p1];
00516     int b1 = ip.image.image[y][1][p1];
00517     int c1 = ip.image.image[y][2][p1];
00518     int a2 = ip.image.image[y][0][p2];
00519     int b2 = ip.image.image[y][1][p2];
00520     int c2 = ip.image.image[y][2][p2];
00521     
00522     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00523     
00524     p1 = y-1;
00525     p2 = y+1;
00526     a1 = ip.image.image[p1][0][x];
00527     b1 = ip.image.image[p1][1][x];
00528     c1 = ip.image.image[p1][2][x];
00529     a2 = ip.image.image[p2][0][x];
00530     b2 = ip.image.image[p2][1][x];
00531     c2 = ip.image.image[p2][2][x];
00532     
00533     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
00534     
00535     return (vertical > horizontal) ? vertical : horizontal; 
00536   }
00537   /** Adds a color and its range to the buffers*/
00538   inline void addColor(){
00539     if (lastColor != -1){
00540       colorBuffer[bufferSize] = lastColor;
00541       ranges[bufferSize] = colorRange;
00542       bufferSize++;
00543       colorRange = 0;
00544     }
00545     else{
00546       colorRange = 0;
00547     }
00548   }
00549   /** Tests, if a point is a valid. Thats a helper.
00550   * @param x x-coordinate
00551   * @param y y-coordinate
00552   * @return True, if point is valid.
00553   */
00554   inline bool insideImage(int x,int y){
00555     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return false;
00556     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return false;
00557     return true;
00558   }
00559   /** This function implements a edge filter. 
00560   *   @param x x-coordinate.
00561   *   @param y y-coordinate.
00562   *   @return A vote for the edgness.
00563   */
00564   inline int susanVote(int x,int y){
00565     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
00566     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
00567     int vote = susanDetector.isEdgePoint(ip.image,x,y,SUSANEdgeDetectionLite::componentA);
00568     vote += susanDetector.isEdgePoint(ip.image,x,y,
00569       SUSANEdgeDetectionLite::componentB);
00570     vote += susanDetector.isEdgePoint(ip.image,x,y,
00571       SUSANEdgeDetectionLite::componentC);
00572     return vote;
00573   }
00574 
00575 
00576   
00577 };
00578 
00579 #endif// __REdgeDetection_h_
00580 
00581 /*
00582 * Change log :
00583 * 
00584 * $Log: REdgeDetection.h,v $
00585 * Revision 1.1  2004/09/09 11:08:04  spranger
00586 * renamed GT2004EdgeDetection to REdgeDetection for consistency
00587 *
00588 * Revision 1.4  2004/09/06 12:02:25  schmidtb
00589 * commented almost all members, removed warnings in documentation
00590 
00591 * did further code clean up
00592 *
00593 * Revision 1.2  2004/09/02 07:59:29  schmidtb
00594 * Added RasterImageProcessor to repository, because we used it for the OpenChallenge.
00595 *
00596 * Revision 1.1  2004/05/17 11:57:04  nistico
00597 * Imported ball detection from RasterImageProcessor (integrated in MSH by Bernd in New Orleans)
00598 *
00599 * Revision 1.1  2004/04/25 17:40:18  pg_arce
00600 * stand 1. spiel
00601 *
00602 * Revision 1.3  2004/03/25 15:10:03  pg_besc
00603 * made some changes
00604 *
00605 * Revision 1.2  2004/03/17 20:58:47  schmidtb
00606 * added new scan methods and buffering.
00607 *
00608 * Revision 1.1  2004/03/11 20:19:43  schmidtb
00609 * Established GT2004EdgeDetection.
00610 *
00611 */

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