BlurFoveator.C

Go to the documentation of this file.
00001 /*!@file Foveator/BlurFoveator.C Foveator class that performs progressive blurring */
00002 
00003 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Foveator/BlurFoveator.C $
00004 // $Id: BlurFoveator.C 4663 2005-06-23 17:47:28Z rjpeters $
00005 
00006 #include "Foveator/BlurFoveator.H"
00007 
00008 #include "Image/Pixels.H"
00009 
00010 #include <algorithm> // for std::max()
00011 #include <cmath>
00012 
00013 // ######################################################################
00014 
00015 // constructor with initialization of original image
00016 BlurFoveator::BlurFoveator( const Image< PixRGB< byte > >& img,
00017                             int filterSize ) : Foveator( img )
00018 {
00019   // find the greater of two dimensions
00020   int dMax = std::max( width, height );
00021 
00022   // generate blur filters
00023   matrices = (dMax+1) * dMax / 2 - 1;
00024   typedef GaussianBlurMatrix* GaussianBlurMatrixPtr;
00025   gbms = new GaussianBlurMatrixPtr[matrices];
00026   int k = -1;
00027   for( int i = 0; i < dMax; i++ )
00028     {
00029       for( int j = 0; j <= i; j++ )
00030         {
00031           if( k > -1 )
00032             {
00033               gbms[k] = new GaussianBlurMatrix( filterSize );
00034               gbms[k]->setBlurRadius( radius( i, j, width * height ) );
00035             }
00036           k++;
00037         }
00038     }
00039 }
00040 
00041 // copy constructor
00042 BlurFoveator::BlurFoveator( const BlurFoveator& bf ) :
00043   Foveator( bf.original )
00044 {
00045   matrices = bf.matrices;
00046   typedef GaussianBlurMatrix* GaussianBlurMatrixPtr;
00047   gbms = new GaussianBlurMatrixPtr[matrices];
00048   for( int i = 0; i < matrices; i++ )
00049     {
00050       gbms[i] = new GaussianBlurMatrix( *(bf.gbms[i]) );
00051     }
00052 }
00053 
00054 // assignment operator
00055 BlurFoveator& BlurFoveator::operator=( const BlurFoveator& bf )
00056 {
00057   BlurFoveator *newbf = new BlurFoveator( bf );
00058   return *newbf;
00059 }
00060 
00061 // destructor
00062 BlurFoveator::~BlurFoveator()
00063 {
00064   delete [] gbms;
00065 }
00066 
00067 // ######################################################################
00068 
00069 // constructor for GaussianBlurMatrix
00070 BlurFoveator::GaussianBlurMatrix::GaussianBlurMatrix( int filterSize )
00071 {
00072   if( filterSize % 2 == 0)
00073     {
00074       LERROR( "Blur filter size should be positive odd integer!" );
00075       LINFO( "Blur foveation will be unstable/unpredictable!" );
00076     }
00077   halfFilter = filterSize/2 + 1;
00078   size = (halfFilter+1) * halfFilter / 2;
00079   weights = new float[size];
00080 }
00081 
00082 // copy constructor for GaussianBlurMatrix
00083 BlurFoveator::GaussianBlurMatrix::
00084 GaussianBlurMatrix( const GaussianBlurMatrix& gbm )
00085 {
00086   halfFilter = gbm.halfFilter;
00087   size = gbm.size;
00088   weights = new float[size];
00089   for( int i = 0; i < size; i++ )
00090     {
00091       weights[i] = gbm.weights[i];
00092     }
00093 }
00094 
00095 // assignment operator
00096 BlurFoveator::GaussianBlurMatrix& BlurFoveator::GaussianBlurMatrix::
00097 operator=( const GaussianBlurMatrix& gbm )
00098 {
00099   GaussianBlurMatrix *newgbm = new GaussianBlurMatrix( gbm );
00100   return *newgbm;
00101 }
00102 
00103 // destructor for GaussianBlurMatrix
00104 BlurFoveator::GaussianBlurMatrix::~GaussianBlurMatrix()
00105 {
00106   delete [] weights;
00107 }
00108 
00109 // calculate a blurred pixel
00110 PixRGB<byte> BlurFoveator::GaussianBlurMatrix::
00111 blurPixel( int x, int y, const Image< PixRGB<byte> >& img ) const
00112 {
00113   float newR = 0.0f;
00114   float newG = 0.0f;
00115   float newB = 0.0f;
00116   float denom = 0.0f;
00117 
00118   int k = 0;
00119   for( int i = 0; i < halfFilter; i++ )
00120     {
00121       for( int j = 0; j <= i; j++ )
00122         {
00123           if( !k )
00124             {
00125               PixRGB<byte> pix = img.getVal( x, y );
00126               newR += pix.red();
00127               newG += pix.green();
00128               newB += pix.blue();
00129               denom++;
00130             }
00131           else
00132             {
00133               if( img.coordsOk( x + i, y + j ) )
00134                 {
00135                   PixRGB<byte> pix = img.getVal( x + i, y + j );
00136                   newR += weights[k] * pix.red();
00137                   newG += weights[k] * pix.green();
00138                   newB += weights[k] * pix.blue();
00139                   denom += weights[k];
00140                 }
00141               if( img.coordsOk( x + j, y + i ) )
00142                 {
00143                   PixRGB<byte> pix = img.getVal( x + j, y + i );
00144                   newR += weights[k] * pix.red();
00145                   newG += weights[k] * pix.green();
00146                   newB += weights[k] * pix.blue();
00147                   denom += weights[k];
00148                 }
00149               if( img.coordsOk( x - i, y + j ) )
00150                 {
00151                   PixRGB<byte> pix = img.getVal( x - i, y + j );
00152                   newR += weights[k] * pix.red();
00153                   newG += weights[k] * pix.green();
00154                   newB += weights[k] * pix.blue();
00155                   denom += weights[k];
00156                 }
00157               if( img.coordsOk( x - j, y + i ) )
00158                 {
00159                   PixRGB<byte> pix = img.getVal( x - j, y + i );
00160                   newR += weights[k] * pix.red();
00161                   newG += weights[k] * pix.green();
00162                   newB += weights[k] * pix.blue();
00163                   denom += weights[k];
00164                 }
00165               if( img.coordsOk( x - i, y - j ) )
00166                 {
00167                   PixRGB<byte> pix = img.getVal( x - i, y - j );
00168                   newR += weights[k] * pix.red();
00169                   newG += weights[k] * pix.green();
00170                   newB += weights[k] * pix.blue();
00171                   denom += weights[k];
00172                 }
00173               if( img.coordsOk( x - j, y - i ) )
00174                 {
00175                   PixRGB<byte> pix = img.getVal( x - j, y - i );
00176                   newR += weights[k] * pix.red();
00177                   newG += weights[k] * pix.green();
00178                   newB += weights[k] * pix.blue();
00179                   denom += weights[k];
00180                 }
00181               if( img.coordsOk( x + i, y - j ) )
00182                 {
00183                   PixRGB<byte> pix = img.getVal( x + i, y - j );
00184                   newR += weights[k] * pix.red();
00185                   newG += weights[k] * pix.green();
00186                   newB += weights[k] * pix.blue();
00187                   denom += weights[k];
00188                 }
00189               if( img.coordsOk( x + j, y - i ) )
00190                 {
00191                   PixRGB<byte> pix = img.getVal( x + j, y - i );
00192                   newR += weights[k] * pix.red();
00193                   newG += weights[k] * pix.green();
00194                   newB += weights[k] * pix.blue();
00195                   denom += weights[k];
00196                 }
00197             }
00198           k++;
00199         }
00200     }
00201 
00202   newR /= denom;
00203   newG /= denom;
00204   newB /= denom;
00205   PixRGB<byte> newPixel( newR, newG, newB );
00206   return newPixel;
00207 }
00208 
00209 // set Gaussian blur radius
00210 void BlurFoveator::GaussianBlurMatrix::setBlurRadius( const float& r )
00211 {
00212   int k = 0;
00213   for( int i = 0; i < halfFilter; i++ )
00214     {
00215       for( int j = 0; j <= i; j++ )
00216         {
00217           weights[k] = (float)( exp( -( (i*i+j*j)/(2*r*r) ) ) );
00218           k++;
00219         }
00220     }
00221 }
00222 
00223 // ######################################################################
00224 
00225 // Radius calculation function based on distance between point and origin
00226 // Should be monotonic increasing
00227 float BlurFoveator::radius( int x, int y, int area )
00228 {
00229   return( 10.0f * ( x*x + y*y ) / area + 0.5f );
00230 }
00231 
00232 // Blur-foveation method, returns foveated image
00233 Image< PixRGB<byte> > BlurFoveator::foveate( void )
00234 {
00235   Image< PixRGB<byte> > fovImg( width, height, NO_INIT );
00236 
00237   // determine maximum distance to an edge
00238   int dMax = std::max( std::max( origin.i, width - origin.i ),
00239                        std::max( origin.j, height - origin.j ) );
00240 
00241   int k = -1;
00242   for( int i = 0; i < dMax; i++ )
00243     {
00244       for( int j = 0; j <= i; j++ )
00245         {
00246           // check if we are operating on origin pixel
00247           if( k == -1 )
00248             {
00249               fovImg.setVal( origin.i, origin.j,
00250                              original.getVal( origin.i, origin.j ) );
00251             }
00252           else
00253             {
00254               if( fovImg.coordsOk( origin.i + i, origin.j + j ) )
00255                 {
00256                   fovImg.setVal( origin.i + i, origin.j + j,
00257                                  gbms[k]->blurPixel( origin.i + i,
00258                                                      origin.j + j,
00259                                                      original ) );
00260                 }
00261               if( fovImg.coordsOk( origin.i + j, origin.j + i ) )
00262                 {
00263                   fovImg.setVal( origin.i + j, origin.j + i,
00264                                  gbms[k]->blurPixel( origin.i + j,
00265                                                      origin.j + i,
00266                                                      original ) );
00267                 }
00268               if( fovImg.coordsOk( origin.i - i, origin.j + j ) )
00269                 {
00270                   fovImg.setVal( origin.i - i, origin.j + j,
00271                                  gbms[k]->blurPixel( origin.i - i,
00272                                                      origin.j + j,
00273                                                      original ) );
00274                 }
00275               if( fovImg.coordsOk( origin.i - j, origin.j + i ) )
00276                 {
00277                   fovImg.setVal( origin.i - j, origin.j + i,
00278                                  gbms[k]->blurPixel( origin.i - j,
00279                                                      origin.j + i,
00280                                                      original ) );
00281                 }
00282               if( fovImg.coordsOk( origin.i - i, origin.j - j ) )
00283                 {
00284                   fovImg.setVal( origin.i - i, origin.j - j,
00285                                  gbms[k]->blurPixel( origin.i - i,
00286                                                      origin.j - j,
00287                                                      original ) );
00288                 }
00289               if( fovImg.coordsOk( origin.i - j, origin.j - i ) )
00290                 {
00291                   fovImg.setVal( origin.i - j, origin.j - i,
00292                                  gbms[k]->blurPixel( origin.i - j,
00293                                                      origin.j - i,
00294                                                      original ) );
00295                 }
00296               if( fovImg.coordsOk( origin.i + i, origin.j - j ) )
00297                 {
00298                   fovImg.setVal( origin.i + i, origin.j - j,
00299                                  gbms[k]->blurPixel( origin.i + i,
00300                                                      origin.j - j,
00301                                                      original ) );
00302                 }
00303               if( fovImg.coordsOk( origin.i + j, origin.j - i ) )
00304                 {
00305                   fovImg.setVal( origin.i + j, origin.j - i,
00306                                  gbms[k]->blurPixel( origin.i + j,
00307                                                      origin.j - i,
00308                                                      original ) );
00309                 }
00310             }
00311           k++;
00312         }
00313     }
00314 
00315   return fovImg;
00316 }
00317 
00318 // ######################################################################
00319 
00320 Image< PixRGB<byte> > BlurFoveator::
00321 foveate( const Image< PixRGB<byte> >& img, int filterSize, int x, int y )
00322 {
00323   // generate an image of same dimensions
00324   int width = img.getWidth();
00325   int height = img.getHeight();
00326   Image< PixRGB< byte > > fovImg( width, height, NO_INIT );
00327 
00328   // generate a Gaussian blur filter of the appropriate size
00329   GaussianBlurMatrix gbm( filterSize );
00330 
00331   // determine maximum distance to an edge
00332   int dMax = std::max( std::max( x, width - x ),
00333                        std::max( y, height - y ) );
00334 
00335   for( int i = 0; i < dMax; i++ )
00336     {
00337       for( int j = 0; j <= i; j++ )
00338         {
00339           // check if we are operating on the origin pixel
00340           if( !i && !j )
00341             {
00342               fovImg.setVal( x, y, img.getVal( x, y ) );
00343             }
00344           else
00345             {
00346               gbm.setBlurRadius( radius( i, j, width * height ) );
00347               if( fovImg.coordsOk( x + i, y + j ) )
00348                 {
00349                   fovImg.setVal( x + i, y + j,
00350                                  gbm.blurPixel( x + i, y + j, img ) );
00351                 }
00352               if( fovImg.coordsOk( x + j, y + i ) )
00353                 {
00354                   fovImg.setVal( x + j, y + i,
00355                                  gbm.blurPixel( x + j, y + i, img ) );
00356                 }
00357               if( fovImg.coordsOk( x - i, y + j ) )
00358                 {
00359                   fovImg.setVal( x - i, y + j,
00360                                  gbm.blurPixel( x - i, y + j, img ) );
00361                 }
00362               if( fovImg.coordsOk( x - j, y + i ) )
00363                 {
00364                   fovImg.setVal( x - j, y + i,
00365                                  gbm.blurPixel( x - j, y + i, img ) );
00366                 }
00367               if( fovImg.coordsOk( x - i, y - j ) )
00368                 {
00369                   fovImg.setVal( x - i, y - j,
00370                                  gbm.blurPixel( x - i, y - j, img ) );
00371                 }
00372               if( fovImg.coordsOk( x - j, y - i ) )
00373                 {
00374                   fovImg.setVal( x - j, y - i,
00375                                  gbm.blurPixel( x - j, y - i, img ) );
00376                 }
00377               if( fovImg.coordsOk( x + i, y - j ) )
00378                 {
00379                   fovImg.setVal( x + i, y - j,
00380                                  gbm.blurPixel( x + i, y - j, img ) );
00381                 }
00382               if( fovImg.coordsOk( x + j, y - i ) )
00383                 {
00384                   fovImg.setVal( x + j, y - i,
00385                                  gbm.blurPixel( x + j, y - i, img ) );
00386                 }
00387             }
00388         }
00389     }
00390 
00391   return fovImg;
00392 }
00393 
00394 // ######################################################################
00395 /* So things look consistent in everyone's emacs... */
00396 /* Local Variables: */
00397 /* indent-tabs-mode: nil */
00398 /* End: */
Generated on Sun May 8 08:04:47 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3