00001 /*!@file Robots/Beobot2/Navigation/FOE_Navigation/SpatioTemporalEnergy.C 00002 detect motion in an image stream */ 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: Christian Siagian <siagian@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/Beobot2/Navigation/FOE_Navigation/SpatioTemporalEnergy.C $ 00035 // $Id: $ 00036 // 00037 00038 #include "Robots/Beobot2/Navigation/FOE_Navigation/SpatioTemporalEnergy.H" 00039 00040 // ###################################################################### 00041 // ##### SpatioTemporalEnergyPyrBuilder Functions: 00042 // ###################################################################### 00043 00044 //debuging 00045 //#define DEBUG_SpatioTemporalEnergy 00046 00047 #ifdef DEBUG_SpatioTemporalEnergy 00048 #include "GUI/DebugWin.H" 00049 #endif 00050 00051 #include "Raster/Raster.H" 00052 #include "Image/CutPaste.H" 00053 #include "Image/ShapeOps.H" 00054 #include "Image/Kernels.H" 00055 00056 // ###################################################################### 00057 template <class T> 00058 SpatioTemporalEnergyPyrBuilder<T>::SpatioTemporalEnergyPyrBuilder 00059 (const PyramidType typ, 00060 const float gabor_theta, 00061 const float speed, 00062 const uint depth, 00063 const int timeDomainSize) : 00064 PyrBuilder<T>(), 00065 itsPtype(typ), 00066 itsDepth(depth), 00067 itsGaborAngle(gabor_theta), 00068 itsSpeed(speed), 00069 itsTimeDomainSize(timeDomainSize) 00070 { 00071 ASSERT(itsTimeDomainSize == 3 || itsTimeDomainSize == 5); 00072 00073 setSpatioTemporalFilters(); 00074 itsSpatioTemporalEnergyOptimalShift.reset(depth); 00075 } 00076 00077 // ###################################################################### 00078 template <class T> 00079 void SpatioTemporalEnergyPyrBuilder<T>::setSpatioTemporalFilters() 00080 { 00081 float angle = 90.0; // NOTE: MAKE THIS 0.0 for the Aperture Problem solution 00082 float filter_period = 2.5; //3.75; 00083 float elongation = 1.0; 00084 uint size = 5; 00085 00086 double major_stddev = filter_period / 3.0; 00087 double minor_stddev = major_stddev * elongation; 00088 00089 itsSpatTemp0filter = gaborFilter3(major_stddev, minor_stddev, 00090 filter_period, 0.0f, angle, size); 00091 itsSpatTemp90filter = gaborFilter3(major_stddev, minor_stddev, 00092 filter_period, 90.0f, angle, size); 00093 00094 LDEBUG("angle = %.2f, period = %.2f pix, size = %dx%d pix", 00095 angle, filter_period, 00096 itsSpatTemp0filter.getWidth(), itsSpatTemp0filter.getHeight()); 00097 00098 00099 // if(itsGaborAngle == 0.0) 00100 // { 00101 // for(uint y = 0; y < size; y++) 00102 // { 00103 // for(uint x = 0; x < size; x++) 00104 // LINFO("%7.3f ", itsSpatTemp0filter.getVal(x,y));//*-128 + 127); 00105 // LINFO("\n"); 00106 // } 00107 // LINFO("\n"); 00108 00109 // for(uint y = 0; y < size; y++) 00110 // { 00111 // for(uint x = 0; x < size; x++) 00112 // LINFO("%7.3f ", itsSpatTemp90filter.getVal(x,y));//*128 + 127); 00113 // LINFO("\n"); 00114 // } 00115 // LINFO("\n"); 00116 // if(itsWin.is_invalid()) 00117 // { 00118 // std::string ntext(sformat("t=%5.2f", itsGaborAngle)); 00119 // itsWin.reset(new XWinManaged(Dims(300,300), 0,0, ntext.c_str())); 00120 // } 00121 // else itsWin->setDims(Dims(300, 300)); 00122 00123 // float mn1,mx1,mn2,mx2; 00124 // getMinMax(itsSpatTemp0filter, mn1, mx1); 00125 // LDEBUG("g0 min: %f, max: %f", mn1, mx1); 00126 // getMinMax(itsSpatTemp90filter, mn2, mx2); 00127 // LDEBUG("g90 min: %f, max: %f", mn2, mx2); 00128 00129 // Image<float> disp0 (300,300,ZEROS); 00130 // Image<float> disp90(300,300,ZEROS); 00131 00132 // disp0 = (disp0 +1.0)*mx1; 00133 // disp90 = (disp90+1.0)*mx2; 00134 // for(int i = 0; i < 5; i++) 00135 // { 00136 // std::string ntexth(sformat("%d", i-2)); 00137 // writeText(disp0, Point2D<int>(70+40*i-10,25), ntexth.c_str(),mn1,mx1); 00138 // writeText(disp90, Point2D<int>(70+40*i-10,25), ntexth.c_str(),mn2,mx2); 00139 // } 00140 // std::string ntexthl(sformat("dx")); 00141 // writeText(disp0, Point2D<int>(250,25), ntexthl.c_str(),mn1,mx1); 00142 // writeText(disp90, Point2D<int>(250,25), ntexthl.c_str(),mn2,mx2); 00143 00144 // for(int i = 0; i < 5; i++) 00145 // { 00146 // std::string ntextv(sformat("%d", i)); 00147 // writeText(disp0, Point2D<int>(25, 70+40*i-10), ntextv.c_str(),mn1,mx1); 00148 // writeText(disp90, Point2D<int>(25, 70+40*i-10), ntextv.c_str(),mn2,mx2); 00149 // } 00150 // std::string ntextvl(sformat("dt")); 00151 // writeText(disp0, Point2D<int>(25,250), ntextvl.c_str(),mn1,mx1); 00152 // writeText(disp90, Point2D<int>(25,250), ntextvl.c_str(),mn2,mx2); 00153 00154 // inplacePaste(disp0, zoomXY(itsSpatTemp0filter , 40), Point2D<int>(50,50)); 00155 // inplacePaste(disp90, zoomXY(itsSpatTemp90filter , 40), Point2D<int>(50,50)); 00156 // inplaceNormalize(disp0, 0.0F, 255.0F); 00157 // inplaceNormalize(disp90, 0.0F, 255.0F); 00158 // Raster::WriteRGB(disp0, "disp0.ppm"); 00159 // Raster::WriteRGB(disp90,"disp90.ppm"); 00160 // //itsWin->drawImage(disp0, 0,0); Raster::waitForKey(); 00161 // //itsWin->drawImage(disp90,0,0); Raster::waitForKey(); 00162 00163 00164 // PixRGB<byte> bl(0, 0, 0); 00165 // PixRGB<byte> wh(255,255,255); 00166 // uint wST = 100 + 19*40; 00167 // uint hST = 100 + 11*40; 00168 // Image<PixRGB<byte> > dispST(wST, hST,ZEROS); 00169 // dispST = (dispST+ wh); 00170 // std::string ntexth(sformat("dt")); 00171 00172 // // 1px/fr 00173 // uint ri = 50 + 40 * 7; uint rj = 50 + 40*9; 00174 // drawFilledRect 00175 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 0)); 00176 // ri = 50 + 40 * 8; rj = 50 + 40*8; 00177 // drawFilledRect 00178 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 0)); 00179 // ri = 50 + 40 * 10; rj = 50 + 40*6; 00180 // drawFilledRect 00181 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 0)); 00182 // ri = 50 + 40 * 11; rj = 50 + 40*5; 00183 // drawFilledRect 00184 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 0)); 00185 00186 // //2 px/fr 00187 // ri = 50 + 40 * 7; rj = 50 + 40*8; 00188 // drawFilledRect 00189 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 255, 0)); 00190 // ri = 50 + 40 * 5; rj = 50 + 40*9; 00191 // drawFilledRect 00192 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 255, 0)); 00193 // ri = 50 + 40 * 11; rj = 50 + 40*6; 00194 // drawFilledRect 00195 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 255, 0)); 00196 // ri = 50 + 40 * 13; rj = 50 + 40*5; 00197 // drawFilledRect 00198 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 255, 0)); 00199 00200 // // 4px/fr 00201 // ri = 50 + 40 * 5; rj = 50 + 40*8; 00202 // drawFilledRect 00203 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 0, 255)); 00204 // ri = 50 + 40 * 1; rj = 50 + 40*9; 00205 // drawFilledRect 00206 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 0, 255)); 00207 // ri = 50 + 40 * 13; rj = 50 + 40*6; 00208 // drawFilledRect 00209 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 0, 255)); 00210 // ri = 50 + 40 * 17; rj = 50 + 40*5; 00211 // drawFilledRect 00212 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(0, 0, 255)); 00213 00214 // // 1/2 px/fr 00215 // ri = 50 + 40 * 11; rj = 50 + 40*1; 00216 // drawFilledRect 00217 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00218 // ri = 50 + 40 * 10; rj = 50 + 40*3; 00219 // drawFilledRect 00220 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00221 // ri = 50 + 40 * 9; rj = 50 + 40*5; 00222 // drawFilledRect 00223 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00224 // ri = 50 + 40 * 8; rj = 50 + 40*7; 00225 // drawFilledRect 00226 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00227 // ri = 50 + 40 * 7; rj = 50 + 40*9; 00228 // drawFilledRect 00229 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00230 00231 // // 1/4 px/fr 00232 // // ri = 50 + 40 * 11; rj = 50 + 40*1; 00233 // // drawFilledRect 00234 // // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00235 // // ri = 50 + 40 * 10; rj = 50 + 40*3; 00236 // // drawFilledRect 00237 // // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 255, 0)); 00238 // ri = 50 + 40 * 9; rj = 50 + 40*1; 00239 // drawFilledRect 00240 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 255)); 00241 // ri = 50 + 40 * 8; rj = 50 + 40*5; 00242 // drawFilledRect 00243 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 255)); 00244 // ri = 50 + 40 * 7; rj = 50 + 40*9; 00245 // drawFilledRect 00246 // (dispST, Rectangle::tlbrI(rj, ri, rj+40-1, ri+40-1), PixRGB<byte>(255, 0, 255)); 00247 00248 00249 00250 00251 // uint ri1 = 50 + 40 * 7 +20; uint rj1 = 50 + 40*9+20; 00252 // uint ri2 = 50 + 40 * 11+20; uint rj2 = 50 + 40*5+20; 00253 // drawLine(dispST, Point2D<int>(ri1, rj1), Point2D<int>(ri2, rj2), bl); 00254 // ri = 50 + 40 * 9; rj = 50 + 40*7; 00255 // drawLine(dispST, Point2D<int>(ri, rj), Point2D<int>(ri+40, rj+40), bl); 00256 // drawLine(dispST, Point2D<int>(ri, rj+40), Point2D<int>(ri+40, rj), bl); 00257 // ri1 = 50 + 40 * 5 +20; rj1 = 50 + 40*9+20; 00258 // ri2 = 50 + 40 * 13+20; rj2 = 50 + 40*5+20; 00259 // drawLine(dispST, Point2D<int>(ri1, rj1), Point2D<int>(ri2, rj2), bl); 00260 // ri1 = 50 + 40 * 1 +20; rj1 = 50 + 40*9+20; 00261 // ri2 = 50 + 40 * 17+20; rj2 = 50 + 40*5+20; 00262 // drawLine(dispST, Point2D<int>(ri1, rj1), Point2D<int>(ri2, rj2), bl); 00263 // ri1 = 50 + 40 * 11 +20; rj1 = 50 + 40*1 +20; 00264 // ri2 = 50 + 40 * 7 +20; rj2 = 50 + 40*9 +20; 00265 // drawLine(dispST, Point2D<int>(ri1, rj1), Point2D<int>(ri2, rj2), bl); 00266 // ri1 = 50 + 40 * 11 +20; rj1 = 50 + 40*-7 +20; 00267 // ri2 = 50 + 40 * 7 +20; rj2 = 50 + 40*9 +20; 00268 // drawLine(dispST, Point2D<int>(ri1, rj1), Point2D<int>(ri2, rj2), bl); 00269 00270 00271 00272 // writeText(dispST, Point2D<int>(25, 25), ntexth.c_str(), bl, wh); 00273 // for(int i = 0; i < 20; i++) 00274 // { 00275 // drawLine(dispST, 00276 // Point2D<int>(50+i*40, 50), 00277 // Point2D<int>(50+i*40, 50+10*40), bl); 00278 // std::string ntext(sformat("%2d", i-8)); 00279 // if(i != 19) 00280 // writeText(dispST, Point2D<int>(70+40*i-10, 50+10*40+5), ntext.c_str(), bl, wh); 00281 // } 00282 00283 // std::string ntextv(sformat("dx")); 00284 // writeText(dispST, Point2D<int>(70+40*19-10, 50+10*40+5), ntextv.c_str(), bl, wh); 00285 // for(int j = 0; j < 11; j++) 00286 // { 00287 // drawLine(dispST, 00288 // Point2D<int>(50, 50+j*40), 00289 // Point2D<int>(50+19*40,50+j*40), bl); 00290 00291 // std::string ntext(sformat("%2d", j-9)); 00292 // if(j != 10) 00293 // writeText(dispST, Point2D<int>(25, 70+40*j-10), ntext.c_str(), bl, wh); 00294 // } 00295 00296 // //inplaceNormalize(dispST, 0.0F, 255.0F); 00297 // Raster::WriteRGB(dispST, "ST.ppm"); 00298 // itsWin->setDims(Dims(wST, hST)); 00299 // //itsWin->drawImage(dispST,0,0); Raster::waitForKey(); 00300 00301 00302 // uint wRF = 100 + 28*20; 00303 // uint hRF = 100 + 28*20; 00304 // Image<PixRGB<byte> > dispRF (wRF,hRF,ZEROS); 00305 // dispRF = (dispRF + PixRGB<byte>(255,255,255)); 00306 00307 // ri = 50 + 20 * 2*4; rj = 50 + 20*2*4; 00308 // drawFilledRect 00309 // (dispRF, Rectangle::tlbrI(rj, ri, rj+240-1, ri+240-1), PixRGB<byte>(255, 255, 0)); 00310 // ri = 50 + 20 * 3*4; rj = 50 + 20*3*4; 00311 // drawFilledRect 00312 // (dispRF, Rectangle::tlbrI(rj, ri, rj+80-1, ri+80-1), PixRGB<byte>(255, 0, 0)); 00313 00314 00315 // for(int i = 0; i < 29; i++) 00316 // { 00317 // drawLine(dispRF, 00318 // Point2D<int>(50+i*20, 50), 00319 // Point2D<int>(50+i*20, 50+28*20), bl, 1); 00320 // } 00321 00322 // for(int j = 0; j < 29; j++) 00323 // { 00324 // drawLine(dispRF, 00325 // Point2D<int>(50, 50+j*20), 00326 // Point2D<int>(50+28*20,50+j*20), bl, 1); 00327 // } 00328 00329 // for(int i = 0; i < 29; i+=2) 00330 // { 00331 // drawLine(dispRF, 00332 // Point2D<int>(50+i*20, 50), 00333 // Point2D<int>(50+i*20, 50+28*20), bl, 2); 00334 // } 00335 00336 // for(int j = 0; j < 29; j+=2) 00337 // { 00338 // drawLine(dispRF, 00339 // Point2D<int>(50, 50+j*20), 00340 // Point2D<int>(50+28*20,50+j*20), bl, 2); 00341 // } 00342 00343 // for(int i = 0; i < 29; i+=4) 00344 // { 00345 // drawLine(dispRF, 00346 // Point2D<int>(50+i*20, 50), 00347 // Point2D<int>(50+i*20, 50+28*20), bl, 3); 00348 // } 00349 00350 // for(int j = 0; j < 29; j+=4) 00351 // { 00352 // drawLine(dispRF, 00353 // Point2D<int>(50, 50+j*20), 00354 // Point2D<int>(50+28*20,50+j*20), bl, 3); 00355 // } 00356 00357 // Raster::WriteRGB(dispRF,"RF.ppm"); 00358 // itsWin->setDims(Dims(wRF, hRF)); 00359 // itsWin->drawImage(dispRF,0,0); Raster::waitForKey(); 00360 // } 00361 00362 // old filters with size increase detection 00363 itsSpatTemp2filter = Image<float>(5,5,NO_INIT); 00364 itsSpatTemp2filter.setVal(0,0, 0.01); 00365 itsSpatTemp2filter.setVal(0,1, 0.05); 00366 itsSpatTemp2filter.setVal(0,2, 0.40); 00367 itsSpatTemp2filter.setVal(0,3, 0.05); 00368 itsSpatTemp2filter.setVal(0,4, 0.01); 00369 00370 itsSpatTemp2filter.setVal(1,0, 0.01); 00371 itsSpatTemp2filter.setVal(1,1, 0.10); 00372 itsSpatTemp2filter.setVal(1,2, 0.40); 00373 itsSpatTemp2filter.setVal(1,3, 0.10); 00374 itsSpatTemp2filter.setVal(1,4, 0.01); 00375 00376 itsSpatTemp2filter.setVal(2,0, 0.03); 00377 itsSpatTemp2filter.setVal(2,1, 0.20); 00378 itsSpatTemp2filter.setVal(2,2, 0.40); 00379 itsSpatTemp2filter.setVal(2,3, 0.20); 00380 itsSpatTemp2filter.setVal(2,4, 0.03); 00381 00382 itsSpatTemp2filter.setVal(3,0, 0.05); 00383 itsSpatTemp2filter.setVal(3,1, 0.25); 00384 itsSpatTemp2filter.setVal(3,2, 0.40); 00385 itsSpatTemp2filter.setVal(3,3, 0.25); 00386 itsSpatTemp2filter.setVal(3,4, 0.05); 00387 00388 itsSpatTemp2filter.setVal(4,0, 0.10); 00389 itsSpatTemp2filter.setVal(4,1, 0.30); 00390 itsSpatTemp2filter.setVal(4,2, 0.40); 00391 itsSpatTemp2filter.setVal(4,3, 0.30); 00392 itsSpatTemp2filter.setVal(4,4, 0.10); 00393 } 00394 00395 // ###################################################################### 00396 template <class T> 00397 ImageSet<float> SpatioTemporalEnergyPyrBuilder<T>::getOptimalShift() 00398 { 00399 return itsSpatioTemporalEnergyOptimalShift; 00400 } 00401 // ###################################################################### 00402 template <class T> 00403 ImageSet<float> SpatioTemporalEnergyPyrBuilder<T>::getSpatioTemporalEnergy() 00404 { 00405 return itsSpatioTemporalEnergy; 00406 } 00407 00408 // ###################################################################### 00409 template <class T> 00410 ImageSet<T> SpatioTemporalEnergyPyrBuilder<T>::build 00411 (const Image<T>& image, 00412 const int firstlevel, 00413 const int depth, 00414 PyramidCache<T>* cache) 00415 { 00416 // WAS: Gaussian5 00417 // itsMotionPyrs.reset 00418 // (new SpatioTemporalEnergyPyrBuilder<byte>(Oriented5, 0.0f, 10.0f, itsPyrLevel)); 00419 00420 // create a pyramid with the input image 00421 //ImageSet<T> pyr = buildPyrGeneric(image, 0, itsDepth, Gaussian5, 00422 // itsGaborAngle); 00423 00424 //ImageSet<float> pyr = 00425 // buildPyrGabor(image, 0, itsDepth, itsGaborAngle+90.0, 3.75, 1.0, 7); 00426 00427 ImageSet<float> pyr = 00428 buildPyrGabor(image, 0, itsDepth, itsGaborAngle+90.0, 2.50, 1.0, 5); 00429 00430 //DEBUG 00431 //print(pyr, si, ei, sj, ej, false); 00432 //display(pyr); 00433 00434 imgPyrQ.push_back(pyr); //build the time domain 00435 00436 if (imgPyrQ.size() > itsTimeDomainSize) //limit the image time queue 00437 imgPyrQ.pop_front(); 00438 00439 // if we have too few imgs in the Q, just return an empty image: 00440 if (imgPyrQ.size() < itsTimeDomainSize) 00441 { 00442 LDEBUG("not enough images yet: %"ZU, imgPyrQ.size()); 00443 return ImageSet<float>(); 00444 } 00445 00446 const int pdepth = imgPyrQ[0].size(); 00447 ImageSet<float> result(pdepth); 00448 00449 // compute the motion detection at each location 00450 for (int scale = 0; scale < pdepth; scale++) 00451 result[scale] = buildMotion(scale); 00452 00453 itsSpatioTemporalEnergy = result; 00454 00455 return result; 00456 } 00457 00458 // // ###################################################################### 00459 // // get the motion by detecting edge orientations in the space and time 00460 // template <class T> 00461 // Image<float> SpatioTemporalEnergyPyrBuilder<T>::buildMotion(int scale) 00462 // { 00463 // // if we have too few imgs in the Q, just return an empty image: 00464 // uint currQueueSize = imgPyrQ.size(); 00465 00466 // // go through each spatial shift 00467 // bool motionComputed = false; 00468 // std::vector<Image<float> > results; 00469 // std::vector<float> shifts; 00470 00471 // //LINFO("num of spatial shifts: %d", itsSpatialShift); 00472 00473 // for(uint i = 0; i < itsSpatialShift; i++) 00474 // { 00475 // uint neededSize = itsTimeDomainSize; 00476 // if (neededSize > currQueueSize) 00477 // { 00478 // LINFO("Not enough images: %d < %d for spatial shift %d", 00479 // currQueueSize, neededSize, i); 00480 // } 00481 // else 00482 // { 00483 // uint sshift = uint(pow(2.0, i)); 00484 // results.push_back(buildMotion(scale, sshift, 1)); 00485 // shifts.push_back(float(sshift*pow(2.0, scale))); 00486 // motionComputed = true; 00487 // } 00488 // } 00489 00490 // // FIX: NOTES maybe nested loop later on these two 00491 // // go through each temporal shift 00492 // for(uint j = 0; j < itsTemporalShift; j++) 00493 // { 00494 // //uint neededSize = 9; // speed: 1/2 pix/fr 00495 // //if(j == 1) neededSize = 13; // speed: 1/3 pix/fr 00496 // //else if(j == 2) neededSize = 17; // speed: 1/4 pix/fr 00497 // uint neededSize = 1 + 4*(j+2); 00498 00499 // if (neededSize > currQueueSize) 00500 // { 00501 // LINFO("Not enough images: %d < %d for temporal shift %d", 00502 // currQueueSize, neededSize, j); 00503 // } 00504 // else 00505 // { 00506 // float sshift = 1.0/(j+2.0); 00507 // results.push_back(buildMotion(scale, 1, j+1)); 00508 // shifts.push_back(sshift*pow(2.0, scale)); 00509 // motionComputed = true; 00510 // } 00511 // } 00512 00513 // // find max among all the spatial and temporal shifts 00514 // // --> basically max among all the shifting values 00515 // if(motionComputed) 00516 // { 00517 // uint width = results[0].getWidth(); 00518 // uint height = results[0].getHeight(); 00519 // Image<float> result(width, height, ZEROS); 00520 00521 // itsSpatioTemporalEnergyOptimalShift[scale] = 00522 // Image<float>(width, height, ZEROS); 00523 00524 // typename Image<float>::iterator 00525 // resultT = result.beginw(); 00526 00527 // typename Image<float>::iterator 00528 // shiftT = itsSpatioTemporalEnergyOptimalShift[scale].beginw(); 00529 00530 // typename Image<float>::iterator resT[results.size()]; 00531 // for (unsigned int i=0; i < results.size(); i++) 00532 // resT[i] = results[i].beginw(); 00533 00534 // for(uint i = 0; i < width; i++) 00535 // { 00536 // for(uint j = 0; j < height; j++) 00537 // { 00538 // float max = 0.0; float optShift = 0.0; 00539 // uint size = results.size(); 00540 00541 // for(uint r = 0; r < size; r++) 00542 // { 00543 // float val = *resT[r]++; 00544 // if(max < val) 00545 // { 00546 // max = val; 00547 // optShift = shifts[r]; 00548 // } 00549 // } 00550 // *resultT++ = max; 00551 // *shiftT++ = optShift; 00552 // } 00553 // } 00554 00555 // // if((scale == 1)) 00556 // // { 00557 // // uint div = uint(pow(2.0,scale)); 00558 // // LINFO("COMB: Ang: %f sc: %d", itsGaborAngle, scale); 00559 // // print(result, 166/div, 196/div, 55/div, 75/div, false); 00560 // // } 00561 00562 00563 // return result; 00564 // } 00565 // else 00566 // return Image<float>(); 00567 // } 00568 00569 // ###################################################################### 00570 template <class T> 00571 Image<float> SpatioTemporalEnergyPyrBuilder<T>::buildMotion(int scale) 00572 { 00573 int width = imgPyrQ[0][scale].getWidth(); 00574 int height = imgPyrQ[0][scale].getHeight(); 00575 00576 // build the time domain pointers 00577 /*typename Image<float>::iterator imgT[itsTimeDomainSize]; 00578 for (unsigned int i=0; i < itsTimeDomainSize; i++) 00579 { 00580 imgT[i] = imgPyrQ[i][scale].beginw(); 00581 }*/ 00582 00583 // to make the operation look nice and readable 00584 // the parenthesis around the x are needed 00585 // otherwise a bug happens when using PixH(0,i-1) 00586 #define Pix(t,x,y) (*(imgT[t] + (y*width)+(x))) 00587 00588 float cosAng = cos(itsGaborAngle * M_PI/180.0); 00589 float sinAng = sin(itsGaborAngle * M_PI/180.0); 00590 00591 // LINFO("Bef %f %f ss:%d ts:%d scale: %d ang: %f", 00592 // cosAng,sinAng, spatialShift, temporalShift, scale, itsGaborAngle); 00593 00594 // if(cosAng > .1 && cosAng < 0.9) cosAng = 1.0F; 00595 // if(sinAng > .1 && sinAng < 0.9) sinAng = 1.0F; 00596 // if(cosAng < -.1 && cosAng > -0.9) cosAng = -1.0F; 00597 // if(sinAng < -.1 && sinAng > -0.9) sinAng = -1.0F; 00598 00599 // NOTE: FIX THIS UNFORTUNATE SITUATION 00600 // find the limit on the XY plane of the spatiotemporal space 00601 uint dx = 2*itsSpeed + 2; // 2; //uint(spatialShift * cosAng * (itsTimeDomainSize/2)); 00602 uint dy = 2*itsSpeed + 2; // 2; //uint(spatialShift * sinAng * (itsTimeDomainSize/2)); 00603 // LINFO("%f c,s(%10.3f, %10.3f) dx: %7d, dy: %7d", 00604 // itsGaborAngle, cosAng, sinAng, dx, dy); 00605 00606 Image<float> motion(width, height, ZEROS); // motion place holder 00607 00608 // go through all the active area 00609 for (uint j = dy; j < (height-dy); j++) 00610 { 00611 typename Image<float>::iterator mot = 00612 motion.beginw() + (j*width) + dx; 00613 00614 for (uint i = dx; i < (width-dx); i++) 00615 { 00616 //LINFO("[%d %d]",i ,j, ); 00617 00618 // calculate the firing for displacement & size increase 00619 // based on timedomainsize 00620 switch(itsTimeDomainSize) 00621 { 00622 // calculate values from 3 most recent frames 00623 case 3: // do something simpler later 00624 break; 00625 00626 // 5 values from 5 most recent frames 00627 case 5: 00628 { 00629 uint speed = 1; 00630 uint tshift = 1; 00631 if(itsSpeed >= 1.0) speed = uint(itsSpeed); 00632 else 00633 { 00634 // FIXXX: add cases for 1/2, 1/3, 1/4 00635 } 00636 00637 float val = 00638 getSpatioTemporalVal 00639 (cosAng, sinAng, scale, i, j, speed, tshift); 00640 //motion.setVal(i,j,val); 00641 *mot = val; mot++; // saves 3ms compared to setVal 00642 } 00643 break; 00644 00645 default: LFATAL("invalid itsTimeDomainSize: %d", itsTimeDomainSize); 00646 break; 00647 } 00648 } 00649 } 00650 00651 // DEBUG 00652 // uint div = uint(pow(2.0, scale)); 00653 // if((itsGaborAngle == 0.0 || itsGaborAngle == 180.0) && 00654 // (scale == 0) && (spatialShift == 1) && (temporalShift == 1)) 00655 // { 00656 // if((scale == 0))// && (spatialShift == 1) && (temporalShift == 1)) 00657 // { 00658 // LINFO("Ang: %f sc: %d, ss: %d ts: %d", 00659 // itsGaborAngle, scale, spatialShift, temporalShift); 00660 // print(motion, 158, 169, 55, 75, false); 00661 // } 00662 //print(motion, 165/div, 175/div, 45/div, 75/div, true); 00663 //print(motion, 175/div, 185/div, 45/div, 75/div, true); 00664 //print(motion, 185/div, 195/div, 45/div, 75/div, true); 00665 00666 return motion; 00667 } 00668 00669 // ###################################################################### 00670 template <class T> 00671 float SpatioTemporalEnergyPyrBuilder<T>::getSpatioTemporalVal 00672 (float cosAng, float sinAng, uint scale, uint i, uint j, 00673 uint spatialShift, uint temporalShift) 00674 { 00675 00676 typename Image<float>::iterator f0 = 00677 itsSpatTemp0filter.beginw(); 00678 typename Image<float>::iterator f90 = 00679 itsSpatTemp90filter.beginw(); 00680 00681 // typename Image<float>::iterator f2 = 00682 // itsSpatTemp2filter.beginw(); 00683 00684 // to make the operation look nice and readable 00685 // the parenthesis around the x are needed 00686 // otherwise a bug happens when using PixH(0,i-1) 00687 #define v0(x,y) (*(f0 + (y*itsTimeDomainSize)+(x))) 00688 #define v90(x,y) (*(f90 + (y*itsTimeDomainSize)+(x))) 00689 //#define v2(x,y) (*(f2 + (y*itsTimeDomainSize)+(x))) 00690 00691 float tsum0 = 0.0; float tsum90 = 0.0; 00692 std::vector<float> sum0(5); 00693 std::vector<float> sum90(5); 00694 00695 std::vector<float> spatShift(5); 00696 spatShift[0] = -2.0 * spatialShift; 00697 spatShift[1] = -1.0 * spatialShift; 00698 spatShift[2] = 0.0; 00699 spatShift[3] = 1.0 * spatialShift; 00700 spatShift[4] = 2.0 * spatialShift; 00701 00702 // check temporal shifting 00703 uint tempLimit = 1 + temporalShift*(itsTimeDomainSize-1); 00704 uint ft = 0; 00705 for(uint t = 0; t < tempLimit; t+= temporalShift) 00706 { 00707 sum0[t] = getFilterResponseVal 00708 (spatShift[ft], cosAng, sinAng, t, scale, 00709 i, j, v0(ft,0), v0(ft,1), v0(ft,2), v0(ft,3), v0(ft,4)); 00710 00711 sum90[t] = getFilterResponseVal 00712 (spatShift[ft], cosAng, sinAng, t, scale, 00713 i, j, v90(ft,0), v90(ft,1), v90(ft,2), v90(ft,3), v90(ft,4)); 00714 00715 tsum0 += sum0[t]; 00716 tsum90 += sum90[t]; 00717 // sum[t] = getSpatTempVal 00718 // (shift[t], cosAng, sinAng, t, scale, 00719 // i, j, v2(t,0), v2(t,1), v2(t,2), v2(t,3), v2(t,4)); 00720 00721 // LINFO("s: %f (%f %f) t:%d s:%d [%d %d] %f %f %f %f %f", 00722 // shift[t], cosAng, sinAng, t, scale, 00723 // i, j, v2(t,0), v2(t,1), v2(t,2), v2(t,3), v2(t,4)); 00724 00725 //sum2 += sum[t]; 00726 00727 // LINFO("%10.3f %10.3f %10.3f %10.3f %10.3f ", 00728 // v0(ft,0), v0(ft,1), v0(ft,2), v0(ft,3), v0(ft,4)); 00729 00730 ft++; 00731 } 00732 00733 float sum = tsum0*tsum0 + tsum90*tsum90; 00734 00735 // // grab values from frame t - 4 00736 // float v0 = getSpatTempVal 00737 // (-2.0, cosAng, sinAng, 0, scale, 00738 // i, j, 0.01, 0.05, 0.40, 0.05, 0.01); 00739 00740 // // grab values from frame t - 3 00741 // float v1 = getSpatTempVal 00742 // (-1.0, cosAng, sinAng, 1, scale, 00743 // i, j, 0.01, 0.10, 0.40, 0.10, 0.01); 00744 00745 // // grab values from frame t - 2 00746 // float v2 = getSpatTempVal 00747 // (0.0, cosAng, sinAng, 2, scale, 00748 // i, j, 0.03, 0.20, 0.40, 0.20, 0.03); 00749 00750 // // grab values from frame t - 1 00751 // float v3 = getSpatTempVal 00752 // (1.0, cosAng, sinAng, 3, scale, 00753 // i, j, 0.05, 0.25, 0.40, 0.25, 0.05); 00754 00755 // // grab values from frame t 00756 // float v4 = getSpatTempVal 00757 // (2.0, cosAng, sinAng, 4, scale, 00758 // i, j, 0.10, 0.30, 0.40, 0.30, 0.10); 00759 00760 // if(i > 150 && i < 170 && j ==60) 00761 // { 00762 // LINFO(" 0(%d %d) %10.3f,%10.3f,%10.3f,%10.3f,%10.3f = %10.3f", 00763 // i, j, sum0[0], sum0[1], sum0[2], sum0[3], sum0[4], tsum0); 00764 // LINFO("90(%d %d) %10.3f,%10.3f,%10.3f,%10.3f,%10.3f = %10.3f", 00765 // i, j, sum90[0], sum90[1], sum90[2], sum90[3], sum90[4], tsum90); 00766 00767 // LINFO("%f^2 + %f^2 = %f + %f = %f ", 00768 // tsum0, tsum90, tsum0*tsum0, tsum90*tsum90, sum); 00769 // //LINFO("(%d %d) %10.3f,%10.3f,%10.3f,%10.3f,%10.3f = %10.3f", 00770 // // i, j, v0, v1, v2, v3, v4, v0+v1+v2+v3+v4); 00771 // } 00772 00773 // return v0 + v1 + v2 + v3 + v4; 00774 return sum; 00775 } 00776 00777 // ###################################################################### 00778 template <class T> 00779 float SpatioTemporalEnergyPyrBuilder<T>::getFilterResponseVal 00780 (float dshift, float cosAng, float sinAng, uint time, uint scale, 00781 uint i, uint j, 00782 float wm2, float wm1, float w, float wp1, float wp2) 00783 { 00784 00785 uint width = imgPyrQ[time][scale].getWidth(); 00786 00787 // to make the operation look nice and readable 00788 // the parenthesis around the x are needed 00789 // otherwise a bug happens when using Px(0,i-1) 00790 //#define Px(t,x,y) (*(imgT[t] + ((y)*width)+(x)) 00791 #define Px(x,y) (*(imgT + ((y)*width)+(x))) 00792 00793 // build the time domain pointers 00794 // typename Image<float>::iterator imgT[itsTimeDomainSize]; 00795 // for (unsigned int ind = 0; ind < itsTimeDomainSize; ind++) 00796 // { 00797 // imgT[ind] = imgPyrQ[ind][scale].beginw(); 00798 // } 00799 00800 typename Image<float>::iterator imgT = imgPyrQ[time][scale].beginw(); 00801 00802 float ii = i + (dshift * cosAng); 00803 float jj = j + (dshift * sinAng); 00804 00805 float pi = cosAng; // old: sinAng 00806 float pj = sinAng; // old: cosAng 00807 00808 // float iim2 = ii - 2*pi; 00809 // float jjm2 = jj - 2*pj; 00810 00811 // float iim1 = ii - pi; 00812 // float jjm1 = jj - pj; 00813 00814 // float iip1 = ii + pi; 00815 // float jjp1 = jj + pj; 00816 00817 // float iip2 = ii + 2*pi; 00818 // float jjp2 = jj + 2*pj; 00819 00820 // float v1 = wm2 * Px(time, int(iim2),int(jjm2)); 00821 // float v2 = wm1 * Px(time, int(iim1),int(jjm1)); 00822 // float v3 = w * Px(time, int(ii), int(jj) ); 00823 // float v4 = wp1 * Px(time, int(iip1),int(jjp1)); 00824 // float v5 = wp2 * Px(time, int(iip2),int(jjp2)); 00825 00826 float v1 = wm2 * Px(int(ii - 2*pi),int(jj - 2*pj)); 00827 float v2 = wm1 * Px(int(ii - pi), int(jj - pj)); 00828 float v3 = w * Px(int(ii), int(jj) ); 00829 float v4 = wp1 * Px(int(ii + pi), int(jj + pj)); 00830 float v5 = wp2 * Px(int(ii + 2*pi),int(jj + 2*pj)); 00831 00832 float val = v1 + v2 + v3 + v4 + v5; 00833 00834 // if(i > 158 && i < 170 && j ==60 && scale == 0 && 00835 // pi != 0.0 && pj != 0.0) 00836 // { 00837 // LINFO("[%d] i, j: %d %d", time, i, j); 00838 // LINFO("ii, jj: %f %f", ii, jj); 00839 // LINFO("pi, pj: %f %f", pi, pj); 00840 00841 // // LINFO("%d %d: %f x", int(iim2),int(jjm2), wm2); 00842 // // LINFO("%d %d: %f x", int(iim1),int(jjm1), wm1); 00843 // // LINFO("%d %d: %f x", int(ii), int(jj), w); 00844 // // LINFO("%d %d: %f x", int(iip1),int(jjp1), wp1); 00845 // // LINFO("%d %d: %f x", int(iip2),int(jjp2), wp2); 00846 00847 // LINFO("%d %d: %f x %f", int(iim2),int(jjm2), Px(int(iim2),int(jjm2)), wm2); 00848 // LINFO("%d %d: %f x %f", int(iim1),int(jjm1), Px(int(iim1),int(jjm1)), wm1); 00849 // LINFO("%d %d: %f x %f", int(ii), int(jj), Px(int(ii), int(jj) ), w); 00850 // LINFO("%d %d: %f x %f", int(iip1),int(jjp1), Px(int(iip1),int(jjp1)), wp1); 00851 // LINFO("%d %d: %f x %f", int(iip2),int(jjp2), Px(int(iip2),int(jjp2)), wp2); 00852 00853 // LINFO("%f %f %f %f %f = %f", v1, v2, v3, v4, v5, val); 00854 // } 00855 00856 return val; 00857 00858 } 00859 00860 // ###################################################################### 00861 template <class T> 00862 float SpatioTemporalEnergyPyrBuilder<T>::DrawVectors 00863 (Image<T> &img, Image<float> &motion) 00864 { 00865 //TODO: should check the mag is the same size as dir 00866 00867 Image<float>::const_iterator mag_ptr = motion.begin(); 00868 Image<float>::const_iterator mag_stop = motion.end(); 00869 00870 int inx=0; 00871 int avg_i = 0; 00872 double avg_angle = 0; 00873 00874 while (mag_ptr != mag_stop) 00875 { 00876 int y = inx/motion.getWidth(); 00877 int x = inx - (y*motion.getWidth()); 00878 00879 if (*mag_ptr != 0) { 00880 avg_i++; 00881 //avg_angle += (*mag_ptr+M_PI/2); 00882 avg_angle += (*mag_ptr); 00883 00884 int scale_x = x * (img.getWidth()/motion.getWidth()); 00885 int scale_y = y * (img.getHeight()/motion.getHeight()); 00886 drawLine(img, Point2D<int>(scale_x,scale_y), 00887 Point2D<int>((int)(scale_x+25*cos((*mag_ptr))), 00888 (int)(scale_y-25*sin((*mag_ptr)))), 00889 (T)0); 00890 } 00891 mag_ptr++; 00892 inx++; 00893 } 00894 00895 if (avg_i > 0){ 00896 int xi = img.getWidth()/2; 00897 int yi = img.getHeight()/2; 00898 00899 drawLine(img,Point2D<int>(xi, yi), 00900 Point2D<int>((int)(xi+75*cos(avg_angle/avg_i)), 00901 (int)(yi-75*sin(avg_angle/avg_i))), 00902 (T)0, 3); 00903 return avg_angle/avg_i; 00904 } 00905 00906 return -999; 00907 } 00908 00909 // ###################################################################### 00910 template <class T> 00911 SpatioTemporalEnergyPyrBuilder<T>* SpatioTemporalEnergyPyrBuilder<T>::clone() const 00912 { return new SpatioTemporalEnergyPyrBuilder<T>(*this); } 00913 00914 // ###################################################################### 00915 template <class T> 00916 void SpatioTemporalEnergyPyrBuilder<T>::reset() 00917 { 00918 // imgPyrQ.clear(); 00919 } 00920 00921 // ###################################################################### 00922 template <class T> 00923 void SpatioTemporalEnergyPyrBuilder<T>::print 00924 (Image<float> image, uint si, uint ei, uint sj, uint ej, float stop) 00925 { 00926 for(uint j = sj; j <= ej; j++) 00927 { 00928 for(uint i = si; i <= ei; i++) 00929 //if(image.getVal(i,j) > 0.0) 00930 //LINFO("[%3d %3d]: %10.3f", i,j, image.getVal(i,j)); 00931 LINFO("%9.3f ", image.getVal(i,j)); 00932 LINFO("\n"); 00933 } 00934 LINFO("\n"); 00935 if(stop) Raster::waitForKey(); 00936 } 00937 00938 // ###################################################################### 00939 template <class T> 00940 void SpatioTemporalEnergyPyrBuilder<T>::print 00941 (ImageSet<float> images, uint si, uint ei, uint sj, uint ej, float stop) 00942 { 00943 for(uint k = 0; k < images.size(); k++) 00944 { 00945 LINFO("level: %d", k); 00946 uint div = uint(pow(2.0,k)); 00947 for(uint j = sj/div; j <= ej/div; j++) 00948 { 00949 for(uint i = si/div; i <= ei/div; i++) 00950 //if(image.getVal(i,j) > 0.0) 00951 //LINFO("[%3d %3d]: %10.3f", i,j, image.getVal(i,j)); 00952 LINFO("%9.3f ", images[k].getVal(i,j)); 00953 LINFO("\n"); 00954 } 00955 LINFO("\n"); 00956 } 00957 00958 if(stop) Raster::waitForKey(); 00959 } 00960 00961 00962 // ###################################################################### 00963 // template <class T> 00964 // void SpatioTemporalEnergyPyrBuilder<T>::print 00965 //(Image<float> image, std::vector<uint> si, std::vector<uint> ei, 00966 // std::vector<uint> sj, std::vector<uint> ej, std::vector<uint> levels, float stop) 00967 // { 00968 // for (uint i = 0; i < itsDepth; i++) 00969 // { 00970 // if(i == 0) 00971 // { 00972 // LINFO("level 0"); 00973 // for(uint y = 35; y < 85; y++) 00974 // { 00975 // for(uint x = 155; x < 168; x++) 00976 // LINFO("%7.3f ",pyr[i].getVal(x,y)); 00977 // //LINFO("%3d ",pyr[i].getVal(x,y)); 00978 // LINFO("\n"); 00979 // } 00980 // LINFO("\n"); 00981 // } 00982 00983 // if(i == 1) 00984 // { 00985 // LINFO("level 1"); 00986 // for(uint y = 10; y < 50; y++) 00987 // { 00988 // for(uint x = 75; x < 88; x++) 00989 // LINFO("%7.3f ",pyr[i].getVal(x,y)); 00990 // //LINFO("%3d ",pyr[i].getVal(x,y)); 00991 // LINFO("\n"); 00992 // } 00993 // LINFO("\n"); 00994 // } 00995 00996 // if(i == 2) 00997 // { 00998 // LINFO("level 2"); 00999 // for(uint y = 5; y < 25; y++) 01000 // { 01001 // for(uint x = 35; x < 48; x++) 01002 // LINFO("%7.3f ",pyr[i].getVal(x,y)); 01003 // //LINFO("%3d ",pyr[i].getVal(x,y)); 01004 // LINFO("\n"); 01005 // } 01006 // LINFO("\n"); 01007 // } 01008 01009 // if(i == 3) 01010 // { 01011 // LINFO("level 3"); 01012 // for(uint y = 0; y < 20; y++) 01013 // { 01014 // for(uint x = 13; x < 27; x++) 01015 // LINFO("%7.3f ",pyr[i].getVal(x,y)); 01016 // //LINFO("%3d ",pyr[i].getVal(x,y)); 01017 // LINFO("\n"); 01018 // } 01019 // LINFO("\n"); 01020 // } 01021 01022 // if(i == 4) 01023 // { 01024 // LINFO("level 4"); 01025 // for(uint y = 0; y < 15; y++) 01026 // { 01027 // for(uint x = 5; x < 18; x++) 01028 // LINFO("%7.3f ",pyr[i].getVal(x,y)); 01029 // //LINFO("%3d ",pyr[i].getVal(x,y)); 01030 // LINFO("\n"); 01031 // } 01032 // LINFO("\n"); 01033 // } 01034 // } 01035 //} 01036 01037 // ###################################################################### 01038 template <class T> 01039 void SpatioTemporalEnergyPyrBuilder<T>::display(Image<float> image) 01040 { 01041 uint w = image.getWidth(); 01042 uint h = image.getHeight(); 01043 01044 if(itsWin.is_invalid()) 01045 { 01046 std::string ntext(sformat("t=%5.2f", itsGaborAngle)); 01047 itsWin.reset(new XWinManaged(Dims(w,h), 0,0, ntext.c_str())); 01048 } 01049 01050 itsWin->setDims(Dims(w, h)); 01051 LINFO("Dims: (%d,%d)", w, h); 01052 01053 float mn,mx; getMinMax(image, mn,mx); 01054 LINFO("min: %f, max: %f", mn, mx); 01055 itsWin->drawImage(image,0,0); 01056 Raster::waitForKey(); 01057 } 01058 01059 // ###################################################################### 01060 template <class T> 01061 void SpatioTemporalEnergyPyrBuilder<T>::display(ImageSet<float> images) 01062 { 01063 uint w = images[0].getWidth(); 01064 uint h = images[0].getHeight(); 01065 01066 if(itsWin.is_invalid()) 01067 { 01068 std::string ntext(sformat("t=%5.2f", itsGaborAngle)); 01069 itsWin.reset(new XWinManaged(Dims(w,h), 0,0, ntext.c_str())); 01070 } 01071 01072 uint numLevels = images.size(); 01073 itsWin->setDims(Dims(w, h)); 01074 Image<float> disp(w, h, ZEROS); 01075 LINFO("Depth: %d Dim(%d,%d)", numLevels, w, h); 01076 for (uint i = 0; i < numLevels; i++) 01077 { 01078 uint scale = pow(2.0, i); 01079 01080 if(w >= uint(images[i].getWidth() * scale) && 01081 h >= uint(images[i].getHeight() * scale) ) 01082 { 01083 Image<float> temp = images[i]; 01084 float mn,mx; getMinMax(images[i], mn,mx); 01085 LINFO("min: %f, max: %f", mn, mx); 01086 01087 inplaceNormalize(temp, 0.0F, 255.0F); 01088 inplacePaste(disp, zoomXY(temp, scale) , Point2D<int>(0, 0)); 01089 itsWin->drawImage(disp,0,0); Raster::waitForKey(); 01090 } 01091 else{ LINFO("Too big. Not drawn."); } 01092 } 01093 } 01094 01095 01096 template class SpatioTemporalEnergyPyrBuilder<byte>; 01097 template class SpatioTemporalEnergyPyrBuilder<float>; 01098 01099 // ###################################################################### 01100 /* So things look consistent in everyone's emacs... */ 01101 /* Local Variables: */ 01102 /* indent-tabs-mode: nil */ 01103 /* End: */