HoughTransform.C

Go to the documentation of this file.
00001 /*!@file BeoSub/HoughTransform.C find hough transform for an image     */
00002 // //////////////////////////////////////////////////////////////////// //
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00004 // University of Southern California (USC) and the iLab at USC.         //
00005 // See http://iLab.usc.edu for information about this project.          //
00006 // //////////////////////////////////////////////////////////////////// //
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 // //////////////////////////////////////////////////////////////////// //
00031 //
00032 // Primary maintainer for this file: Michael Montalbo <montalbo@usc.edu>
00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/HoughTransform.C $
00034 // $Id: HoughTransform.C 9412 2008-03-10 23:10:15Z farhan $
00035 
00036 
00037 #ifndef HoughTransform_C
00038 #define HoughTransform_C
00039 
00040 #include "BeoSub/HoughTransform.H"
00041 
00042 #include "Image/Image.H"
00043 #include "Image/Pixels.H"
00044 #include "Util/Timer.H"
00045 #include "Util/Types.H"
00046 #include "Util/log.H"
00047 #include "Image/ColorOps.H"
00048 #include "Image/Image.H"
00049 #include "Image/MathOps.H"
00050 #include "Image/DrawOps.H"
00051 #include "Image/FilterOps.H"
00052 #include "Image/Transforms.H"
00053 #include "Raster/Raster.H"
00054 #include "rutz/shared_ptr.h"
00055 #include "BeoSub/hysteresis.H"
00056 #include "VFAT/segmentImageTrackMC.H"
00057 #include <cstdio>
00058 #include <cstdlib>
00059 #include <cstring>
00060 #include <iostream> //needed for segmentImageTrackMC!
00061 #include <math.h>
00062 #include <list>
00063 #include "Image/MatrixOps.H"
00064 #include "BeoSub/CannyEdge.H"
00065 #include "MBARI/Geometry2D.H"
00066 using namespace std;
00067 
00068 // finds all the lines in an image by using the hough transform
00069 // thetaRes is the resolution of each theta
00070 // dRes is the resolution of the D
00071 // returns a vector with the line segments found
00072 std::vector <LineSegment2D> houghTransform
00073 (Image<byte> &inputImage, float thetaRes, float dRes, int threshold,
00074  Image< PixRGB<byte> > &output)
00075 {
00076   //Timer tim(1000000);
00077   //uint t;
00078 
00079   uint w = inputImage.getWidth();
00080   uint h = inputImage.getHeight();
00081 
00082   // get the total number of angles and delta from the resolution of theta and D's
00083   int numAngle = (int) (M_PI / thetaRes);
00084   int numD = (int)(sqrt((w*w + h*h)/ dRes) / 2);
00085   int centerX = (int)(w/2);
00086   int centerY = (int)(h/2);
00087 
00088   std::vector <LineSegment2D> lines;
00089   std::vector <Point2D<int> > edgePoints;
00090 
00091   //find all the white edge pixels in the image and store them
00092   for(int y = 0; y < inputImage.getHeight(); y++)
00093     {
00094       for(int x = 0; x < inputImage.getWidth(); x++)
00095         {
00096           //if the pixel is an edge
00097           if(inputImage.getVal(x,y) == 255)
00098             // convert the x,y position of the pixel to an x,y position where
00099             // the center of the image is the origin as opposed to the top left corner
00100             // and store the pixel
00101             edgePoints.push_back(Point2D<int>(x - centerX, y - centerY));
00102         }
00103     }
00104 
00105   // store the edge points that belong to each line
00106   std::vector<std::vector<std::vector<Point2D<int> > > > ptList;
00107   ptList.resize(numD);
00108   for(int i = 0; i < numD; i++) ptList[i].resize(numAngle);
00109 
00110   // equation of the line is x*cos(theta) + y*sin(theta) = D
00111 
00112   // fill the accumulator
00113   for(uint c = 0; c < edgePoints.size(); c++)
00114     {
00115       int edgePointX = edgePoints[c].i;
00116       int edgePointY = edgePoints[c].j;
00117 
00118       //get all possible D and theta that can fit to that point
00119       for(int n = 0; n < numAngle; n++)
00120         {
00121           int r =  (int)(edgePointX * cos(n*thetaRes) + edgePointY * sin(n*thetaRes));
00122 
00123           // if the radius is negative, make it positive so as to avoid segfaults
00124           // (a point with radius r lies on the same line
00125           // as a point with radius -r if they share the same angle)
00126           r = abs(r);
00127 
00128           ptList[r][n].push_back(edgePoints[c]);
00129 
00130         }
00131     }
00132 
00133   // find the peaks, ie any number of points greater
00134   // than the threshold as well as a local maximum is considered a line
00135   for(int i = 1; i < numD - 1; i++)  {
00136     for(int j = 1; j < numAngle - 1; j++)
00137       {
00138         uint currentPointCount = ptList[i][j].size();
00139 
00140         if(currentPointCount > (unsigned int)(threshold) &&
00141            currentPointCount > ptList[i-1][j].size() &&
00142            currentPointCount > ptList[i+1][j].size() &&
00143            currentPointCount > ptList[i][j-1].size() &&
00144            currentPointCount > ptList[i][j+1].size()    ) // found a peak
00145           {
00146             //find the endpoints of the line segment
00147             int minx = ptList[i][j][1].i, maxx = ptList[i][j][1].i;
00148              int miny = ptList[i][j][1].j, maxy = ptList[i][j][1].j;
00149             //the indexes of the two endpoints in the vector
00150             uint mini = 0, maxi = 0;
00151             for(uint k = 1; k < currentPointCount; k++)
00152               {
00153                 if(minx > ptList[i][j][k].i)
00154                   { minx =  ptList[i][j][k].i; mini = k; }
00155                 if(maxx < ptList[i][j][k].i)
00156                   { maxx =  ptList[i][j][k].i; maxi = k; }
00157               }
00158 //             LINFO("ksize: %d, min[%d]:%d,%d max[%d]:%d,%d", ptList[i][j].size(),
00159 //                   mini, ptList[i][j][mini].i, ptList[i][j][mini].j,
00160 //                   maxi, ptList[i][j][maxi].i, ptList[i][j][maxi].j);
00161 
00162             // if the line is vertical
00163             if(minx == maxx)
00164               {
00165                 for(uint k = 1; k < currentPointCount; k++)
00166                   {
00167                     if(miny > ptList[i][j][k].j)
00168                       { miny =  ptList[i][j][k].j; mini = k; }
00169                     if(maxy > ptList[i][j][k].j)
00170                   { maxy =  ptList[i][j][k].j; maxi = k; }
00171                   }
00172               }
00173 
00174             // the two endpoints of the line segment
00175             Point2D<int> p1 = ptList[i][j][mini];
00176             Point2D<int> p2 = ptList[i][j][maxi];
00177 
00178             // convert from x,y where the center of the image is the origin
00179             // back to x,y where top left of image is the origin
00180             p1.i += centerX;
00181             p1.j += centerY;
00182             p2.i += centerX;
00183             p2.j += centerY;
00184 
00185             LineSegment2D thisLine(p1,p2);
00186 
00187             if(thisLine.isValid())
00188               {
00189                 lines.push_back(thisLine);
00190                 drawLine(output, p1, p2,  PixRGB<byte> (255,0,0), 1);
00191               }
00192           }
00193       }
00194   }
00195 
00196   return lines;
00197 
00198 }
00199 
00200 #endif
00201 
00202 // ######################################################################
00203 /* So things look consistent in everyone's emacs... */
00204 /* Local Variables: */
00205 /* indent-tabs-mode: nil */
00206 /* End: */
Generated on Sun May 8 08:04:33 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3