HoughTransform2.C

00001 #ifndef HoughTransform2_C
00002 #define HoughTransform2_C
00003 
00004 #include "BeoSub/HoughTransform2.H"
00005 
00006 #include "Image/Image.H"
00007 #include "Image/Pixels.H"
00008 #include "Util/Timer.H"
00009 #include "Util/Types.H"
00010 #include "Util/log.H"
00011 #include "Image/ColorOps.H"
00012 #include "Image/Image.H"
00013 #include "Image/MathOps.H"
00014 #include "Image/DrawOps.H"
00015 #include "Image/FilterOps.H"
00016 #include "Image/Transforms.H"
00017 #include "Raster/Raster.H"
00018 #include "rutz/shared_ptr.h"
00019 #include "BeoSub/hysteresis.H"
00020 #include "VFAT/segmentImageTrackMC.H"
00021 #include <cstdio>
00022 #include <cstdlib>
00023 #include <cstring>
00024 #include <iostream> //needed for segmentImageTrackMC!
00025 #include <math.h>
00026 #include <list>
00027 #include "Image/MatrixOps.H"
00028 #include "BeoSub/CannyEdge.H"
00029 #include "MBARI/Geometry2D.H"
00030 using namespace std;
00031 
00032 
00033 void findEndPoints(int p, float theta, Point2D<int> *intercept1, Point2D<int> *intercept2, Dims dimensions)
00034 {
00035          int imageWidth = dimensions.w();
00036          int imageHeight = dimensions.h();
00037 
00038           //convert d and angle to a pair of endpoints
00039           intercept1->i = -1;
00040           intercept2->i = -1;
00041           int tempX0, tempX1, tempY0, tempY1;
00042           int cosTheta = (int) cos(theta);
00043           int sinTheta = (int) sin(theta);
00044 
00045           //Find the possible image border intersects
00046           tempX0 = (p) / cosTheta; //y=0
00047           tempX1 = (p-imageHeight*sinTheta)/cosTheta; //y=imageHeight
00048           tempY0 = (p / sinTheta); //x = 0
00049           tempY1 = (p - imageWidth * cosTheta) / sinTheta; //x = imageWidth
00050 
00051           //Decide which two of the four intersects are valid and store them
00052           if(tempX0 > 0 && tempX0 < imageWidth)
00053           {
00054               intercept1->i = tempX0;
00055               intercept1->j = 0;
00056           }
00057           if(tempX1 > 0 && tempX1 < imageWidth)
00058           {
00059             if(intercept1->i == -1) {
00060               intercept1->i = tempX1;
00061               intercept1->j = imageHeight;
00062             }
00063             else {
00064               intercept2->i = tempX1;
00065               intercept2->j = imageHeight;
00066             }
00067           }
00068           if(tempY0 > 0 && tempY0 < imageHeight)
00069           {
00070             if(intercept1->i == -1) {
00071               intercept1->i = 0;
00072               intercept1->j = tempY0;
00073             }
00074             else {
00075               intercept2->i = 0;
00076               intercept2->j = tempY0;
00077             }
00078           }
00079           if(tempY1 > 0 && tempY1 < imageHeight)
00080           {
00081             if(intercept1->i == -1) {
00082               intercept1->i = imageWidth;
00083               intercept1->j = tempY1;
00084             }
00085             else {
00086               intercept2->i = imageWidth;
00087               intercept2->j = tempY1;
00088             }
00089           }
00090 
00091 }
00092 //finds the line by using hough transform
00093 //thetaRes is the resolution of each theta
00094 //dRes is the resolution of the D
00095 //returns the number of lines found
00096 std::vector <LineSegment2D> houghTransform(Image<byte> &inputImage,
00097                                            float thetaRes,
00098                                            float dRes,
00099                                            int threshold,
00100                                            Image< PixRGB<byte> > &output)
00101 {
00102   LDEBUG("Inside houghTransform");
00103   int imageWidth = inputImage.getWidth();
00104   int imageHeight = inputImage.getHeight();
00105   //get the total number of angles and P from the resolution of theta and P's
00106   int numAngle = (int) (360 / thetaRes); //in degrees
00107   int numP = (int) (((max(imageHeight, imageWidth) / 2) - 1) / dRes);
00108 
00109 
00110   //stores the lines found in the image
00111   std::vector <LineSegment2D> lines;
00112 
00113   //accumulator -> represents the hough space
00114   int accumulator[numP][numAngle];
00115 
00116   LDEBUG("Clearing accumulator");
00117 
00118   //fill accumulator with zeroes
00119   for(int i = 0; i<numP; i++)
00120     {
00121       for(int j = 0; j < numAngle; j++)
00122         {
00123           accumulator[i][j] = 0;
00124         }
00125     }
00126 
00127   // Normal Parameterization of a Line:
00128   // p = x * cos(theta) + y * sin(theta)
00129   //////////////////////////Mike/////////////////////////////
00130 
00131   LDEBUG("Accumulator is cleared");
00132 
00133   float theta;
00134   for(int p = 0; p < numP; p++)
00135     {
00136       for(int angle = 0; angle < numAngle; angle++)
00137         {
00138           theta = angle * thetaRes;
00139 
00140           //skip the thrid quadrant
00141           if(theta == 180)
00142             theta = 271;
00143 
00144           Point2D<int> intercept1, intercept2;
00145 
00146           findEndPoints(p, theta, &intercept1, &intercept2, Dims(imageWidth, imageHeight));
00147 
00148           //increment accumulator every time a white pixel lies on the
00149           //line plotted by bresenham algorithm using the endpoints found before
00150 
00151           int x0 = intercept1.i;
00152           int x1 = intercept1.j;
00153           int y0 = intercept2.i;
00154           int y1 = intercept2.j;
00155 
00156           bool steep = abs(y1 - y0) > abs(x1 - x0);
00157           if(steep)
00158             {
00159               swap(x0, y0);
00160               swap(x1, y1);
00161            }
00162 
00163           if(x0 > x1)
00164             {
00165               swap(x0, x1);
00166               swap(y0, y1);
00167             }
00168 
00169           int deltax = x1 - x0;
00170           int deltay = abs(y1 - y0);
00171           int error = -deltax / 2;
00172           int ystep;
00173           int y = y0;
00174           int x;
00175 
00176           if(y0 < y1)
00177             {
00178               ystep = 1;
00179             }
00180           else
00181             {
00182               ystep = -1;
00183             }
00184 
00185           for(x = x0; x < x1; x++)
00186             {
00187               if(steep)
00188                 {
00189                   if(inputImage.getVal(y,x) == 255)
00190                     {
00191                       accumulator[p][angle]++;
00192                     }
00193                 }
00194               else
00195                 {
00196                   if(inputImage.getVal(x,y) == 255)
00197                     {
00198                       accumulator[p][angle]++;
00199                     }
00200                 }
00201 
00202               error = error + deltay;
00203 
00204               if(error > 0)
00205                 {
00206                   y = y + ystep;
00207                   error = error - deltax;
00208                 }
00209             }
00210 
00211           for(int i = 0; i<numP; i++)
00212             {
00213               for(int j = 0; j < numAngle; j++)
00214                 {
00215                   theta = j * thetaRes;
00216                   if(accumulator[i][j] > threshold && accumulator[i][j] > accumulator[i-1][j]
00217                      && accumulator[i][j] > accumulator[i+1][j] && accumulator[i][j] > accumulator[i][j-1]
00218                      && accumulator[i][j] > accumulator[i][j+1])//found a peak
00219                     {
00220                       Point2D<int> lineEndPoint1, lineEndPoint2;
00221                       findEndPoints(i , theta, &lineEndPoint1, &lineEndPoint2, Dims(imageWidth, imageHeight));
00222 
00223                       LineSegment2D theLine(lineEndPoint1, lineEndPoint2);
00224 
00225                       lines.push_back(theLine);
00226                     }
00227                 }
00228             }
00229 
00230         }
00231     }
00232 
00233     return lines;
00234 }
00235 
00236 
00237   //////////////////////////////////////////////////////////
00238   /*
00239         //equation of the line is Xcos(theta)+ysin(theta) = D
00240         // fill the accumulator
00241         //        printf("numD is %d\n",numD);
00242     for(int j = 0; j < inputImage.getHeight(); j++ ) {
00243       for(int i = 0; i < inputImage.getWidth(); i++ )
00244       {
00245         if( inputImage.getVal(i,j) != 0 )//point is an edge
00246           for(int n = 0; n < numangle; n++ )//get all possible D and theta that can fit to that point
00247         {
00248           r =  (int)(i * cos(n*thetaRes) + j * sin(n*thetaRes));
00249           r += (numD -1)/2;
00250 
00251           if(r > 0 && r < numD) //Avoid segfaults
00252             accumulator[r][n]++;
00253 
00254 
00255         }
00256       }
00257     }
00258 
00259     Point2D<int> p1;
00260     Point2D<int> p2;
00261     Point2D<int> storage[inputImage.getWidth()*inputImage.getHeight()];
00262     double a, b;
00263     int totalLines = 0;
00264     int pointCount = 0;
00265 
00266 
00267 
00268     // find the peaks, ie any number greater than the threshold is considered a line
00269     for(int i = 0; i<numD; i++)
00270       {
00271         for(int j = 0; j < numangle; j++)
00272           {
00273             if(accumulator[i][j] > threshold && accumulator[i][j]> accumulator[i-1][j]
00274                && accumulator[i][j]> accumulator[i+1][j] && accumulator[i][j]> accumulator[i][j-1]
00275                && accumulator[i][j]> accumulator[i][j+1])//found a peak
00276               {
00277                 totalLines++;
00278 
00279                 //get the image coordinates for the 2 endpoint of the line
00280                 a = cos(j*thetaRes);
00281                 b = sin(j*thetaRes);
00282 
00283                 //TODO: ROOM FOR IMPROVEMENT!
00284                 for(int x = 0; x < inputImage.getWidth(); x++) {
00285                   for(int y = 0; y < inputImage.getHeight(); y++) {
00286                     if( inputImage.getVal(x,y) != 0 )//point is an edge
00287                       if(((int)(x * cos(j*thetaRes) + y * sin(j*thetaRes))) + ((numD -1)/2) == i)
00288                         {
00289                           storage[pointCount].i = x;
00290                           storage[pointCount].j = y;
00291                           pointCount++;
00292                         }
00293                   }
00294                 }
00295 
00296                 //check the distance between each point
00297                 bool isolated = true;
00298                 int numtoDiscard = 0;
00299                 float discardPoints[inputImage.getWidth() * inputImage.getHeight()];
00300                 for(int y = 0; y < pointCount; y++){
00301                   for(int x = 0; x <pointCount; x++){
00302                     if(storage[0].distance(storage[x]) < 1 && x != y)
00303                       isolated = false;
00304 
00305                   }
00306                   if(isolated)//discard this point
00307                     {
00308                       discardPoints[numtoDiscard++] = y;
00309                     }
00310                 }
00311 
00312 
00313                 //make sure that the point is not in the to be discarded list
00314                 for(int x=0; x < numtoDiscard; x++) {
00315                   for(int y = 0; y < pointCount; y++) {
00316                     if(discardPoints[x] != y){
00317                       p1.i = p2.i = storage[y].i;
00318                       p1.j = p2.j = storage[y].j;
00319 
00320                     }
00321 
00322                   }
00323                 }
00324                 //find the 2 endpoints of line
00325                 //check if vertical
00326                 if(fabs(a) < .001)
00327                   {
00328 
00329                     //search the 2 endpoints
00330                     for(int x = 0; x < pointCount; x++)
00331                       {
00332 
00333                         bool discard = false;
00334                         for(int k = 0; k < numtoDiscard; k++) {
00335                           if(discardPoints[k] == x)
00336                             discard = true;
00337                         }
00338 
00339                         if(!discard){
00340                           if(p1.j < storage[x].j)
00341                             {
00342                               p1.j = storage[x].j;
00343                               p1.i = storage[x].i;
00344                             }
00345                           if(p2.j > storage[x].j)
00346                             {
00347                               p2.j = storage[x].j;
00348                               p2.i = storage[x].i;
00349 
00350                             }
00351                         }
00352                       }
00353 
00354                   }
00355                 else // horizontal
00356                   {
00357                     //search the 2 endpoints
00358                     for(int x = 0; x < pointCount; x++)
00359                       {
00360                         bool discard = false;
00361                         for(int k = 0; k < numtoDiscard; k++) {
00362                           if(discardPoints[k] == x)
00363                             discard = true;
00364 
00365                         }
00366 
00367                         if(!discard){
00368 
00369                           if(p1.i < storage[x].i)
00370                             {
00371                               p1.j = storage[x].j;
00372                               p1.i = storage[x].i;
00373                             }
00374                           if(p2.i > storage[x].i)
00375                             {
00376                               p2.j = storage[x].j;
00377                               p2.i = storage[x].i;
00378 
00379                             }
00380                         }
00381                       }
00382                   }
00383                 pointCount = 0;
00384 
00385 
00386                 LineSegment2D thisLine(p1, p2);
00387 
00388 
00389                 if (thisLine.isValid()) {
00390 
00391 
00392                   lines.push_back(thisLine);
00393                   drawLine(output, p1, p2,  PixRGB<byte> (255,0,0), 1);
00394                 }
00395 
00396               }
00397           }
00398           }*/
00399 
00400 /*
00401 functions to find the best fit line
00402 */
00403 
00404 
00405 
00406 #endif
00407 
Generated on Sun May 8 08:40:20 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3