BeoSubBin.C

Go to the documentation of this file.
00001 /*!@file BeoSub/BeoSubBin.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/BeoSub/BeoSubBin.C $
00034 // $Id: BeoSubBin.C 12782 2010-02-05 22:14:30Z irock $
00035 
00036 #include "Image/OpenCVUtil.H"  // must be first to avoid conflicting defs of int64, uint64
00037 
00038 #include "GUI/XWinManaged.H"
00039 
00040 #include "Image/Pixels.H"
00041 #include "Raster/Raster.H"
00042 
00043 #include "Util/Timer.H"
00044 #include "Util/Types.H"
00045 #include "Util/log.H"
00046 
00047 #include "Image/ColorOps.H"
00048 #include "Image/CutPaste.H"
00049 #include "Image/MathOps.H"
00050 #include "Image/DrawOps.H"
00051 #include "Image/FilterOps.H"
00052 #include "Image/Transforms.H"
00053 
00054 #include "BeoSub/hysteresis.H"
00055 #include "VFAT/segmentImageTrackMC.H"
00056 #include "BeoSub/HoughTransform.H"
00057 #include "BeoSub/ColorTracker.H"
00058 #include "BeoSub/CannyEdge.H"
00059 //#include "BeoSub/IsolateColor.H"
00060 #include "rutz/compat_cmath.h" // for isnan()
00061 
00062 #include "BeoSub/BeoSubBin.H"
00063 
00064 #include <cstdio>
00065 #include <cstdlib>
00066 #include <cstring>
00067 #include <iostream> //needed for segmentImageTrackMC!
00068 #include <math.h>
00069 #include <vector>
00070 #include <cmath>
00071 
00072 // ######################################################################
00073 BeoSubBin::BeoSubBin()
00074 {
00075   imageAngles.resize(0);
00076   imageLines.resize(0);
00077   binAngles.resize(0);
00078   binLines.resize(0);
00079   binCenter = *(new Point2D<int>(-1, -1));
00080 
00081 }
00082 
00083 // ######################################################################
00084 BeoSubBin::~BeoSubBin()
00085 { }
00086 
00087 
00088 
00089 // ######################################################################
00090 float BeoSubBin::getBinSceneMass(Image< PixRGB<byte> > &cameraImage, Image< PixRGB<byte> > &outputImage, Point2D<int>& center) {
00091 #ifndef HAVE_OPENCV
00092   LFATAL("OpenCV must be installed in order to use this function");
00093   return 0;
00094 #else
00095   IplImage *edge = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00096   IplImage *out = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00097   IplImage *edge2 = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1);
00098 
00099   ////////// image manipulation ///////////////
00100   cvThreshold(img2ipl(luminance(cameraImage)), edge, 170, 255, CV_THRESH_TOZERO);
00101 
00102   IplConvKernel* dilation = cvCreateStructuringElementEx(8, 8, 0, 0, CV_SHAPE_RECT);
00103   cvErode(edge, edge2, dilation, 1);
00104   cvDilate(edge2, edge, dilation, 1);
00105   cvThreshold(edge, out, 200, 255, CV_THRESH_TOZERO);
00106 
00107 
00108   int mass=-1, x=0, y=0;
00109   Image<byte> isoWhite = luminance(ipl2gray(out));
00110   //////FIXME  mass = isolateWhite(isoWhite, isoWhite, x, y);
00111 
00112   outputImage = toRGB(isoWhite);
00113 
00114   center.i = x;
00115   center.j = y;
00116 
00117   cvReleaseImage(&edge);
00118   cvReleaseImage(&edge2);
00119   //  cvReleaseImage(&out);
00120   cvReleaseStructuringElement(&dilation);
00121   return mass;
00122 #endif
00123 }
00124 
00125 
00126 std::vector<LineSegment2D> BeoSubBin::getHoughLines(Image< PixRGB <byte> > &cameraImage, Image< PixRGB <byte> > &preHough,
00127                                                     Image< PixRGB <byte> > &outputImage)
00128 {
00129   std::vector <LineSegment2D> lines;
00130 
00131 #ifndef HAVE_OPENCV
00132   LFATAL("OpenCV must be installed in order to use this function");
00133 #else
00134 
00135   //  inplacePaste(dispImage, toRGB(edgeImage), Point2D<int>(0,h));
00136   IplImage *edge = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00137   IplImage *out = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00138   IplImage *edge2 = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00139   //cvSobel(img2ipl(luminance(cameraImage)), edge, 0, 1, 3);
00140 
00141 
00142 
00143 
00144 
00145   /////////////////////// steps for bottom camera which only uses rectangulation ///////////////
00146 
00147   //////////////// image manipulation, may need tweaking /////////////////////
00148   // need to up contrast
00149   cvEqualizeHist(img2ipl(luminance(cameraImage)), edge);
00150   cvThreshold(img2ipl(luminance(cameraImage)), edge, 170, 255, CV_THRESH_TOZERO );
00151 
00152   cvThreshold(edge, edge2, 170, 255, CV_THRESH_TOZERO);
00153   IplConvKernel* dilation = cvCreateStructuringElementEx(8, 8, 0, 0, CV_SHAPE_RECT);
00154   out = edge;
00155   cvErode(edge, edge2, dilation, 1);
00156   cvDilate(edge2, edge, dilation, 1 );
00157   cvThreshold(edge, edge2, 200, 255, CV_THRESH_TOZERO );
00158 
00159   /////////////////////////////////////////////////////////
00160 
00161 
00162   cvCanny(edge, out, 100, 150, 3 );//150,200,3
00163   preHough =  ipl2gray(edge);
00164 
00165 
00166   CvMemStorage* storage = cvCreateMemStorage(0);
00167 
00168   outputImage.clear();
00169   outputImage = toRGB( ipl2gray( out ) );
00170 
00171   CvSeq* cvlines = cvHoughLines2(out, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 10, 10, 10);
00172 
00173     for(int i = 0; i < MIN(cvlines->total,10); i++ )
00174     {
00175       float* line = (float*)cvGetSeqElem(cvlines,i);
00176       float rho = line[0];
00177       float theta = line[1];
00178       CvPoint pt1, pt2;
00179       double a = cos(theta), b = sin(theta);
00180       double x0 = a*rho, y0 = b*rho;
00181       pt1.x = cvRound(x0 + 1000*(-b));
00182       pt1.y = cvRound(y0 + 1000*(a));
00183       pt2.x = cvRound(x0 - 1000*(-b));
00184       pt2.y = cvRound(y0 - 1000*(a));
00185       lines.push_back(LineSegment2D(Point2D<int>(pt1.x,pt1.y),Point2D<int>(pt2.x,pt2.y)));
00186       drawLine(outputImage, Point2D<int>(pt1.x,pt1.y), Point2D<int>(pt2.x, pt2.y), PixRGB<byte>(255,0,0));
00187     }
00188     ///////////////////////////////////////////////////////////////////////////////////
00189 
00190 
00191 
00192 
00193     ///////////// NOTE:::: will need to create overlap function that will remove orange, replace it with black ///////
00194     ////////////////// before any bin recognition is done /////////////////////////
00195 
00196 
00197     cvReleaseImage(&edge);
00198     cvReleaseImage(&edge2);
00199     //cvReleaseImage(&out);
00200     cvReleaseStructuringElement(&dilation);
00201 
00202 
00203 #endif // HAVE_OPENCV
00204     return lines;
00205 }
00206 
00207 // ######################################################################
00208 void BeoSubBin::pruneLines(std::vector<LineSegment2D>& lines, std::vector<LineSegment2D> &pruned, Image< PixRGB<byte> >* img ) {
00209 
00210 
00211   std::vector<LineSegment2D> nonSimilarLines;
00212   std::vector<LineSegment2D>::iterator iter;
00213 
00214   // add the first line to the nonSimilarLine vector
00215   // erase if from the input line vector we are checking
00216   if(lines.size() > 0) {
00217     nonSimilarLines.push_back(lines[0]);
00218     lines.erase(lines.begin());
00219     iter = lines.begin();
00220   }
00221   else
00222     LDEBUG("*** NO LINES ***");
00223 
00224 
00225   double x, y;
00226 
00227 
00228 
00229   //top border of image
00230   LineSegment2D border1 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(img->getWidth(), 0) ) );
00231   // left border of image
00232   LineSegment2D border2 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(0, img->getHeight()) ) );
00233   // right border of image
00234   LineSegment2D border3 ( *(new Point2D<int>(img->getWidth(), 0)), *(new Point2D<int>(img->getWidth(), img->getHeight()) ) );
00235   //bottom border of image
00236   LineSegment2D border4 ( *(new Point2D<int>(0, img->getHeight())), *(new Point2D<int>(img->getWidth(), img->getHeight()) ) );
00237 
00238   // check for similar lines
00239   for(uint i = 0; i < nonSimilarLines.size(); i++) {
00240 
00241     while(iter != lines.end()) {
00242 
00243       double angle = nonSimilarLines[i].angleBetween(*iter);
00244       angle *= 180/PI;
00245       double intersect = nonSimilarLines[i].intersects((*iter), x, y);
00246 
00247       // if the lines do not intersect in the image, possibly parallel
00248       if(!intersect) {
00249 
00250         double x2, y2;
00251         // if the parallel lines intersect the top and bottom images
00252         // at similar points, remove line from unpruned line list
00253         if((nonSimilarLines[i].intersects(border1, x, y) && (*iter).intersects(border1, x2, y2)) ||
00254            (nonSimilarLines[i].intersects(border4, x, y) && (*iter).intersects(border4, x2, y2))) {
00255 
00256 
00257           if(fabs(x - x2) < 5.0) {
00258             // drawLine(*img, (*iter).point1(), (*iter).point2(), PixRGB<byte>(255, 150, 0));
00259             lines.erase(iter);
00260           }
00261 
00262         }
00263         // if the parallel lines intersect the left and right images
00264         // at similar points, remove one of them
00265         else if((nonSimilarLines[i].intersects(border2, x, y) && (*iter).intersects(border2, x2, y2)) ||
00266                 (nonSimilarLines[i].intersects(border3, x, y) && (*iter).intersects(border3, x2, y2))) {
00267 
00268           if(fabs(y - y2) < 5.0) {
00269             //drawLine(*img, (*iter).point1(), (*iter).point2(), PixRGB<byte>(255, 150, 0));
00270             lines.erase(iter);
00271           }
00272 
00273         }
00274 
00275       }
00276       // else if lines are not parallel,
00277       // if they intersect in the image at a very small angle
00278       // remove one of them
00279       else if(intersect && img->coordsOk((int)x, (int)y) && (fabs(angle) < 2.5 || fabs(angle) > 178.5)) {
00280         //drawLine(*img, (*iter).point1(), (*iter).point2(), PixRGB<byte>(255, 0, 150));
00281         lines.erase(iter);
00282       }
00283 
00284       if(iter != lines.end())
00285         iter++;
00286     }
00287 
00288     iter = lines.begin();
00289     // once all unpruned lines have been compared to current nonSimilarLine,
00290     // in which any similar lines have been removed.
00291     // add next unpruned line to nonSimilarLines vector
00292     // reiterate and see if any unpruned lines are similar to that one
00293     if(lines.size() > 0) {
00294       nonSimilarLines.push_back(*iter);
00295       lines.erase(iter);
00296     }
00297 
00298 
00299   }
00300 
00301   pruned = nonSimilarLines;
00302   // lines are now pruned
00303   binAngles.clear();
00304 
00305   // now remove similar angles at similar intersections
00306   pruneAngles(nonSimilarLines, binAngles, img);
00307 
00308 
00309   /// drawing ////////////////
00310   for(uint i = 0; i < nonSimilarLines.size(); i++)
00311     drawLine(*img, nonSimilarLines[i].point1(), nonSimilarLines[i].point2(), PixRGB<byte>(255,0,0));
00312 
00313 //   for(uint i = 0; i < binAngles.size(); i++) {
00314 //     //printf("x: %d, y: %d, angle: %f\n", binAngles[i].pos.i, binAngles[i].pos.j, binAngles[i].angle);
00315 //     drawCircle(*img, binAngles[i].pos, 5, PixRGB<byte>(0, 255, 0));
00316 //   }
00317 
00318   drawCircle(*img, *(new Point2D<int>(160, 120)), 5, PixRGB<byte>(200, 255, 0));
00319 
00320   /// we also want to return angles with their respective positions.
00321   //// which will require a struct that associates angle, with an x and a y;
00322 
00323 }
00324 
00325 
00326 void BeoSubBin::pruneAngles(std::vector<LineSegment2D>& lines, std::vector<BinAngles>& angles, Image< PixRGB< byte > >* img) {
00327 
00328 
00329   for(uint i = 0; i < lines.size(); i++) {
00330 
00331     for(uint j = i+1; j < lines.size(); j++) {
00332 
00333       double angle = lines[i].angleBetween(lines[j]);
00334       angle *= 180/PI;
00335 
00336       double x, y;
00337       lines[i].intersects(lines[j], x, y);
00338 
00339       // look through list of angles added so far,
00340       // if the angle we are currently looking at is
00341       // a similar angle, and it has a similar intersection
00342       // do not add it to angles vector
00343       bool add = true;
00344       for(uint k = 0; k < angles.size(); k++) {
00345         if(fabs(angles[k].angle - angle) < 5.0 &&
00346            (abs(angles[k].pos.i - (int)x) <= 2.0 && abs(angles[k].pos.j - (int)y) <= 2.0)) {
00347           add = false;
00348           break;
00349         }
00350       }
00351 
00352       // add angle if there no similar angles at intersections
00353       // in angles vector
00354       if(add && img->coordsOk((int)x, (int)y)) {
00355         BinAngles b;
00356         b.pos = *(new Point2D<int>((int)x, (int)y));
00357         b.angle = angle;
00358         angles.push_back(b);
00359       }
00360 
00361     }
00362   }
00363 
00364 }
00365 
00366 void BeoSubBin::removeOrangePipe(Image< PixRGB<byte> >& img) {
00367 
00368 //   Image<byte> orange(img.getWidth(), img.getHeight(), ZEROS);
00369 
00370 //   float mass = isolateOrange(img, orange);
00371 
00372 
00373 //   if(mass > 0) {
00374 
00375 //     for(int i = 0; i < img.getWidth(); i++) {
00376 //       for(int j = 0; j < img.getHeight(); j++) {
00377 
00378 //         if(orange.coordsOk(i, j) && orange.getVal(i, j) == 255)
00379 //           img.setVal(i, j, 0);
00380 
00381 //       }
00382 //     }
00383 
00384 //   }
00385 
00386 
00387 }
00388 
00389 void BeoSubBin::getWeightedBinMass(std::vector<BinAngles>& angles, Point2D<int> & center, bool cropWindow, Image<PixRGB<byte> > *img) {
00390 
00391   // find closest
00392   float DIST = 1;
00393 
00394   float avgY = 0;
00395 
00396   if(angles.size() > 0) {
00397     DIST = center.distance(angles[0].pos);
00398     avgY = angles[0].pos.j;
00399   }
00400 
00401 
00402   for(uint i = 1; i < angles.size(); i++) {
00403     float closer = center.distance(angles[i].pos);
00404 
00405     avgY += angles[i].pos.j;
00406 
00407     if(closer < DIST) //&& angles[i].pos.j > 100) //&& angles[i].angle < 80 && angles[i].angle > 40)
00408       DIST = closer;
00409 
00410   }
00411 
00412   avgY /= angles.size();
00413   avgY = 120 - avgY;
00414 
00415   float topCap = 0, bottomCap = 240;
00416 
00417   if(cropWindow && avgY < 0)
00418     bottomCap = 240 - avgY;
00419   else if(cropWindow)
00420     topCap = avgY;
00421 
00422   if(cropWindow) {
00423   LINFO("avgY: %f", avgY);
00424   drawLine(*img, Point2D<int>(0, (int)avgY), Point2D<int>(320, (int)avgY), PixRGB<byte>(255, 0, 0));
00425   drawLine(*img, Point2D<int>(0, (int)topCap), Point2D<int>(320, (int)topCap), PixRGB<byte>(255,0,0));
00426   drawLine(*img, Point2D<int>(0, (int)bottomCap), Point2D<int>(320, (int)bottomCap), PixRGB<byte>(255,0,0));
00427   }
00428 
00429   Point2D<int> weightedCenter = center;
00430   /// setup weighting system
00431   //// ORIGINAL DISTANCE / (WEIGHT)^2 from CLOSEST DISTANCE * WEIGHT = ORIGINAL DISTANCE
00432 
00433   printf("closest dist: %f\n", DIST);
00434 
00435   for(uint i = 0; i < angles.size(); i++) {
00436 
00437     if(angles[i].pos.j < bottomCap && angles[i].pos.j > topCap) {
00438       float currentDist = weightedCenter.distance(angles[i].pos);
00439       printf("current dist: %f, x: %d, y: %d\n", currentDist, angles[i].pos.i, angles[i].pos.j);
00440       float weight = 1 / (currentDist/DIST ); // * currentDist/DIST);
00441       printf("weight: %f\n", weight);
00442       float cx = (angles[i].pos.i - weightedCenter.i) * weight + weightedCenter.i;
00443       float cy = (angles[i].pos.j - weightedCenter.j) * weight + weightedCenter.j;
00444 
00445       Point2D<int> weightPoint((int)cx, (int)cy);
00446       printf("new point, x: %d, y: %d\n", weightPoint.i, weightPoint.j);
00447       center += weightPoint;
00448       center /= 2;
00449     }
00450   }
00451 
00452 }
00453 
00454 // THIS FUNCTION IS ONLY USED FOR FRONT CAMERA
00455 void BeoSubBin::getParallelIntersections(std::vector<LineSegment2D>& lines, std::vector<LineSegment2D>& frontLines,
00456                                          Image< PixRGB<byte> >& img) {
00457 
00458   printf("size of lines: %d\n", (int)lines.size());
00459 
00460   bool moreThanOne;
00461 
00462   frontLines.clear();
00463   std::vector<LineSegment2D> tmp = lines;
00464   std::vector<LineSegment2D>::iterator iter2 = tmp.begin();
00465 
00466  // left border of image
00467   LineSegment2D border2 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(0, img.getHeight()) ) );
00468   // right border of image
00469   LineSegment2D border3 ( *(new Point2D<int>(img.getWidth(), 0)), *(new Point2D<int>(img.getWidth(), img.getHeight()) ) );
00470 
00471   // iterate through set of lines
00472   for(uint i = 0; i < tmp.size(); i++) {
00473 
00474     moreThanOne = false;
00475     // check current line with other lines in the set
00476     iter2 = tmp.begin() + i + 1;
00477     while(tmp.size() > i+1 && iter2 != tmp.end()) {
00478 
00479       double x, y;
00480       x = y = -1;
00481       // if both lines do not intersect each other in the image
00482       // and current lines are not in a horizontal direction, add to output vector
00483       if((!lines[i].intersects(*iter2, x, y) && !img.coordsOk((int)x, (int)y)) &&
00484          lines[i].intersects(border2, x, y) && lines[i].intersects(border3, x, y)) {
00485 
00486         drawLine(img, (*iter2).point1(), (*iter2).point2(), PixRGB<byte>(0,255,0));
00487         frontLines.push_back(*iter2);
00488         tmp.erase(iter2);
00489         moreThanOne = true;
00490 
00491 
00492       }
00493       else
00494         iter2++;
00495     }
00496 
00497     // if we found parallel lines,
00498     // make sure we add the line we were checking against
00499     if(moreThanOne && tmp.size() > i) {
00500       iter2 = tmp.begin() + i;
00501       drawLine(img, (*iter2).point1(), (*iter2).point2(), PixRGB<byte>(0,255,200));
00502       frontLines.push_back(*iter2);
00503       tmp.erase(iter2);
00504     }
00505   }
00506 
00507   // get intersections
00508   printf("size of frontLines before adding intersections: %d\n", (int)frontLines.size());
00509   uint size = frontLines.size();
00510   iter2 = tmp.begin();
00511   for(uint i = 0; i < size; i++) {
00512     iter2 = tmp.begin();
00513     while(tmp.size() > 0 && iter2 != tmp.end()) {
00514 
00515       double x, y;
00516       x = y = -1;
00517       if(frontLines[i].intersects(*iter2, x, y) && img.coordsOk((int)x, (int)y)) {
00518         frontLines.push_back(*iter2);
00519         tmp.erase(iter2);
00520       }
00521       else
00522         iter2++;
00523     }
00524   }
00525 
00526 
00527   printf("size of frontLines: %d\n", (int)frontLines.size());
00528 }
00529 
00530 void BeoSubBin::getBinCenter(std::vector<BinAngles>& angles, Point2D<int>& center) {
00531 
00532   for(uint i = 0; i < angles.size(); i++)
00533     center += angles[i].pos;
00534 
00535   center /= angles.size();
00536 }
00537 
00538 // ######################################################################
00539 /* So things look consistent in everyone's emacs... */
00540 /* Local Variables: */
00541 /* indent-tabs-mode: nil */
00542 /* End: */
Generated on Sun May 8 08:04:32 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3