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

# Modules/ImageProcessor/ImageProcessorTools/GT2004EdgeDetection.h

Go to the documentation of this file.

    00001 /**
    00002 * @file Modules/ImageProcessor/ImageProcessorTools/GT2004EdgeDetection.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 __GT2004EdgeDetection_h_
    00010 #define __GT2004EdgeDetection_h_
    00011
    00012 #include "Representations/Perception/Image.h"
    00013 #include "Modules/ImageProcessor/ImageProcessor.h"
    00014 #include "Modules/ImageProcessor/ImageProcessorTools/MSH2004ColorCorrector.h"
    00015 #include "Modules/ImageProcessor/ImageProcessorTools/SUSANEdgeDetectionLite.h"
    00016
    00017 /**
    00018 * @class GT2004EdgeDetection
    00019 * Utility-class for edge-detection.
    00020 */
    00021 class GT2004EdgeDetection
    00022 {
    00023
    00024 public:
    00025
    00026   /**
    00027   * Default constructor.
    00028   */
    00029
    00030   GT2004EdgeDetection(ImageProcessor& processor,MSH2004ColorCorrector& corrector);
    00031
    00032   ~GT2004EdgeDetection();
    00033
    00034   int threshold;
    00035
    00036   int tempX;
    00037
    00038   int tempY;
    00039
    00040   bool scanEast(int& x, int& y);
    00041
    00042   bool scanWest(int& x, int& y);
    00043
    00044   bool scanNorth(int& x, int& y);
    00045
    00046   bool scanSouth(int& x, int& y);
    00047
    00048   bool ballScanEast(int& x, int& y);
    00049
    00050   bool ballScanWest(int& x, int& y);
    00051
    00052   /** Follows the given direction,
    00053     and determines edges by the sum of all three channels.
    00054     The position of the edge is stored in x and y.
    00055     @param x The starting x-value.
    00056     @param y The starting y-value.
    00057         @param direction The direction followed.
    00058     @return edge was found*/
    00059   bool scan(int& x,int& y,Vector2<double> direction);
    00060
    00061   /** Follows the given direction,
    00062     and determines edges by the sum of all three channels.
    00063     The position of the edge is stored in x and y.
    00064     Fills the colorBuffer while scanning, so the client
    00065     can determine with the colorBuffer-Array what kind of
    00066     object was found.
    00067
    00068     @param x The starting x-value.
    00069     @param y The starting y-value.
    00070         @param direction The direction followed.
    00071     @return edge was found*/
    00072   bool bufferedScan(int& x,int& y,Vector2<double> direction);
    00073
    00074   /** Follows the last given direction. Skips 3 pixels at the beginning
    00075   of each scan, while filling the buffer.*/
    00076   bool bufferedScan(int& x,int& y);
    00077
    00078     /** Follows the given direction,and searches for field-edge-points.
    00079     Determines edges by the sum of the first two channels.
    00080     The position of the edge is stored in x and y.
    00081     @param x The starting x-value.
    00082     @param y The starting y-value.
    00083         @param direction The direction followed.
    00084     @return edge was found*/
    00085   bool scanField(int& x,int& y,Vector2<double> direction);
    00086
    00087   /** Follows the last given direction,and searches for field-edge-points.
    00088     Determines edges by the sum of the first two channels.
    00089     The position of the edge is stored in x and y.
    00090     @param x The starting x-value.
    00091     @param y The starting y-value.
    00092     @return edge was found*/
    00093   bool scanField(int& x,int& y);
    00094
    00095   /** Follows the last given direction,
    00096     and determines edges by the sum of all three channels */
    00097   bool scan(int& x,int& y);
    00098
    00099   bool colorScan(int& x,int& y,Vector2<double> direction,colorClass& lastColor);
    00100
    00101   bool colorScan(int& x,int& y,colorClass& lastColor);
    00102
    00103   bool susanScan(int& x,int& y,Vector2<double> direction);
    00104
    00105   bool scan(int& x,int& y,int x1,int y1);
    00106
    00107   bool colorScan(int& x,int& y,int x1,int y1,colorClass& lastColor);
    00108
    00109   inline void setDirection(Vector2<double> dir){
    00110     cx = (dir.x<0)? -1 : 1;
    00111     cy = (dir.y<0)? -1 : 1;
    00112     dx = abs((int)(dir.x * 500.0f));
    00113     dy = abs((int)(dir.y * 500.0f));
    00114     if (dx>dy){
    00115       e = dx - 2*dy;
    00116       f = 2*(dx - dy);
    00117       g = -2*dy;
    00118     }
    00119     else{
    00120       e = dy - 2*dx;
    00121       f = 2*(dy - dx);
    00122       g = -2*dx;
    00123     }
    00124     direction = dir;
    00125   }
    00126
    00127   inline colorClass getColor(int index){
    00128     return colorBuffer[index];
    00129   }
    00130
    00131   inline int getRange(int index){
    00132     return ranges[index];
    00133   }
    00134
    00135   inline bool isHorizontalEdge(int x, int y){
    00136     return horizontalEdgeVote(x,y) > threshold;
    00137   }
    00138
    00139   inline int horizontalEdgeVote(int x,int y){
    00140     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
    00141     int cx1 = x-1;
    00142     int cx2 = x+1;
    00143     int a1 = ip.image.image[y][0][cx1];
    00144     int b1 = ip.image.image[y][1][cx1];
    00145     int c1 = ip.image.image[y][2][cx1];
    00146     int a2 = ip.image.image[y][0][cx2];
    00147     int b2 = ip.image.image[y][1][cx2];
    00148     int c2 = ip.image.image[y][2][cx2];
    00149
    00150     return abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00151   }
    00152
    00153   inline bool isVerticalEdge(int x, int y){
    00154     return verticalEdgeVote(x,y) > threshold;
    00155   }
    00156
    00157   inline int verticalEdgeVote(int x,int y){
    00158     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
    00159     int cy1 = y-1;
    00160     int cy2 = y+1;
    00161     int a1 = ip.image.image[cy1][0][x];
    00162     int b1 = ip.image.image[cy1][1][x];
    00163     int c1 = ip.image.image[cy1][2][x];
    00164     int a2 = ip.image.image[cy2][0][x];
    00165     int b2 = ip.image.image[cy2][1][x];
    00166     int c2 = ip.image.image[cy2][2][x];
    00167
    00168     return abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00169   }
    00170
    00171   inline int ballEdgeVote(int x,int y){
    00172     //could be different code as in crossEdgeVote()
    00173     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
    00174     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
    00175     int vertical = 0;
    00176     int horizontal = 0;
    00177     int p1 = x-1;
    00178     int p2 = x+1;
    00179     int a1 = ip.image.image[y][0][p1];
    00180     int b1 = ip.image.image[y][1][p1];
    00181     int c1 = ip.image.image[y][2][p1];
    00182     int a2 = ip.image.image[y][0][p2];
    00183     int b2 = ip.image.image[y][1][p2];
    00184     int c2 = ip.image.image[y][2][p2];
    00185
    00186     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00187
    00188     p1 = y-1;
    00189     p2 = y+1;
    00190     a1 = ip.image.image[p1][0][x];
    00191     b1 = ip.image.image[p1][1][x];
    00192     c1 = ip.image.image[p1][2][x];
    00193     a2 = ip.image.image[p2][0][x];
    00194     b2 = ip.image.image[p2][1][x];
    00195     c2 = ip.image.image[p2][2][x];
    00196
    00197     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00198
    00199     return (vertical > horizontal) ? vertical : horizontal;
    00200   }
    00201
    00202   inline int crossEdgeVote(int x,int y){
    00203     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
    00204     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
    00205     int vertical = 0;
    00206     int horizontal = 0;
    00207     int p1 = x-1;
    00208     int p2 = x+1;
    00209     int a1 = ip.image.image[y][0][p1];
    00210     int b1 = ip.image.image[y][1][p1];
    00211     int c1 = ip.image.image[y][2][p1];
    00212     int a2 = ip.image.image[y][0][p2];
    00213     int b2 = ip.image.image[y][1][p2];
    00214     int c2 = ip.image.image[y][2][p2];
    00215
    00216     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00217
    00218     p1 = y-1;
    00219     p2 = y+1;
    00220     a1 = ip.image.image[p1][0][x];
    00221     b1 = ip.image.image[p1][1][x];
    00222     c1 = ip.image.image[p1][2][x];
    00223     a2 = ip.image.image[p2][0][x];
    00224     b2 = ip.image.image[p2][1][x];
    00225     c2 = ip.image.image[p2][2][x];
    00226
    00227     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00228
    00229     return (vertical > horizontal) ? vertical : horizontal;
    00230   }
    00231   inline int fieldEdgeVote(int x,int y){
    00232     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
    00233     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
    00234     int vertical = 0;
    00235     int horizontal = 0;
    00236     int p1 = x-1;
    00237     int p2 = x+1;
    00238     int a1 = ip.image.image[y][0][p1];
    00239     int b1 = ip.image.image[y][1][p1];
    00240     int a2 = ip.image.image[y][0][p2];
    00241     int b2 = ip.image.image[y][1][p2];
    00242
    00243
    00244     horizontal = abs(a1 - a2) + abs(b1 - b2);
    00245
    00246     p1 = y-1;
    00247     p2 = y+1;
    00248     a1 = ip.image.image[p1][0][x];
    00249     b1 = ip.image.image[p1][1][x];
    00250     a2 = ip.image.image[p2][0][x];
    00251     b2 = ip.image.image[p2][1][x];
    00252
    00253     vertical = abs(a1 - a2) + abs(b1 - b2);
    00254
    00255     return (vertical > horizontal) ? vertical : horizontal;
    00256   }
    00257   /* implemented with colorCorrection*/
    00258   inline colorClass getColor(int x,int y){
    00259     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return (colorClass)-1;
    00260     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return (colorClass)-1;
    00261
    00262     //TODO remove hack for color correction
    00263     unsigned char cy = ip.image.image[y][0][x];
    00264     unsigned char cu = ip.image.image[y][1][x];
    00265     unsigned char cv = ip.image.image[y][2][x];
    00266     corrector.getCorrectedPixel(x,y,cy,cu,cv);
    00267     return ip.colorTable.getColorClass(cy,cu,cv);
    00268   }
    00269
    00270   /** Gives the next pixel of last scan. This is only for the scans that
    00271     use Bresenham's algorithm.*/
    00272   inline void skip(int& x,int& y){
    00273     if (dx>dy){
    00274       x+=cx;
    00275       if (e<0) {
    00276         y+=cy;
    00277         e+=f;
    00278       }
    00279       else {
    00280         e+=g;
    00281       }
    00282     }
    00283     else{
    00284       y+=cy;
    00285       if (e<0) {
    00286         x+=cx;
    00287         e+=f;
    00288       }
    00289       else {
    00290         e+=g;
    00291       }
    00292     }
    00293   }
    00294
    00295   inline bool findStart(Vector2<int>& start,const Vector2<double>& dir){
    00296     int dx = (int)(dir.x*300 + 0.5);
    00297       int dy = (int)(dir.y*300 + 0.5);
    00298
    00299     Vector2<int> rightBorder(start.x + dx,start.y + dy);
    00300
    00301     return Geometry::clipLineWithRectangleCohenSutherland(
    00302       Vector2<int>(1,1),
    00303       Vector2<int>(ip.image.cameraInfo.resolutionWidth -2,ip.image.cameraInfo.resolutionHeight -2),
    00304       start,
    00305       rightBorder
    00306       );
    00307   }
    00308
    00309   inline int getBufferSize(){
    00310     return bufferSize;
    00311   }
    00312
    00313 //Bresenham
    00314 /*inline void draw_line(int x0, int y0, int x1, int y1){
    00315   int x,y=y0,dx = 2*(x1-x0),dy = 2*(y1-y0);
    00316   int dydx = dy - dx, d = dy - dx/2;
    00317   for(x=x0;x<=x1;x++){
    00318     DOT(imageProcessor_general,x,y,
    00319       Drawings::white, Drawings::red);
    00320     if(d<0) {d+= dy;}
    00321     else {y+=1; d += dydx;}
    00322   }
    00323 }
    00324 */
    00325
    00326
    00327 private:
    00328
    00329   ImageProcessor& ip;
    00330
    00331   SUSANEdgeDetectionLite susanDetector;
    00332
    00333   MSH2004ColorCorrector corrector;
    00334
    00335   Vector2<double> direction;
    00336
    00337   int e;
    00338
    00339   int f;
    00340
    00341   int g;
    00342
    00343   int dx;
    00344
    00345   int dy;
    00346
    00347   int cx;
    00348
    00349   int cy;
    00350
    00351   int bufferSize;
    00352
    00353   colorClass currentColor;
    00354
    00355   colorClass lastColor;
    00356
    00357   int colorRange;
    00358
    00359   /** This buffer is used to store the colors
    00360   * passed by a buffered scan-method during the last scan
    00361   */
    00362   colorClass colorBuffer[20];
    00363
    00364   /** This buffer is used to store the ranges of the colors */
    00365   int ranges[20];
    00366
    00367   inline int fastCrossEdgeVote(int x,int y){
    00368     int vertical = 0;
    00369     int horizontal = 0;
    00370     int p1 = x-1;
    00371     int p2 = x+1;
    00372     int a1 = ip.image.image[y][0][p1];
    00373     int b1 = ip.image.image[y][1][p1];
    00374     int c1 = ip.image.image[y][2][p1];
    00375     int a2 = ip.image.image[y][0][p2];
    00376     int b2 = ip.image.image[y][1][p2];
    00377     int c2 = ip.image.image[y][2][p2];
    00378
    00379     horizontal = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00380
    00381     p1 = y-1;
    00382     p2 = y+1;
    00383     a1 = ip.image.image[p1][0][x];
    00384     b1 = ip.image.image[p1][1][x];
    00385     c1 = ip.image.image[p1][2][x];
    00386     a2 = ip.image.image[p2][0][x];
    00387     b2 = ip.image.image[p2][1][x];
    00388     c2 = ip.image.image[p2][2][x];
    00389
    00390     vertical = abs(a1 - a2) + abs(b1 - b2) + abs(c1 - c2);
    00391
    00392     return (vertical > horizontal) ? vertical : horizontal;
    00393   }
    00394
    00395   inline void addColor(){
    00396     if (lastColor != -1){
    00397       colorBuffer[bufferSize] = lastColor;
    00398       ranges[bufferSize] = colorRange;
    00399       bufferSize++;
    00400       colorRange = 0;
    00401     }
    00402     else{
    00403       colorRange = 0;
    00404     }
    00405   }
    00406
    00407   inline bool insideImage(int x,int y){
    00408     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return false;
    00409     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return false;
    00410     return true;
    00411   }
    00412
    00413   inline int susanVote(int x,int y){
    00414     if (x < 1 || x > ip.image.cameraInfo.resolutionWidth-2) return -1;
    00415     if (y < 1 || y > ip.image.cameraInfo.resolutionHeight-2) return -1;
    00416     int i = 0;
    00417     //~ if (susanDetector.isEdgePoint(ip.image,x,y,
    00418       //~ SUSANEdgeDetectionLite::componentA)) ++i;
    00419     if (susanDetector.isEdgePoint(ip.image,x,y,
    00420       SUSANEdgeDetectionLite::componentB)) ++i;
    00421     //if (susanDetector.isEdgePoint(ip.image,x,y,
    00422     //  SUSANEdgeDetectionLite::componentC)) ++i;
    00423     return i;
    00424   }
    00425
    00426
    00427
    00428 };
    00429
    00430 #endif// __GT2004EdgeDetection_h_