CannyModel.C

Go to the documentation of this file.
00001 /*!@file BeoSub/CannyModel.C Simple shape models */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Zack Gossman <gossman@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/BeoSub/CannyModel.C $
00035 // $Id: CannyModel.C 9412 2008-03-10 23:10:15Z farhan $
00036 //
00037 
00038 #include "CannyModel.H"
00039 #include "Image/DrawOps.H"
00040 #include "Image/ColorOps.H"
00041 #include "GUI/XWindow.H"
00042 #include <cmath>
00043 
00044 // ######################################################################
00045 ShapeModel::ShapeModel(const int ndims, const double thresh,
00046                        double* dims, const bool debug) :
00047   itsNumDims(ndims), itsThreshold(thresh),
00048   itsDebugMode(debug), itsWindow()
00049 {
00050 
00051   itsDimensions = (double*)calloc(ndims+1, sizeof(double));
00052   for(int i = 0; i <=ndims; i++){
00053 
00054     itsDimensions[i] = dims[i];
00055   }
00056 
00057 }
00058 
00059 // ######################################################################
00060 ShapeModel::~ShapeModel()
00061 {
00062   itsWindow.reset(NULL);
00063 }
00064 
00065 // ######################################################################
00066 double ShapeModel::getThreshold() const
00067 { return itsThreshold; }
00068 
00069 // ######################################################################
00070 int ShapeModel::getNumDims() const
00071 { return itsNumDims; }
00072 
00073 double* ShapeModel::getDimensions() const
00074 {
00075   double* tempDims = (double*)calloc(itsNumDims+1, sizeof(double));
00076   for(int i = 0; i < itsNumDims; i++){
00077     tempDims[i] = itsDimensions[i];
00078   }
00079 
00080   return itsDimensions;
00081 }
00082 
00083 void ShapeModel::setDimensions(double* in)
00084 {
00085   for(int i = 0; i <=itsNumDims; i++){
00086     itsDimensions[i] = in[i];
00087   }
00088 }
00089 
00090 // ######################################################################
00091 float ShapeModel::getDistVal(const double x, const double y,
00092                              const Image<float>& distMap,
00093                              Image< PixRGB<byte> >& xdisp) const
00094 {
00095   int xx = int(x + 0.5), yy = int(y + 0.5);
00096 
00097   // if we are inside the image, just get the distance from the
00098   // distance map:
00099   if (distMap.coordsOk(int(x), int(y)))
00100     {
00101       if (xdisp.initialized())
00102         drawDisk(xdisp, Point2D<int>(xx, yy), 3, PixRGB<byte>(255, 0, 0));
00103       float d = distMap.getValInterp(x, y);
00104       return d * d;
00105     }
00106   else
00107     {
00108       // we are outside the distance map; return an error that depends
00109       // on how far outside we are:
00110       int xerror = 0, yerror = 0;
00111       if (xx < 0) xerror = -xx;
00112       else if (xx >= distMap.getWidth()) xerror = xx - distMap.getWidth();
00113 
00114       if (yy < 0) yerror = -yy;
00115       else if (yy > distMap.getHeight()) yerror = yy - distMap.getHeight();
00116 
00117       return 10.0f * ((xerror + yerror) * (xerror + yerror));//May need a higher penalty than 10. FIX?
00118     }
00119 }
00120 
00121 // ######################################################################
00122 double ShapeModel::calcDist(double p[], const Image<float>& distMap) const
00123 {
00124 
00125   // Prepare an image to draw into:
00126   Image< PixRGB<byte> > xdisp;
00127   xdisp = toRGB(Image<byte>(distMap));
00128 
00129   // if this is the first time we are called and we are in debug mode,
00130   // open an XWindow of the size of the distMap:
00131   if (itsWindow.get() == NULL && itsDebugMode == true){
00132     const_cast<ShapeModel *>(this)->
00133       itsWindow.reset(new XWindow(distMap.getDims()));
00134     const_cast<ShapeModel *>(this)->
00135       itsWindow->setPosition((xdisp.getWidth()*2)+20, 0);
00136   }
00137 
00138   // get the distance:
00139   double dist = getDist(p, distMap, xdisp);
00140 
00141   // if we have a window, show shape and distance map:
00142   if (itsWindow.get()){
00143     itsWindow->drawImage(xdisp);
00144   }
00145   return dist;
00146 }
00147 
00148 // ######################################################################
00149 RectangleShape::RectangleShape(const double thresh, double* dims, const bool debug) :
00150   ShapeModel(5, thresh, dims, debug)
00151 {  }
00152 
00153 // ######################################################################
00154 RectangleShape::~RectangleShape()
00155 { }
00156 
00157 // ######################################################################
00158 float RectangleShape::getDist(double p[], const Image<float>& distMap,
00159                               Image< PixRGB<byte> >& xdisp) const
00160 {
00161   //NEED to put in limitations keeping shape from becoming too small and keeping any part of the shape from leaving the scope of the image! FIX!!
00162 
00163   // ########## Parse the parameters into human form:
00164   double x_center = p[1];
00165   double y_center = p[2];
00166   double alpha = p[3];
00167 
00168   double width = p[4];
00169   double height = p[5];
00170 
00171   // ########## Trace the shape and accumulate distances:
00172   float sina = sin(alpha/10.0);
00173   float cosa = cos(alpha/10.0);
00174   int numPts = 0;
00175   float dist = 0.0;
00176 
00177   // The following is code for a free-form rectangle.
00178   for (int i = -5; i < 5; i++) {
00179     // (-w/2,-h/2) -> (-w/2, h/2)
00180     float tempValX = x_center - width*cosa/2.0 - (i+1)*height*sina/10.0;
00181     float tempValY = y_center - width*sina/2.0 + (i+1)*height*cosa/10.0;
00182     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00183     numPts++;
00184 
00185     // (w/2, -h/2) -> (w/2, h/2)
00186     tempValX = x_center + width*cosa/2.0 - (i+1)*height*sina/10.0;
00187     tempValY = y_center + width*sina/2.0 + (i+1)*height*cosa/10.0;
00188     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00189     numPts++;
00190 
00191     // (-w/2, -h/2) -> (w/2, -h/2)
00192     tempValX = x_center + height*sina/2.0 + (i+1)*width*cosa/10.0;
00193     tempValY = y_center - height*cosa/2.0 + (i+1)*width*sina/10.0;
00194     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00195     numPts++;
00196 
00197     // (-w/2, h/2) -> (w/2, h/2)
00198     tempValX = x_center - height*sina/2.0 + (i+1)*width*cosa/10.0;
00199     tempValY = y_center + height*cosa/2.0 + (i+1)*width*sina/10.0;
00200     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00201     numPts++;
00202   }
00203 
00204   dist = dist / numPts;
00205 
00206   // ########## Add a distance penalty if shape too small:
00207   if (width < 40) dist += (10.0*((40 - width) * (40 - width)));
00208   if (height < 30) dist += (10.0*((30 - height) * (30-height)));
00209 
00210   return dist;
00211 }
00212 
00213 
00214 // ######################################################################
00215 SquareShape::SquareShape(const double thresh, double* dims, const bool debug) :
00216   ShapeModel(4, thresh, dims, debug)
00217 {  }
00218 
00219 // ######################################################################
00220 SquareShape::~SquareShape()
00221 { }
00222 
00223 // ######################################################################
00224 float SquareShape::getDist(double p[], const Image<float>& distMap,
00225                               Image< PixRGB<byte> >& xdisp) const
00226 {
00227   // ########## Parse the parameters into human form:
00228   double x_center = p[1];
00229   double y_center = p[2];
00230   double alpha = p[4];
00231   double height = p[3];
00232 
00233   // ########## Trace the shape and accumulate distances:
00234   float sina = sin(alpha/10.0);
00235   float cosa = cos(alpha/10.0);
00236   int numPts = 0;
00237   float dist = 0.0;
00238 
00239   //Following is the mathematical representation of a square
00240   for(int i=-5; i<5; i++) {
00241     // (-h/2,-h/2) -> (-h/2, h/2)
00242     float tempValX = x_center - height*cosa/2 - (i+1)*height*sina/10;
00243     float tempValY = y_center - height*sina/2 + (i+1)*height*cosa/10;
00244     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00245     numPts++;
00246 
00247     // (h/2, -h/2) -> (h/2, h/2)
00248     tempValX = x_center + height*cosa/2 - (i+1)*height*sina/10;
00249     tempValY = y_center + height*sina/2 + (i+1)*height*cosa/10;
00250     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00251     numPts++;
00252 
00253     // (-h/2, -h/2) -> (h/2, -h/2)
00254     tempValX = x_center + height*sina/2 + (i+1)*height*cosa/10;
00255     tempValY = y_center - height*cosa/2 + (i+1)*height*sina/10;
00256     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00257     numPts++;
00258 
00259     // (-h/2, h/2) -> (h/2, h/2)
00260     tempValX = x_center - height*sina/2 + (i+1)*height*cosa/10;
00261     tempValY = y_center + height*cosa/2 + (i+1)*height*sina/10;
00262     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00263     numPts++;
00264   }
00265 
00266   dist = dist / numPts;
00267 
00268   // ########## Add a distance penalty if shape too small:
00269   if (height < 30) dist += (10.0 * ((30 - height)*(30 - height)));
00270 
00271   return dist;
00272 }
00273 
00274 
00275 
00276 // ######################################################################
00277 OctagonShape::OctagonShape(const double thresh, double* dims, const bool debug) :
00278   ShapeModel(4, thresh, dims, debug)
00279 {  }
00280 
00281 // ######################################################################
00282 OctagonShape::~OctagonShape()
00283 { }
00284 
00285 // ######################################################################
00286 float OctagonShape::getDist(double p[], const Image<float>& distMap,
00287                               Image< PixRGB<byte> >& xdisp) const
00288 {
00289   // ########## Parse the parameters into human form:
00290   double x_center = p[1];
00291   double y_center = p[2];
00292   double alpha = p[4];
00293   double height = p[3]; //note that "height" may not be quite the correct label here
00294 
00295   // ########## Trace the shape and accumulate distances:
00296   float sina = sin(alpha/10.0);
00297   float cosa = cos(alpha/10.0);
00298   //funky angles for diagonal edges in octagon
00299   float sinb = sin((alpha+40.00)/10.0);
00300   float cosb = cos((alpha+40.00)/10.0);
00301   int numPts = 0;
00302   float dist = 0.0;
00303 
00304 
00305   //Following is the mathematical representation of an octagon
00306   for(int i=-5; i<5; i++) {
00307       //Diagonal edges are even-numbered
00308       // edge 1
00309       float tempValX = x_center - height*cosa/2 - ((i+1)*height*sina/10)/2.2;
00310       float tempValY = y_center - height*sina/2 + ((i+1)*height*cosa/10)/2.2;
00311       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00312       numPts++;
00313 
00314       //edge 2
00315       tempValX = x_center - height*cosb/2 - ((i+1)*height*sinb/10)/2.2;
00316       tempValY = y_center - height*sinb/2 + ((i+1)*height*cosb/10)/2.2;
00317       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00318       numPts++;
00319 
00320       // edge 3
00321       tempValX = x_center + height*cosa/2 - ((i+1)*height*sina/10)/2.2;
00322       tempValY = y_center + height*sina/2 + ((i+1)*height*cosa/10)/2.2;
00323       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00324       numPts++;
00325 
00326       // edge 4
00327       tempValX = x_center + height*cosb/2 - ((i+1)*height*sinb/10)/2.2;
00328       tempValY = y_center + height*sinb/2 + ((i+1)*height*cosb/10)/2.2;
00329       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00330       numPts++;
00331 
00332       // edge 5
00333       tempValX = x_center + height*sina/2 + ((i+1)*height*cosa/10)/2.2;
00334       tempValY = y_center - height*cosa/2 + ((i+1)*height*sina/10)/2.2;
00335       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00336       numPts++;
00337 
00338       // edge 6
00339       tempValX = x_center + height*sinb/2 + ((i+1)*height*cosb/10)/2.2;
00340       tempValY = y_center - height*cosb/2 + ((i+1)*height*sinb/10)/2.2;
00341       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00342       numPts++;
00343 
00344       // edge 7
00345       tempValX = x_center - height*sina/2 + ((i+1)*height*cosa/10)/2.2;
00346       tempValY = y_center + height*cosa/2 + ((i+1)*height*sina/10)/2.2;
00347       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00348       numPts++;
00349 
00350       // edge 8
00351       tempValX = x_center - height*sinb/2 + ((i+1)*height*cosb/10)/2.2;
00352       tempValY = y_center + height*cosb/2 + ((i+1)*height*sinb/10)/2.2;
00353       dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00354       numPts++;
00355     }
00356 
00357   dist = dist / numPts;
00358 
00359   // ########## Add a distance penalty if shape too small:
00360   if (height < 20) dist += (10.0 * ((20 - height) * (20 - height)));
00361 
00362   return dist;
00363 }
00364 
00365 
00366 
00367 // ######################################################################
00368 CircleShape::CircleShape(const double thresh, double* dims, const bool debug) :
00369   ShapeModel(3, thresh, dims, debug)
00370 {  }
00371 
00372 // ######################################################################
00373 CircleShape::~CircleShape()
00374 { }
00375 
00376 // ######################################################################
00377 float CircleShape::getDist(double p[], const Image<float>& distMap,
00378                               Image< PixRGB<byte> >& xdisp) const
00379 {
00380   // ########## Parse the parameters into human form:
00381   double x_center = p[1];
00382   double y_center = p[2];
00383   double radius = p[3];
00384 
00385   // ########## Trace the shape and accumulate distances:
00386   int numPts = 0;
00387   float dist = 0.0;
00388 
00389 
00390   //Following is the mathematical representation of a circle
00391   for(int i=-7; i<7; i++) {
00392     // The following is code for a circle
00393     float tempValX = x_center + radius * cos(i*2*M_PI/14);
00394     float tempValY = y_center + radius * sin(i*2*M_PI/14);
00395     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00396     numPts++;
00397   }
00398 
00399   dist = dist / numPts;
00400 
00401   // ########## Add a distance penalty if shape too small:
00402   if (radius < 20) dist += (10.0 * ((20 - radius) * (20 - radius)));
00403 
00404   return dist;
00405 }
00406 
00407 
00408 
00409 // ######################################################################
00410 ParallelShape::ParallelShape(const double thresh, double* dims, const bool debug) :
00411   ShapeModel(5, thresh, dims, debug)
00412 {  }
00413 
00414 // ######################################################################
00415 ParallelShape::~ParallelShape()
00416 { }
00417 
00418 // ######################################################################
00419 float ParallelShape::getDist(double p[], const Image<float>& distMap,
00420                               Image< PixRGB<byte> >& xdisp) const
00421 {
00422 
00423   // ########## Parse the parameters into human form:
00424   double x_center = p[1];
00425   double y_center = p[2];
00426   double alpha = p[3];
00427 
00428   double width = p[4];
00429   double height = p[5];
00430 
00431   // ########## Trace the shape and accumulate distances:
00432   float sina = sin(alpha/10.0);
00433   float cosa = cos(alpha/10.0);
00434   int numPts = 0;
00435   float dist = 0.0;
00436 
00437   // The following is code for a free-form rectangle.
00438   for (int i = -5; i < 5; i++) {
00439 
00440     // (-w/2, -h/2) -> (w/2, -h/2)
00441     float tempValX = x_center + height*sina/2.0 + (i+1)*width*cosa/10.0;
00442     float tempValY = y_center - height*cosa/2.0 + (i+1)*width*sina/10.0;
00443     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00444     numPts++;
00445 
00446     // (-w/2, h/2) -> (w/2, h/2)
00447     tempValX = x_center - height*sina/2.0 + (i+1)*width*cosa/10.0;
00448     tempValY = y_center + height*cosa/2.0 + (i+1)*width*sina/10.0;
00449     dist += getDistVal(tempValX, tempValY, distMap, xdisp);
00450     numPts++;
00451   }
00452 
00453   dist = dist / numPts;
00454 
00455   // ########## Add a distance penalty if shape too small:
00456   if (width < 70) dist += (10.0 * ((70 - width) * (70-width)));
00457   if (height < 30) dist += (10.0 * ((30 - height) * (30 - height)));
00458 
00459   return dist;
00460 }
00461 // ######################################################################
00462 /* So things look consistent in everyone's emacs... */
00463 /* Local Variables: */
00464 /* indent-tabs-mode: nil */
00465 /* End: */
Generated on Sun May 8 08:04:33 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3