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

# Modules/ImageProcessor/ImageProcessorTools/MSH2004EdgeDetection.h

Go to the documentation of this file.

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