CrossRecognizer.C

00001 /*!@file SeaBee/PipeRecognizer.C find pipe     */
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/SeaBee/CrossRecognizer.C $
00034 // $Id: CrossRecognizer.C 10794 2009-02-08 06:21:09Z itti $
00035 
00036 #include "SeaBee/CrossRecognizer.H"
00037 
00038 
00039 // ######################################################################
00040 CrossRecognizer::CrossRecognizer()
00041 {
00042   //default values for hough transform
00043    houghThreshold = 40;
00044   minThreshold = 10;
00045   maxThreshold = 50;
00046   sigma = 1.1;
00047   tlow = 0.3;
00048   thigh = 1.1;
00049   linescale = 80;
00050   avgCrossCenterX = 0;
00051   avgCrossCenterY = 0;
00052   avgCrossAngle = 0.0;
00053   stdDevCrossX = 0.0;
00054   stdDevCrossY = 0.0;
00055   stdDevCrossAngle = 0.0;
00056 
00057   stdDevAngleCount = 0;
00058   stdDevCenterCount = 0;
00059 
00060   foundCount = 0;
00061 
00062   itsSetupOrangeTracker = false;
00063 }
00064 
00065 // ######################################################################
00066 CrossRecognizer::~CrossRecognizer()
00067 { }
00068 
00069 // ######################################################################
00070 void CrossRecognizer::getCrossLocation(rutz::shared_ptr<Image<byte> > colorSegmentedImage,
00071                                        rutz::shared_ptr<Image<PixRGB <byte> > > outputImage,
00072                                        CrossRecognizeMethod method,
00073                                        rutz::shared_ptr<Point2D<int> > crossCenterPoint,
00074                                        rutz::shared_ptr<float> crossAngle,
00075                                        rutz::shared_ptr<uint> stalePointCount
00076                                        )
00077 {
00078   switch(method)
00079     {
00080     case HOUGH:
00081       calculateHoughTransform(colorSegmentedImage, outputImage, crossCenterPoint, crossAngle, stalePointCount);
00082       break;
00083 
00084     default:
00085       LERROR("Invalid pipe recognizer method specified");
00086     }
00087 
00088 }
00089 
00090 // ######################################################################
00091 
00092 void CrossRecognizer::calculateHoughTransform(rutz::shared_ptr<Image<byte> > colorSegmentedImage,
00093                                              rutz::shared_ptr<Image<PixRGB <byte> > > outputImage,
00094                                              rutz::shared_ptr<Point2D<int> > crossCenterPoint,
00095                                              rutz::shared_ptr<float> crossAngle,
00096                                              rutz::shared_ptr<uint> stalePointCount
00097                                              )
00098 {
00099   std::vector<LineSegment2D> lines = getHoughLines(colorSegmentedImage, outputImage);
00100   std::vector<LineSegment2D> centerPointLines;
00101   *crossCenterPoint = getCrossCenter(lines, centerPointLines, stalePointCount);
00102 
00103   LDEBUG("Center Point X: %d, Y: %d", crossCenterPoint->i, crossCenterPoint->j);
00104 
00105   *crossAngle = getCrossDir(centerPointLines);
00106 }
00107 
00108 // ######################################################################
00109 
00110 std::vector<LineSegment2D> CrossRecognizer::pruneLines (std::vector<LineSegment2D> lines)
00111 {
00112   uint nLines = lines.size();
00113   // get the mean
00114   float sumLength = 0.0;  float meanLength = 0.0;
00115   for (uint i = 0; i < nLines; i++) sumLength += lines[i].length();
00116   meanLength = sumLength / nLines;
00117 
00118   // get the standard deviation
00119   float sumsqr = 0.0;
00120   for (uint i = 0; i < nLines; i++)
00121     sumsqr += pow((float)(lines[i].length()) - meanLength, 2.0);
00122   float stdevLength = sqrt(sumsqr / (nLines-1));
00123 
00124   // kick out lines that aren't within the stddev of the mean length
00125   LDEBUG ("Mean: %f   StdDev: %f", meanLength, stdevLength);
00126   std::vector<LineSegment2D> nlines;
00127   for(uint i = 0; i < nLines; i++)
00128     {
00129       if (lines[i].length() > (meanLength - stdevLength) &&
00130           lines[i].length() < (meanLength + stdevLength)   )
00131         nlines.push_back(lines[i]);
00132     }
00133 
00134   if (nlines.size() == 0)
00135     { LDEBUG("*** NO LINE LENGTH WITHIN STD DEV ***"); return lines; }
00136 
00137   std::vector<LineSegment2D> flines = nlines;
00138   LDEBUG("\n\n\n\nSum the Average...");
00139   double sumAngle = 0;
00140   std::vector<LineSegment2D>::iterator itr  = flines.begin();
00141   while(itr < flines.end())
00142     {
00143       float angle = (*itr).angle();
00144       LDEBUG("Line Angle[%4d,%4d][%4d,%4d]: %f",
00145             (*itr).point1().i, (*itr).point1().j,
00146             (*itr).point2().i, (*itr).point2().j,
00147             angle * 180/M_PI);
00148 
00149       // eliminate lines that are close to vertical
00150       if(!isnan(angle)) { sumAngle += angle; itr++; }
00151       else
00152         {
00153           sumAngle += 90.0;
00154           //          itr = flines.erase(itr);
00155           LDEBUG("Drop a line");
00156         }
00157     }
00158   if (flines.size() == 0) return lines;
00159 
00160   // also drop off angles that do not fall
00161   // within a standard deviation of the average angle
00162   float meanAngle = sumAngle / flines.size();
00163   float stdAngleSum = 0.0;
00164   float stdAngleSqr = 0.0;
00165   for(uint i = 0; i < flines.size(); i++)
00166     {
00167       float angle = flines[i].angle();
00168       stdAngleSum = angle - meanAngle;
00169       stdAngleSqr += (stdAngleSum * stdAngleSum);
00170     }
00171   float stdevAngle = stdAngleSqr / flines.size();
00172   double stdtemp = sqrt((double)stdevAngle);
00173   stdevAngle = (float)stdtemp;
00174 
00175   // throw out angles that do not fit within stdev of the angle
00176   sumAngle = 0.0;  itr  = flines.begin();
00177   while(itr < flines.end())
00178     {
00179       float angle = (*itr).angle();
00180       if(angle >= (meanAngle - stdevAngle) &&
00181          angle <= (meanAngle + stdevAngle))
00182         { sumAngle += angle; itr++; }
00183       else itr = flines.erase(itr);
00184     }
00185 
00186   return flines;
00187 }
00188 
00189 // ######################################################################
00190 
00191  Point2D<int> CrossRecognizer::getCrossCenter (const std::vector<LineSegment2D> lines,
00192                                          std::vector<LineSegment2D> &centerPointLines,
00193                                          rutz::shared_ptr<uint> stalePointCount)
00194 {
00195 
00196   Point2D<int> avgCrossCenterPoint = Point2D<int>(avgCrossCenterX,avgCrossCenterY);
00197 
00198   uint nLines = lines.size();
00199   if(nLines == 0)
00200     {
00201       LDEBUG("*** NO LINES ***");
00202       ++(*stalePointCount);
00203       return avgCrossCenterPoint;
00204     }
00205 
00206   std::vector<LineSegment2D> posAngleLines, negAngleLines;
00207 
00208   for(uint i = 0; i < nLines; i++)
00209     {
00210       if(lines[i].angle() >= 0)
00211         {
00212           posAngleLines.push_back(lines[i]);
00213         }
00214       else
00215         {
00216           negAngleLines.push_back(lines[i]);
00217         }
00218     }
00219 
00220   std::vector<LineSegment2D> fPosAngleLines = posAngleLines;//pruneLines(posAngleLines);
00221   std::vector<LineSegment2D> fNegAngleLines = negAngleLines;//pruneLines(negAngleLines);
00222 
00223   std::vector<LineSegment2D> flines;
00224 
00225   for(uint i = 0; i < fPosAngleLines.size(); i++)
00226   {
00227     flines.push_back(fPosAngleLines[i]);
00228   }
00229 
00230   for(uint i = 0; i < fNegAngleLines.size(); i++)
00231   {
00232     flines.push_back(fNegAngleLines[i]);
00233   }
00234 
00235 
00236   std::vector<std::vector<Point2D<int> > > intersectPts;
00237 
00238   //Go through all the remaining lines
00239   for(uint r = 0; r < flines.size(); r++)
00240     {
00241       for(uint s = 0; s < flines.size(); s++)
00242         {
00243           if(r != s)
00244             {
00245               double xIntersect, yIntersect = 0.0;
00246               //if two lines intersect
00247               if(flines[r].intersects(flines[s],xIntersect,yIntersect)
00248                  && (fabs(flines[r].angleBetween(flines[s])) >= 0.95 * M_PI/2)//convert to radians
00249                  && (fabs(flines[r].angleBetween(flines[s])) <= 1.05 * M_PI/2))//convert to radians
00250                 {
00251                   int ptIndex = -1;
00252 
00253                   centerPointLines.push_back(flines[r]);
00254                   centerPointLines.push_back(flines[s]);
00255 
00256 
00257                   //check to see if the point at which they intersect fits into a pre-existing bucket
00258                   for(uint c = 0; c < intersectPts.size(); c++)
00259                     {
00260                       if(xIntersect < intersectPts[c][0].i + 5 &&
00261                          xIntersect > intersectPts[c][0].i - 5 &&
00262                          yIntersect < intersectPts[c][0].j + 5 &&
00263                          yIntersect > intersectPts[c][0].j - 5 )
00264                         {
00265                           ptIndex = c;
00266                         }
00267 
00268                     }
00269 
00270                   //if the point fits into a pre-existing bucket, add it to the bucket
00271                   if(ptIndex > 0)
00272                     {
00273                       int x = (int)(xIntersect);
00274                       int y = (int)(yIntersect);
00275 
00276                       intersectPts[ptIndex].push_back(Point2D<int>(x,y));
00277                       //average the old bucket's value with the new point added
00278                       //so as to create a moving bucket
00279                        intersectPts[ptIndex][0].i += x;
00280                        intersectPts[ptIndex][0].i /= 2;
00281                        intersectPts[ptIndex][0].j += y;
00282                        intersectPts[ptIndex][0].j /= 2;
00283 
00284                     }
00285                   //otherwise, create a new bucket
00286                   else
00287                     {
00288                       int x = (int)(xIntersect);
00289                       int y = (int)(yIntersect);
00290 
00291                       std::vector<Point2D<int> > newIntPts;
00292                       newIntPts.push_back(Point2D<int>(x,y));
00293                       intersectPts.push_back(newIntPts);
00294                     }
00295                 }
00296             }
00297         }
00298     }
00299 
00300   if(intersectPts.size() == 0)
00301     {
00302       LDEBUG("*** NO INTERSECT POINTS FOUND ***");
00303       ++(*stalePointCount);
00304       return avgCrossCenterPoint;
00305     }
00306 
00307   uint maxPts = intersectPts[0].size();
00308   uint maxIndex = 0;
00309 
00310   for(uint i = 0; i < intersectPts.size(); i++)
00311     {
00312       if(intersectPts[i].size() > maxPts)
00313         {
00314           maxPts = intersectPts[i].size();
00315           maxIndex = i;
00316         }
00317     }
00318 
00319   Point2D<int> finalPoint = intersectPts[maxIndex][0];
00320 
00321 
00322   // Smooth out the center points being displayed by averaging the position of the
00323   // last 30 center points.
00324 
00325   bool isWithinStdDev = false;
00326   // Check if center point is within std dev
00327   if(centerPointBuff.size() < 2
00328      || (abs(finalPoint.i - avgCrossCenterX) <= stdDevCrossX
00329          && abs(finalPoint.j - avgCrossCenterY) <= stdDevCrossY)
00330      )
00331     {
00332       stdDevCenterCount = 0;
00333       isWithinStdDev = true;
00334     }
00335   else
00336     {
00337       stdDevCenterCount++;
00338 
00339       LINFO("Current X: %d Y: %d",finalPoint.i, finalPoint.j);
00340       LINFO("AVG X: %d Y: %d",avgCrossCenterX, avgCrossCenterY);
00341       LINFO("STDDEV CROSS (X,Y):(%f,%f)",stdDevCrossX, stdDevCrossY);
00342 
00343     }
00344 
00345   *stalePointCount = 0;
00346 
00347   uint centerBuffSize = centerPointBuff.size();
00348 
00349   if(stdDevCenterCount > 5)
00350     {
00351       isWithinStdDev = true;
00352       centerPointBuff.clear();
00353     }
00354 
00355   if(isWithinStdDev)
00356     {
00357       if(centerBuffSize >= 30)
00358         {
00359           centerPointBuff.pop_front();
00360         }
00361 
00362       centerPointBuff.push_back(finalPoint);
00363 
00364       centerBuffSize = centerPointBuff.size();
00365     }
00366 
00367   if(centerBuffSize > 0)
00368     {
00369       int sumX = 0, sumY = 0;
00370       std::list<Point2D<int> >::iterator it;
00371 
00372       for(it = centerPointBuff.begin(); it != centerPointBuff.end(); ++it)
00373         {
00374           sumX += (*it).i;
00375           sumY += (*it).j;
00376         }
00377 
00378       avgCrossCenterX = sumX / centerBuffSize;
00379       avgCrossCenterY = sumY / centerBuffSize;
00380 
00381       avgCrossCenterPoint = Point2D<int>(avgCrossCenterX,avgCrossCenterY);
00382 
00383       float sqrStdCenterX = 0.0;
00384       float sqrStdCenterY = 0.0;
00385 
00386 
00387       for(it = centerPointBuff.begin(); it != centerPointBuff.end(); ++it)
00388       {
00389         sqrStdCenterX += (((*it).i - avgCrossCenterX) * ((*it).i - avgCrossCenterX));
00390         sqrStdCenterY += (((*it).j - avgCrossCenterY) * ((*it).j - avgCrossCenterY));
00391       }
00392 
00393       float stdevCenterX = sqrStdCenterX / centerBuffSize;
00394       float stdevCenterY = sqrStdCenterY / centerBuffSize;
00395       double stdTempCenterX = sqrt((double)stdevCenterX);
00396       double stdTempCenterY = sqrt((double)stdevCenterY);
00397       stdDevCrossX = (float)stdTempCenterX;
00398       stdDevCrossY = (float)stdTempCenterY;
00399     }
00400   else
00401     {
00402       avgCrossCenterPoint = finalPoint;
00403     }
00404   //         stalePointCount++;
00405   return avgCrossCenterPoint;
00406 }
00407 
00408 
00409 // ######################################################################
00410 float CrossRecognizer::getCrossDir(const std::vector<LineSegment2D> lines)
00411 {
00412   uint nLines = lines.size();
00413   if(nLines == 0) { LDEBUG("*** NO LINES ***"); return avgCrossAngle;}
00414 
00415   //separate lines into positive and negative angles
00416   std::vector<LineSegment2D> posAngleLines, negAngleLines;
00417 
00418   for(uint i = 0; i < nLines; i++)
00419     {
00420       if(lines[i].angle() >= 0)
00421         {
00422           posAngleLines.push_back(lines[i]);
00423         }
00424       else
00425         {
00426           negAngleLines.push_back(lines[i]);
00427         }
00428     }
00429 
00430   std::vector<LineSegment2D> fPosAngleLines = posAngleLines;//pruneLines(posAngleLines);
00431   std::vector<LineSegment2D> fNegAngleLines = negAngleLines;//pruneLines(negAngleLines);
00432 
00433   double avgPosAngle, avgNegAngle;
00434 
00435   // Find average of positive angles
00436   //  LINFO("\n\n\n\nSum the Average...");
00437   double sumPosAngle = 0;
00438   std::vector<LineSegment2D>::iterator itr  = fPosAngleLines.begin();
00439   while(itr < fPosAngleLines.end())
00440     {
00441       float angle = (*itr).angle();
00442       LDEBUG("Line Angle[%4d,%4d][%4d,%4d]: %f",
00443             (*itr).point1().i, (*itr).point1().j,
00444             (*itr).point2().i, (*itr).point2().j,
00445             angle * 180/M_PI);
00446 
00447       // eliminate lines that are close to vertical
00448       if(!isnan(angle)) { sumPosAngle += angle; itr++; }
00449       else
00450         { sumPosAngle += 90.0;
00451           //itr = fPosAngleLines.erase(itr);
00452           LDEBUG("Drop a line");
00453         }
00454     }
00455 
00456   if (fPosAngleLines.size() == 0)
00457     {
00458       return avgCrossAngle;
00459     }
00460   else
00461     {
00462       avgPosAngle = sumPosAngle / fPosAngleLines.size();
00463     }
00464 
00465   // Find average of negative angles
00466   double sumNegAngle = 0;
00467   itr  = fNegAngleLines.begin();
00468   while(itr < fNegAngleLines.end())
00469     {
00470       float angle = (*itr).angle();
00471       LDEBUG("Line Angle[%4d,%4d][%4d,%4d]: %f",
00472             (*itr).point1().i, (*itr).point1().j,
00473             (*itr).point2().i, (*itr).point2().j,
00474             angle * 180/M_PI);
00475 
00476       // eliminate lines that are close to vertical
00477       if(!isnan(angle)) { sumNegAngle += angle; itr++; }
00478       else
00479         { sumNegAngle += 90.0;
00480 
00481         //        itr = fNegAngleLines.erase(itr);
00482         LDEBUG("Drop a line");
00483       }
00484     }
00485 
00486 
00487   if (fNegAngleLines.size() == 0)
00488     {
00489       return avgCrossAngle;
00490     }
00491   else
00492     {
00493       avgNegAngle = sumNegAngle / fNegAngleLines.size();
00494     }
00495 
00496   //Get the distance that the avg pos and neg angles are away from 90
00497   int posAngleDistance = abs(90 - (int)avgPosAngle);
00498   int negAngleDistance = abs(90 - abs((int)avgNegAngle));
00499 
00500   float meanAngle = 0.0;
00501   float sumAngle = 0.0;
00502   std::vector<LineSegment2D> flines;
00503 
00504   if(posAngleDistance <= negAngleDistance)
00505     {
00506       flines = fPosAngleLines;
00507       meanAngle = avgPosAngle;
00508       sumAngle = sumPosAngle;
00509     }
00510   else
00511     {
00512       flines = fNegAngleLines;
00513       meanAngle = avgNegAngle;
00514       sumAngle = sumNegAngle;
00515     }
00516 
00517 //   // also drop off angles that do not fall
00518 //   // within a standard deviation of the average angle
00519 //   float stdAngleSum = 0.0;
00520 //   float stdAngleSqr = 0.0;
00521 //   for(uint i = 0; i < flines.size(); i++)
00522 //     {
00523 //       float angle = flines[i].angle();
00524 //       stdAngleSum = angle - meanAngle;
00525 //       stdAngleSqr += (stdAngleSum * stdAngleSum);
00526 //     }
00527 //   float stdevAngle = stdAngleSqr / flines.size();
00528 //   double stdtemp = sqrt((double)stdevAngle);
00529 //   stdevAngle = (float)stdtemp;
00530 
00531 //   // throw out angles that do not fit within stdev of the angle
00532 //   sumAngle = 0.0;  itr  = flines.begin();
00533 //   while(itr < flines.end())
00534 //     {
00535 //       float angle = (*itr).angle();
00536 //       if(angle >= (meanAngle - stdevAngle) &&
00537 //          angle <= (meanAngle + stdevAngle))
00538 //         { sumAngle += angle; itr++; }
00539 //       else itr = flines.erase(itr);
00540 //     }
00541 
00542   float avgAngle = 0.0;
00543 
00544   if (flines.size() != 0)
00545     {
00546       avgAngle = sumAngle / flines.size();
00547     }
00548   else
00549     {
00550       return avgCrossAngle;
00551     }
00552 
00553   if (avgAngle > 0) avgAngle -= M_PI;
00554 
00555 
00556   // Smooth out the angles being displayed by averaging the position of the last 30 angles
00557   uint angleBuffSize = angleBuff.size();
00558 
00559   bool isWithinStdDev = false;
00560   // Check if angle is within std dev
00561   if(angleBuff.size() < 2
00562      || (fabs(avgAngle - avgCrossAngle) <= stdDevCrossAngle ))
00563     {
00564       stdDevAngleCount = 0;
00565       isWithinStdDev = true;
00566     }
00567   else
00568     {
00569       stdDevAngleCount++;
00570     }
00571 
00572   if(stdDevAngleCount > 10)
00573     {
00574       angleBuff.clear();
00575       isWithinStdDev = true;
00576     }
00577 
00578   if(isWithinStdDev)
00579     {
00580       if(angleBuffSize >= 50)
00581         {
00582           angleBuff.pop_front();
00583         }
00584 
00585       angleBuff.push_back(avgAngle);
00586 
00587       angleBuffSize = angleBuff.size();
00588     }
00589 
00590   if(angleBuffSize > 0)
00591     {
00592       float sumBuffAngle = 0.0;
00593       std::list<float>::iterator it;
00594 
00595       for(it = angleBuff.begin(); it != angleBuff.end(); ++it)
00596         {
00597           sumBuffAngle += (*it);
00598         }
00599 
00600       avgCrossAngle = sumBuffAngle / angleBuffSize;
00601 
00602       //      LINFO("AVG Cross Angle: %f",avgCrossAngle);
00603 
00604 
00605       float sqrStdDevAngle = 0.0;
00606       for(it = angleBuff.begin(); it != angleBuff.end(); ++it)
00607       {
00608         sqrStdDevAngle = ((*it - avgCrossAngle) * (*it - avgCrossAngle));
00609       }
00610 
00611       float stdevAngle = sqrStdDevAngle / angleBuffSize;
00612       double stdTempAngle = sqrt((double)stdevAngle);
00613       stdDevCrossAngle = (float)stdTempAngle;
00614     }
00615   else
00616     {
00617       avgCrossAngle = avgAngle;
00618     }
00619 
00620   return avgCrossAngle;
00621 }
00622 
00623 
00624 // ######################################################################
00625 std::vector<LineSegment2D> CrossRecognizer::getHoughLines
00626 (rutz::shared_ptr< Image< byte > > colorSegmentedImage,
00627  rutz::shared_ptr< Image< PixRGB <byte> > > outputImage)
00628 {
00629 
00630 #ifndef HAVE_OPENCV
00631   LFATAL("OpenCV must be installed in order to use this function");
00632 #else
00633 
00634   //find edges of segmented image using canny
00635   IplImage *edge = cvCreateImage( cvGetSize(img2ipl(*colorSegmentedImage)), 8, 1 );
00636   cvCanny( img2ipl(luminance(*colorSegmentedImage)), edge, 100, 150, 3 );//150,200,3
00637 
00638   //clear output image and set it equal to canny edge image
00639   outputImage->clear();
00640   *outputImage = toRGB(ipl2gray(edge));
00641 
00642   //storage for use in hough transform
00643   CvMemStorage* storage = cvCreateMemStorage(0);
00644 
00645   //perform hough transform and store hough lines
00646   CvSeq* cvLines = cvHoughLines2(edge, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 30, 20, 10);
00647 
00648   LINFO("cvLines %d",cvLines->total);
00649 
00650   //storage for hough line segments
00651   std::vector <LineSegment2D> lineSegments;
00652 
00653   //loop through hough lines, store them as line segments, and draw lines in output image
00654   for(int i = 0; i < cvLines->total; i++ )
00655     {
00656       //get a line
00657       CvPoint* line = (CvPoint*)cvGetSeqElem(cvLines,i);
00658       //get line end points
00659       Point2D<int> pt1 = Point2D<int>(line[0].x,line[0].y);
00660       Point2D<int> pt2 = Point2D<int>(line[1].x,line[1].y);
00661 
00662 
00663       //create line segment from endpoints and store
00664       lineSegments.push_back(LineSegment2D(pt1,pt2));
00665 
00666       //draw line segment in output image
00667       drawLine(*outputImage, pt1, pt2, PixRGB<byte>(255,0,0));
00668     }
00669 
00670   //clean up pointers
00671   //  delete edge;
00672   //  delete storage;
00673   //  delete cvLines;
00674 
00675 
00676 
00677 #endif // HAVE_OPENCV
00678 
00679 
00680 
00681 
00682 
00683 
00684 
00685 
00686 
00687 
00688  std::vector <LineSegment2D> lines;
00689 
00690 #ifndef HAVE_OPENCV
00691   LFATAL("OpenCV must be installed in order to use this function");
00692 #else
00693 
00694   IplImage *edge = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00695   cvCanny( img2ipl(luminance(cameraImage)), edge, 100, 150, 3 );//150,200,3
00696 
00697   //  inplacePaste(dispImage, toRGB(edgeImage), Point2D<int>(0,h));
00698 
00699   //  tim.reset();
00700 //   rutz::shared_ptr<CvMemStorage*> storage;
00701 //   *storage = cvCreateMemStorage(0);
00702 
00703   CvMemStorage* storage = cvCreateMemStorage(0);
00704 
00705   //outputImage.clear();
00706 
00707   outputImage = ipl2gray(edge);
00708 
00709   CvSeq* cvlines = cvHoughLines2(edge, storage, CV_HOUGH_STANDARD,
00710                                  1, CV_PI/180, 40 , 0, 0);
00711   //  t = tim.get();
00712   //  LDEBUG("houghTransform takes: %f ms", (float)t/1000.0);
00713 
00714     for(int i = 0; i < MIN(cvlines->total,10); i++ )
00715     {
00716       float* line = (float*)cvGetSeqElem(cvlines,i);
00717       float rho = line[0];
00718       float theta = line[1];
00719       CvPoint pt1, pt2;
00720       double a = cos(theta), b = sin(theta);
00721       double x0 = a*rho, y0 = b*rho;
00722       pt1.x = cvRound(x0 + 1000*(-b));
00723       pt1.y = cvRound(y0 + 1000*(a));
00724       pt2.x = cvRound(x0 - 1000*(-b));
00725       pt2.y = cvRound(y0 - 1000*(a));
00726       lines.push_back(LineSegment2D(Point2D<int>(pt1.x,pt1.y),
00727                                     Point2D<int>(pt2.x,pt2.y)));
00728       drawLine(outputImage, Point2D<int>(pt1.x,pt1.y),
00729                Point2D<int>(pt2.x, pt2.y), PixRGB<byte>(255,0,0));
00730     }
00731 
00732      cvReleaseMemStorage(&storage);
00733      cvReleaseImage(&edge);
00734      //cvReleaseSeq(&cvlines);
00735 
00736     //    delete edge;
00737     //    delete cvlines;
00738 
00739 #endif // HAVE_OPENCV
00740 
00741     return lines;
00742 }
00743 
00744 
00745 
00746 
00747 // ######################################################################
Generated on Sun May 8 08:06:45 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3