ImageSpring.H

Go to the documentation of this file.
00001 /*!@file Beobot/ImageSpring.H derived from the image template class */
00002 // all the pixels are linked to theirs neighbors with springs
00003 
00004 
00005 // //////////////////////////////////////////////////////////////////// //
00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00007 // University of Southern California (USC) and the iLab at USC.         //
00008 // See http://iLab.usc.edu for information about this project.          //
00009 // //////////////////////////////////////////////////////////////////// //
00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00012 // in Visual Environments, and Applications'' by Christof Koch and      //
00013 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00014 // pending; application number 09/912,225 filed July 23, 2001; see      //
00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00016 // //////////////////////////////////////////////////////////////////// //
00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00018 //                                                                      //
00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00020 // redistribute it and/or modify it under the terms of the GNU General  //
00021 // Public License as published by the Free Software Foundation; either  //
00022 // version 2 of the License, or (at your option) any later version.     //
00023 //                                                                      //
00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00027 // PURPOSE.  See the GNU General Public License for more details.       //
00028 //                                                                      //
00029 // You should have received a copy of the GNU General Public License    //
00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00032 // Boston, MA 02111-1307 USA.                                           //
00033 // //////////////////////////////////////////////////////////////////// //
00034 //
00035 // Primary maintainer for this file: Laurent Itti <itti@usc.edu>
00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/ImageSpring.H $
00037 // $Id: ImageSpring.H 9412 2008-03-10 23:10:15Z farhan $
00038 //
00039 
00040 #ifndef IMAGE_SPRING_H_DEFINED
00041 #define IMAGE_SPRING_H_DEFINED
00042 
00043 #include "Image/Image.H"
00044 #include "Util/Assert.H"
00045 
00046 template <class T> class PixRGB;
00047 
00048 //! This class is some sort of self organizing map used for clustering
00049 /*! All the pixels are linked by springs whose stiffness depends on the
00050     difference between them
00051 */
00052 template<class T>
00053 class ImageSpring : public Image<T>
00054 {
00055 public:
00056   //! Constructor that only allocates memory for given size
00057   inline ImageSpring(const int width, const int height,
00058                      const int nbNeighbors);
00059 
00060   //! Constructor for uninitialized image (useful for arrays of Images).
00061   /*! Use init() later to initialize */
00062   inline ImageSpring();
00063 
00064   //! Copy constructor
00065   inline ImageSpring(const ImageSpring<T>& A);
00066 
00067   //! init function
00068   inline void init(const int width, const int height,
00069                    const int nbNeighbors);
00070 
00071   //! init function, to copy another ImageSpring
00072   inline void init(const T* a, const float* posX, const float* posY,
00073                    const float** stiff,
00074                    const int width, const int height,
00075                    const int nbNeighbors);
00076 
00077   //! Destructor
00078   inline ~ImageSpring();
00079 
00080   //! Free memory and switch to uninitialized state
00081   inline void freeMem();
00082 
00083   //! initialize 'stiff' and 'pos'
00084   void initClustering(bool initPosMasses);
00085 
00086   //! compute the stiffness of the spring between the masses
00087   /*! based on the color-distance between pixels */
00088   void computeStiff(void);
00089 
00090   //! updates the positions of the masses
00091   /*! based on simple mechanics */
00092   void computePos(const float dt);
00093 
00094   //! computes mean and stdev (**heuristic**)
00095   /*! this function is a heuristic because it will only
00096     consider nbHeuristic pixels at random */
00097   void getStats(void);
00098 
00099   //! computes meanDist and stdevDist (**heuristic**)
00100   /*! weight must be defined
00101     this function is an heuristic because it will only
00102     consider nbHeuristic pairs of pixels at random */
00103   void getStatsDist(void);
00104 
00105   //! returns (X,Y) given an index=X+w*Y (see posX)
00106   inline void getXY(const int index, Point2D<int> &pt) const;
00107 
00108   //! returns the index=X+w*Y (see posX)
00109   inline void getIndex(const Point2D<int> point, int &index) const;
00110 
00111   //! returns the number of neighbors
00112   inline int getNbNeighbors(void) const;
00113 
00114   //! distance between the 2 masses
00115   float getDistanceMasses(const int index1, const int index2) const;
00116 
00117   //! computes the index of the nth neighbor of "index"
00118   /*! returns true iif the neighbor is in the image */
00119   inline bool getNeighbor(const int index, const int n,
00120                           int& indexNeighbor) const;
00121 
00122   //! Get position of masses and strength of springs (for debug)
00123   void getPositions(Image< PixRGB<byte> >& img, const int zoom = 16);
00124 
00125 
00126   //! get clustered image and track centroid position
00127   void getClusteredImage(const Image< PixRGB<byte> > &scene,
00128                          Image< PixRGB<byte> > &clusteredImage,
00129                          Point2D<int> &supposedTrackCentroid,
00130                          const Point2D<int>& previousTrackCentroid);
00131 
00132 private:
00133   //! subfunction find n-connex graph
00134   /*! n connex sub-graph are the subgraph whose nodes are connected to
00135    one another by at least n links. The nodes already marked have non 0
00136   values in 'marked', the current node is 'currentPoint' and the current label
00137   (i.e. number of the group) is 'color'. 'begin' is used to initialize the
00138   algorithm because if we apply n-connexity from the beginng then obviously
00139   no node will qualify as the first one we see has 0 neighbors... */
00140   void goGraph(Image<int32> &marked, const int currentIndex,
00141                const int32 color, const int begin = 3);
00142 
00143   //! defines the neighborhhod topology (5, 9 or 25)
00144   /*! see "getNeighbor" for indexing */
00145   int nbNeighbors;
00146 
00147   //! mean and stdev of the image
00148   /*! not necessarily scalar, don't confuse with meanDist, stdevDist */
00149   T mean, stdev;
00150 
00151   //! mean and stdev of the distance between meighbor pixels
00152   /*! always scalar by definition of  adistance...
00153     don't be confused, it's NOT the mean and stdev of the image */
00154   double meanDist, stdevDist;
00155 
00156   //! to define weightedDistance() between pixels
00157   /*! this is normally stdev.inverse(), this way the system is
00158       completly independent from the dynamic range of the low
00159       level features */
00160   T weight;
00161 
00162   //! physical position of the "masses" at time t
00163   /*! 2D array represented as 1D array: index = x+y*nX */
00164   float *posX, *posY;
00165 
00166   //! physical position of the "masses" at time t-dt.
00167   float *oldPosX, *oldPosY;
00168 
00169   /*! stiff[index][n] is the stiffness of the spring between index and
00170     its nth neighbor. Note: we consider that length is 0 for all
00171     springs ! */
00172   float **stiff;
00173 
00174   //! computes weight given mean & stdev
00175   void computeWeight(void);
00176 
00177   //! sets the "physical" position of mass at (x,y)
00178   inline void setPos(const Point2D<int> mass, const float x, const float y);
00179 
00180   //! sets the stiffness of the spring
00181   inline void setStiff(const Point2D<int> mas, int neighboor, float stiff);
00182 
00183   //! the moments will be estimated with nbHeuristic outcomes
00184   const static int nbHeuristic = 500;
00185 };
00186 
00187 // ######################################################################
00188 // ######################################################################
00189 // ######################################################################
00190 // INLINE FUNCTIONS:
00191 // ######################################################################
00192 // ######################################################################
00193 // ######################################################################
00194 
00195 // ######################################################################
00196 template<class T> inline
00197 ImageSpring<T>::ImageSpring(const int width, const int height,
00198                             const int nbN) :
00199   Image<T>(width, height, NO_INIT)
00200 {
00201   init(width, height, nbN);
00202 }
00203 
00204 // ######################################################################
00205 template<class T> inline
00206 ImageSpring<T>::ImageSpring() : Image<T>()
00207 { posX = NULL; posY = NULL; oldPosX = NULL; oldPosY = NULL; stiff = NULL; }
00208 
00209 // ######################################################################
00210 template<class T> inline
00211 ImageSpring<T>::ImageSpring(const ImageSpring<T>& A) : Image<T>(A)
00212 {
00213   ASSERT(A.initialized());
00214   posX = NULL; posY = NULL; oldPosX = NULL; oldPosY = NULL; stiff = NULL;
00215 
00216   init(A.getArrayPtr(), posX, posY, const_cast<const float**>(A.stiff),
00217        A.getWidth(), A.getHeight(), A.nbNeighbors);
00218 }
00219 
00220 // ######################################################################
00221 template<class T> inline
00222 ImageSpring<T>::~ImageSpring()
00223 { freeMem(); }
00224 
00225 // ######################################################################
00226 template<class T> inline
00227 void ImageSpring<T>::freeMem()
00228 {
00229   if (stiff) {
00230     for (int index = 0;index < this->getSize(); index++) delete [] stiff[index];
00231     delete [] stiff; stiff = NULL;
00232   }
00233   if (posX) { delete [] posX; posX = NULL; }
00234   if (posY) { delete [] posY; posY = NULL; }
00235   if (oldPosX) { delete [] oldPosX; oldPosX = NULL; }
00236   if (oldPosY) { delete [] oldPosY; oldPosY = NULL; }
00237   Image<T>::freeMem();
00238 }
00239 
00240 // ######################################################################
00241 template<class T> inline
00242 void ImageSpring<T>::init(const T* inarray,
00243                           const float* inPosX, const float* inPosY,
00244                           const float** inStiff,
00245                           const int width, const int height,
00246                           const int nbN)
00247 {
00248   freeMem();  // delete any allocated memory
00249   this->resize(width, height);  // allocate underlying Image<T>
00250   nbNeighbors = nbN; int size = this->getSize();
00251 
00252   // allocate memory for the mass positions:
00253   posX = new float[size]; memcpy(posX, inPosX, size * sizeof(float));
00254   posY = new float[size]; memcpy(posY, inPosY, size * sizeof(float));
00255   oldPosX = new float[size]; memcpy(oldPosX, inPosX, size * sizeof(float));
00256   oldPosY = new float[size]; memcpy(oldPosY, inPosY, size * sizeof(float));
00257 
00258   // the neighbor #0 is the grid point, so there are nbN+1 neighbors
00259   typedef float* floatptr;
00260   stiff = new floatptr[size];
00261   for (int index = 0; index < size; index++)
00262     {
00263       stiff[index] = new float[nbN + 1];
00264       memcpy(stiff[index], inStiff[index], (nbN + 1) * sizeof(float));
00265     }
00266 }
00267 
00268 // ######################################################################
00269 template<class T> inline
00270 void ImageSpring<T>::init(const int width, const int height,
00271                           const int nbN)
00272 {
00273   freeMem();  // delete any allocated memory
00274   this->resize(width, height);  // allocate underlying Image<T>
00275   nbNeighbors = nbN; int size = this->getSize();
00276 
00277   // allocate memory for the mass positions:
00278   posX = new float[size]; posY = new float[size];
00279   oldPosX = new float[size]; oldPosY = new float[size];
00280 
00281   typedef float* floatptr;
00282   stiff = new floatptr[size];
00283   for (int index = 0; index < size; index++) stiff[index] = new float[nbN + 1];
00284 }
00285 
00286 // ######################################################################
00287 template<class T> inline
00288 void ImageSpring<T>::getXY( const int index, Point2D<int> &pt ) const
00289 { pt.i = index % this->getWidth(); pt.j = index / this->getWidth(); }
00290 
00291 // ######################################################################
00292 template<class T> inline
00293 void ImageSpring<T>::getIndex( const Point2D<int> point, int &index ) const
00294 { index = point.i + point.j * this->getWidth(); }
00295 
00296 // ######################################################################
00297 template<class T> inline
00298 bool ImageSpring<T>::getNeighbor( const int index, const int n,
00299                                   int& indexNeighbor ) const
00300 {
00301   ASSERT(n > 0 && n <= nbNeighbors);
00302 
00303   Point2D<int> pt; getXY(index, pt);
00304 
00305   switch(n)
00306     {
00307     case 0 : break;   // to the grid
00308 
00309       // 4-neighbors
00310     case 1 : pt.i--;         break;
00311     case 2 :         pt.j--; break;
00312     case 3 : pt.i++;         break;
00313     case 4 :         pt.j++; break;
00314 
00315       // 8-neighbors
00316     case 5 : pt.i--; pt.j--; break;
00317     case 6 : pt.i++; pt.j--; break;
00318     case 7 : pt.i--; pt.j++; break;
00319     case 8 : pt.i++; pt.j++; break;
00320 
00321       // 24-neighbors
00322     case 9 : pt.i-=2; pt.j+=2; break;
00323     case 10: pt.i-=1; pt.j+=2; break;
00324     case 11:          pt.j+=2; break;
00325     case 12: pt.i+=1; pt.j+=2; break;
00326     case 13: pt.i+=2; pt.j+=2; break;
00327     case 14: pt.i+=2; pt.j+=1; break;
00328     case 15: pt.i+=2;          break;
00329     case 16: pt.i+=2; pt.j-=1; break;
00330     case 17: pt.i+=2; pt.j-=2; break;
00331     case 18: pt.i+=1; pt.j-=2; break;
00332     case 19:          pt.j-=2; break;
00333     case 20: pt.i-=1; pt.j-=2; break;
00334     case 21: pt.i-=2; pt.j-=2; break;
00335     case 22: pt.i-=2; pt.j-=1; break;
00336     case 23: pt.i-=2;          break;
00337     case 24: pt.i-=2; pt.j+=1; break;
00338 
00339       // larger than that is unsupported:
00340     default:
00341       LFATAL("Neighbor out or range");
00342     }
00343 
00344   getIndex( pt, indexNeighbor );
00345 
00346   return this->coordsOk( pt );
00347 }
00348 
00349 // ######################################################################
00350 template<class T> inline
00351 int ImageSpring<T>::getNbNeighbors( void ) const
00352 { return nbNeighbors; }
00353 
00354 // ######################################################################
00355 template<class T> inline
00356 void ImageSpring<T>::setPos(const Point2D<int> mass, const float x, const float y)
00357 {
00358   ASSERT(this->initialized() && this->coordsOk(mass));
00359   int index; getIndex(mass, index);
00360   posX[index] = x; posY[index] = y;
00361 }
00362 
00363 // ######################################################################
00364 template<class T>
00365 void ImageSpring<T>::setStiff(const Point2D<int> mass, int neighbor, float stif)
00366 {
00367   ASSERT(this->initialized() && this->coordsOk(mass) && neighbor <= nbNeighbors);
00368   int index; getIndex(mass, index);
00369   stiff[index][neighbor] = stif;
00370 }
00371 
00372 
00373 
00374 // ######################################################################
00375 /* So things look consistent in everyone's emacs... */
00376 /* Local Variables: */
00377 /* indent-tabs-mode: nil */
00378 /* End: */
00379 
00380 #endif
Generated on Sun May 8 08:04:29 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3