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_

Generated on Mon Mar 20 21:59:50 2006 for GT2005 by doxygen 1.3.6