00001
00002
00003
00004
00005
00006 #include "Foveator/BlurFoveator.H"
00007
00008 #include "Image/Pixels.H"
00009
00010 #include <algorithm>
00011 #include <cmath>
00012
00013
00014
00015
00016 BlurFoveator::BlurFoveator( const Image< PixRGB< byte > >& img,
00017 int filterSize ) : Foveator( img )
00018 {
00019
00020 int dMax = std::max( width, height );
00021
00022
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
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
00055 BlurFoveator& BlurFoveator::operator=( const BlurFoveator& bf )
00056 {
00057 BlurFoveator *newbf = new BlurFoveator( bf );
00058 return *newbf;
00059 }
00060
00061
00062 BlurFoveator::~BlurFoveator()
00063 {
00064 delete [] gbms;
00065 }
00066
00067
00068
00069
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
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
00096 BlurFoveator::GaussianBlurMatrix& BlurFoveator::GaussianBlurMatrix::
00097 operator=( const GaussianBlurMatrix& gbm )
00098 {
00099 GaussianBlurMatrix *newgbm = new GaussianBlurMatrix( gbm );
00100 return *newgbm;
00101 }
00102
00103
00104 BlurFoveator::GaussianBlurMatrix::~GaussianBlurMatrix()
00105 {
00106 delete [] weights;
00107 }
00108
00109
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
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
00226
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
00233 Image< PixRGB<byte> > BlurFoveator::foveate( void )
00234 {
00235 Image< PixRGB<byte> > fovImg( width, height, NO_INIT );
00236
00237
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
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
00324 int width = img.getWidth();
00325 int height = img.getHeight();
00326 Image< PixRGB< byte > > fovImg( width, height, NO_INIT );
00327
00328
00329 GaussianBlurMatrix gbm( filterSize );
00330
00331
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
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
00396
00397
00398