00001
00002
00003
00004
00005
00006 #include "Foveator/LPTFoveator.H"
00007
00008 #include "Image/Pixels.H"
00009
00010 #include <algorithm>
00011
00012
00013
00014
00015
00016 LPTFoveator::LPTFoveator( const Image< PixRGB<byte> >& img,
00017 int lptW, int lptH) : Foveator( img ),
00018 lptWidth( lptW ),
00019 lptHeight( lptH )
00020 {
00021 if( lptW <= 0 || lptH <= 0 )
00022 LERROR( "LPTFoveator map image must have positive dimensions." );
00023 setOrigin( width / 2, height / 2 );
00024 }
00025
00026
00027
00028 LPTFoveator::~LPTFoveator()
00029 {
00030 lptMap.clear();
00031 }
00032
00033
00034
00035
00036
00037 bool LPTFoveator::setOrigin( Point2D<int> pt )
00038 {
00039 if( Foveator::setOrigin( pt ) )
00040 {
00041
00042 int maxX = std::max( origin.i, width - origin.i );
00043 int maxY = std::max( origin.j, height - origin.j );
00044 logMultiplier = ( lptWidth - 1 ) / log( maxX*maxX + maxY*maxY + 1.0 );
00045
00046
00047 lptMap.clear();
00048 Point2D<int> mapPt;
00049 Point2D<int> originalPt;
00050 for( int x = 0; x < width; x++ )
00051 {
00052 for( int y = 0; y < height; y++ )
00053 {
00054 originalPt.i = x;
00055 originalPt.j = y;
00056 mapPt.i = (int)radius( x - origin.i, y - origin.j );
00057 mapPt.j = (int)angle( x - origin.i, y - origin.j );
00058 lptMap.insert( std::pair< Point2D<int>, Point2D<int> >
00059 ( mapPt, originalPt ) );
00060 }
00061 }
00062
00063
00064 return true;
00065 }
00066 else
00067 return false;
00068 }
00069
00070 bool LPTFoveator::setOrigin( int x, int y )
00071 {
00072 Point2D<int> pt( x, y );
00073 return setOrigin( pt );
00074 }
00075
00076
00077
00078 Image< PixRGB<byte> > LPTFoveator::foveate( void )
00079 {
00080 Image< PixRGB<byte> > fovImg = invLPT( getLPT() );
00081 return fovImg;
00082 }
00083
00084
00085
00086 Image< PixRGB<byte> > LPTFoveator::getLPT( void )
00087 {
00088 Image< PixRGB<byte> > lptImg( lptWidth, lptHeight, NO_INIT );
00089 for( int x = 0; x < lptWidth; x++ )
00090 {
00091 for( int y = 0; y < lptHeight; y++ )
00092 {
00093 Point2D<int> pt( x, y );
00094 Point2DMapPtr pmp = lptMap.lower_bound( pt );
00095 int count = 0;
00096 int rAcc = 0;
00097 int gAcc = 0;
00098 int bAcc = 0;
00099 while( pmp != lptMap.upper_bound( pt ) )
00100 {
00101
00102 rAcc += original.getVal( (*pmp).second ).red();
00103 gAcc += original.getVal( (*pmp).second ).green();
00104 bAcc += original.getVal( (*pmp).second ).blue();
00105 count++;
00106 pmp++;
00107 }
00108 if( count > 1 )
00109 {
00110 rAcc /= count;
00111 gAcc /= count;
00112 bAcc /= count;
00113 }
00114 PixRGB<byte> pix( rAcc, gAcc, bAcc );
00115 lptImg.setVal( pt, pix );
00116 }
00117 }
00118 return lptImg;
00119 }
00120
00121
00122
00123 Image< PixRGB<byte> > LPTFoveator::invLPT( const Image< PixRGB<byte> >& img )
00124 {
00125 Image< PixRGB<byte> > invImg( width, height, NO_INIT );
00126 for( Point2DMapPtr pmp = lptMap.begin(); pmp != lptMap.end(); pmp++ )
00127 {
00128 invImg.setVal( (*pmp).second, img.getVal( (*pmp).first ) );
00129 }
00130 return invImg;
00131 }
00132
00133
00134
00135 Image< PixRGB<byte> > LPTFoveator::foveate( const Image< PixRGB<byte> >& img,
00136 int lptW, int lptH, int x, int y,
00137 bool getMap )
00138 {
00139
00140 int maxX = std::max( x, img.getWidth() - x );
00141 int maxY = std::max( y, img.getHeight() - y );
00142 double logMult = ( lptW - 1 ) / log( maxX * maxX + maxY * maxY + 1.0 );
00143
00144
00145 int **R_acc;
00146 int **G_acc;
00147 int **B_acc;
00148 int **counter;
00149
00150 typedef int* intptr;
00151 R_acc = new intptr[lptW];
00152 G_acc = new intptr[lptW];
00153 B_acc = new intptr[lptW];
00154 counter = new intptr[lptW];
00155 for( int i = 0; i < lptW; i++ )
00156 {
00157 R_acc[i] = new int[lptH];
00158 G_acc[i] = new int[lptH];
00159 B_acc[i] = new int[lptH];
00160 counter[i] = new int[lptH];
00161 }
00162
00163
00164 for( int i = 0; i < lptW; i++ )
00165 {
00166 for( int j = 0; j < lptH; j++ )
00167 {
00168 R_acc[i][j] = 0;
00169 G_acc[i][j] = 0;
00170 B_acc[i][j] = 0;
00171 counter[i][j] = 0;
00172 }
00173 }
00174
00175
00176 for( int i = 0; i < img.getWidth(); i++ )
00177 {
00178 for( int j = 0; j < img.getHeight(); j++ )
00179 {
00180
00181 int xx = i - x;
00182 int yy = j - y;
00183
00184
00185 int r = int( logMult * log( xx * xx + yy * yy + 1.0 ) + 0.5 );
00186
00187 int theta;
00188 if( yy == 0 )
00189 {
00190 theta = (int)( ( xx >= 0 ) ?
00191 0.0 : 0.5 * ( lptH - 1 ) );
00192 }
00193 else if( xx == 0 )
00194 {
00195 theta = (int)( ( yy > 0 ) ?
00196 0.25 * ( lptH - 1 ) : 0.75 * ( lptH - 1 ) );
00197 }
00198 else
00199 {
00200 theta = (int)( ( M_PI + atan2( -1.0 * yy, -1.0 * xx ) ) /
00201 ( 2 * M_PI ) * ( lptH - 1 ) + 0.5 );
00202 }
00203
00204
00205 R_acc[r][theta] += ( img.getVal( i, j ) ).red();
00206 G_acc[r][theta] += ( img.getVal( i, j ) ).green();
00207 B_acc[r][theta] += ( img.getVal( i, j ) ).blue();
00208 counter[r][theta]++;
00209 }
00210 }
00211
00212
00213 Image< PixRGB<byte> > mapImage( lptW, lptH, NO_INIT );
00214 for( int r = 0; r < lptW; r++ )
00215 {
00216 for( int theta = 0; theta < lptH; theta++ )
00217 {
00218 if( counter[r][theta] > 1 )
00219 {
00220
00221 R_acc[r][theta] /= counter[r][theta];
00222 G_acc[r][theta] /= counter[r][theta];
00223 B_acc[r][theta] /= counter[r][theta];
00224 }
00225 PixRGB<byte> pix( R_acc[r][theta], G_acc[r][theta], B_acc[r][theta] );
00226 mapImage.setVal( r, theta, pix );
00227 }
00228 }
00229
00230
00231 delete [] R_acc;
00232 delete [] G_acc;
00233 delete [] B_acc;
00234 delete [] counter;
00235
00236 if( getMap )
00237 return mapImage;
00238 else
00239 return ( invLPT( mapImage, img.getWidth(), img.getHeight(), x, y ) );
00240 }
00241
00242
00243
00244 Image< PixRGB<byte> > LPTFoveator::invLPT( const Image< PixRGB<byte> >& img,
00245 int w, int h, int x, int y )
00246 {
00247
00248 int maxX = std::max( x, w - x );
00249 int maxY = std::max( y, h - y );
00250 double logMult = ( img.getWidth() - 1 ) /
00251 log( maxX * maxX + maxY * maxY + 1.0 );
00252
00253 Image< PixRGB<byte> > invImage( w, h, NO_INIT );
00254
00255
00256 for( int i = 0; i < w; i++ )
00257 {
00258 for( int j = 0; j < h; j++ )
00259 {
00260
00261 int xx = i - x;
00262 int yy = j - y;
00263
00264
00265 int r = int( logMult * log( xx * xx + yy * yy + 1.0 ) + 0.5 );
00266
00267 int theta;
00268 if( yy == 0 )
00269 {
00270 theta = (int)( ( xx >= 0 ) ?
00271 0.0 : 0.5 * ( img.getHeight() - 1 ) );
00272 }
00273 else if( xx == 0 )
00274 {
00275 theta = (int)( ( yy > 0 ) ?
00276 0.25 * ( img.getHeight() - 1 ) :
00277 0.75 * ( img.getHeight() - 1 ) );
00278 }
00279 else
00280 {
00281 theta = (int)( ( M_PI + atan2( -1.0 * yy, -1.0 * xx ) ) /
00282 ( 2 * M_PI ) * ( img.getHeight() - 1 ) + 0.5 );
00283 }
00284
00285 invImage.setVal( i, j, img.getVal( r, theta ) );
00286 }
00287 }
00288 return invImage;
00289 }
00290
00291
00292
00293
00294
00295