00001 /*!@file Image/IntegerMathOps.H Fixed-point integer math versions of some of our floating-point Image functions */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/IntegerMathOps.H $ 00035 // $Id: IntegerMathOps.H 10983 2009-03-05 07:19:14Z itti $ 00036 // 00037 00038 #ifndef IMAGE_INTEGERMATHOPS_H_DEFINED 00039 #define IMAGE_INTEGERMATHOPS_H_DEFINED 00040 00041 #include "Image/Image.H" 00042 #include "Image/ImageSet.H" 00043 #include "Image/PyrBuilder.H" 00044 #include "Image/fancynorm.H" 00045 #include "Image/integer_math.h" 00046 00047 #include <deque> 00048 00049 template <int tabsiz_, int nbits_> 00050 class IntgTrigTable 00051 { 00052 public: 00053 enum { tabsiz = tabsiz_ }; 00054 enum { nbits = nbits_ }; 00055 00056 IntgTrigTable() 00057 { 00058 for (int i = 0; i < tabsiz; ++i) 00059 { 00060 const double arg = (2.0*M_PI*i) / double(tabsiz); 00061 #ifdef HAVE_SINCOS 00062 double sinarg, cosarg; 00063 sincos(arg, &sinarg, &cosarg); 00064 #else 00065 double sinarg = sin(arg); 00066 double cosarg = cos(arg); 00067 #endif 00068 sintab[i] = int(sinarg * (1 << nbits)); 00069 costab[i] = int(cosarg * (1 << nbits)); 00070 } 00071 } 00072 00073 int indexDegrees(const double deg) 00074 { 00075 int idx = int((deg * tabsiz) / 360.0) % tabsiz; 00076 if (idx < 0) idx += tabsiz; 00077 return idx; 00078 } 00079 00080 int indexRadians(const double rad) 00081 { 00082 int idx = int((rad * tabsiz) / (2.0*M_PI)) % tabsiz; 00083 if (idx < 0) idx += tabsiz; 00084 return idx; 00085 } 00086 00087 int sintab[tabsiz]; 00088 int costab[tabsiz]; 00089 00090 private: 00091 00092 bool inited; 00093 }; 00094 00095 /// shift left if nbits > 8; shift right if nbits < 8 00096 /** src is a pointer (rather than a reference) to prevent unwanted 00097 implicit conversions */ 00098 int intgScaleFromByte(const byte* src, const uint nbits); 00099 00100 /// assume input range is [0..255]; shift left if nbits > 8; shift right if nbits < 8 00101 /** src is a pointer (rather than a reference) to prevent unwanted 00102 implicit conversions */ 00103 int intgScaleFromFloat(const float* src, const uint nbits); 00104 00105 /// shift left if nbits > 8; shift right if nbits < 8 00106 /** src is a pointer (rather than a reference) to prevent unwanted 00107 implicit conversions */ 00108 Image<int> intgScaleFromByte(const Image<byte>* src, const uint nbits); 00109 00110 /// assume input range is [0..255]; shift left if nbits > 8; shift right if nbits < 8 00111 /** src is a pointer (rather than a reference) to prevent unwanted 00112 implicit conversions */ 00113 Image<int> intgScaleFromFloat(const Image<float>* src, const uint nbits); 00114 00115 /// shift left if nbits > 8; shift right if nbits < 8 00116 /** src is a pointer (rather than a reference) to prevent unwanted 00117 implicit conversions */ 00118 Image<PixRGB<int> > intgScaleFromByte(const Image<PixRGB<byte> >* src, const uint nbits); 00119 00120 /// get the luminance with nbits of precision of the input image 00121 Image<int> intgScaleLuminanceFromByte(const Image<PixRGB<byte> >* src, const uint nbits); 00122 00123 /// assume input range is [0..255]; shift left if nbits > 8; shift right if nbits < 8 00124 /** src is a pointer (rather than a reference) to prevent unwanted 00125 implicit conversions */ 00126 Image<PixRGB<int> > intgScaleFromFloat(const Image<PixRGB<float> >* src, const uint nbits); 00127 00128 /// Convert from out integer representation to floats 00129 /** src is a pointer (rather than a reference) to prevent unwanted 00130 implicit conversions */ 00131 Image<float> intgScaleToFloat(const Image<int>* src, const uint nbits); 00132 00133 Image<int> intgLowPass5xDecX(const Image<int>& src, 00134 const integer_math* imath); 00135 00136 Image<int> intgLowPass5yDecY(const Image<int>& src, 00137 const integer_math* imath); 00138 00139 Image<int> intgXFilterClean(const Image<int>& src, 00140 const int* hFilt, const int hfs, 00141 const int shiftbits, 00142 const integer_math* imath); 00143 00144 Image<int> intgYFilterClean(const Image<int>& src, 00145 const int* vFilt, const int vfs, 00146 const int shiftbits, 00147 const integer_math* imath); 00148 00149 Image<int> intgLowPass9x(const Image<int>& src, 00150 const integer_math* imath); 00151 Image<int> intgLowPass9y(const Image<int>& src, 00152 const integer_math* imath); 00153 Image<int> intgLowPassX(int filterSize, const Image<int>& src, 00154 const integer_math* imath); 00155 Image<int> intgLowPassY(int filterSize, const Image<int>& src, 00156 const integer_math* imath); 00157 Image<int> intgLowPass(int filterSize, const Image<int>& src, 00158 const integer_math* imath); 00159 Image<int> intgQuadEnergy(const Image<int>& img1, const Image<int>& img2); 00160 Image<int> intgOrientedFilter(const Image<int>& src, 00161 const float k, const float theta, 00162 const integer_math* imath); 00163 void intgInplaceAttenuateBorders(Image<int>& a, int size); 00164 ImageSet<int> intgBuildPyrLaplacian(const Image<int>& image, 00165 int firstlevel, int depth, 00166 int filterSize, 00167 const integer_math* imath); 00168 ImageSet<int> intgBuildPyrOrientedFromLaplacian(const ImageSet<int>& lplc, 00169 const int filterSize, 00170 const float theta, 00171 const integer_math* imath); 00172 ImageSet<int> intgBuildPyrOriented(const Image<int>& image, 00173 int firstlevel, int depth, 00174 int filterSize, float theta, 00175 const integer_math* imath); 00176 ImageSet<int> intgBuildPyrGaussian(const Image<int>& image, 00177 int depth, int filterSize, 00178 const integer_math* imath); 00179 00180 Image<int> intgDownSize(const Image<int>& src, const Dims& dims, 00181 const int filterWidth, 00182 const integer_math* imath); 00183 Image<int> intgRescale(const Image<int>& src, const Dims& dims); 00184 void intgInplaceAddBGnoise(Image<int>& src, int max); 00185 Image<int> intgMaxNormalize(const Image<int>& src, int min, int max, 00186 MaxNormType typ); 00187 Image<int> intgMaxNormalizeNone(const Image<int>& src, int min, int max); 00188 Image<int> intgMaxNormalizeStd(const Image<int>& src, int min, int max); 00189 Image<int> intgCenterSurround(const ImageSet<int>& pyr, 00190 int lev1, int lev2, bool absol, 00191 const ImageSet<int>* clipPyr); 00192 00193 void intgDoLowThresh(ImageSet<int>& pyr, int thresh, int newval = 0); 00194 00195 void intgDoLowThreshAbs(ImageSet<int>& pyr, int thresh, int newval = 0); 00196 00197 void intgDoRectify(ImageSet<int>& pyr); 00198 00199 void intgInplaceNormalize(Image<int>& dst, 00200 const int nmin, const int nmax, 00201 int* actualmin, int* actualmax); 00202 00203 Image<int> intgCenterSurround(const Image<int>& center, 00204 const Image<int>& surround, 00205 const bool absol); 00206 00207 /// Pixels with luminance less than MAX/threshfactor will have rg=by=0 00208 /** Note that in the floating-point version getRGBY(), we take a 00209 luminance threshold and test 00210 00211 ((r+g+b)/3 < thresh) 00212 00213 where thresh is usually set to 25.5, i.e. 255/10. Here, to avoid 00214 loss of precision, we want to avoid any divisions, so instead we 00215 test 00216 00217 (threshfactor*(r+g+b) < 3*MAX) 00218 00219 which is equivalent to, but more precise than, 00220 00221 ((r+g+b)/3 < MAX/threshfactor). 00222 */ 00223 void intgGetRGBY(const Image<PixRGB<byte> >& src, 00224 Image<int>& rg, 00225 Image<int>& by, const int threshfactor, 00226 const uint inputbits); 00227 00228 Image<int> intgShiftImage(const Image<int>& srcImg, 00229 const int dxnumer, const int dynumer, 00230 const uint denombits); 00231 00232 // ###################################################################### 00233 //! Builds pyramids based on Gaussian filters. 00234 class IntgGaussianPyrBuilder : public PyrBuilder<int> 00235 { 00236 public: 00237 //! Constructor. 00238 IntgGaussianPyrBuilder(const int filter_size, 00239 const integer_math* imath); 00240 00241 // Default copy constructor and assignment operator ok. 00242 00243 //! Cloning constructor: 00244 virtual IntgGaussianPyrBuilder* clone() const; 00245 00246 //! Builds a Gaussian pyramid based on \a img. 00247 virtual ImageSet<int> build(const Image<int>& img, 00248 const int firstlevel, const int depth, 00249 PyramidCache<int>* cache = 0); 00250 00251 private: 00252 const int itsFiltSize; 00253 const integer_math* const itsImath; 00254 }; 00255 00256 // ###################################################################### 00257 //! Builds pyramid based on oriented Laplacian filters. 00258 /*! This is a fast approximation to Gabor convolution. */ 00259 class IntgOrientedPyrBuilder : public PyrBuilder<int> 00260 { 00261 public: 00262 //! Construct with a given gabor filter orientation and intensity. 00263 IntgOrientedPyrBuilder(const int filter_size, const float theta, 00264 const integer_math* imath); 00265 00266 // Default copy constructor and assignment operator ok. 00267 00268 //! Cloning constructor: 00269 virtual IntgOrientedPyrBuilder* clone() const; 00270 00271 //! Builds an oriented pyramid based on \a img. 00272 virtual ImageSet<int> build(const Image<int>& img, 00273 const int firstlevel, const int depth, 00274 PyramidCache<int>* cache = 0); 00275 00276 private: 00277 const int itsFiltSize; 00278 const float itsAngle; 00279 const integer_math* const itsImath; 00280 }; 00281 00282 // ###################################################################### 00283 //! This class implements Reichardt motion detections 00284 /*! The class uses the filter results of pyramids of other types 00285 to implement Reichardt motion detection. The pyramids of the previous 00286 time step are stored and used with the pyramid of this time step and 00287 a version of the current pyramid, in which each level is shifted by the 00288 same amount dx and dy. The results are stored in the Reichardt pyramid and 00289 represent motion at different speeds and spatial resolutions. */ 00290 class IntgReichardtPyrBuilder : public PyrBuilder<int> 00291 { 00292 public: 00293 // ###################################################################### 00294 // #### Constructors 00295 // ###################################################################### 00296 //! build with depth, dx, dy and type, but no input image yet 00297 /*! @param dx the number of pixels to shift into the x-direction 00298 (can be fractional value) 00299 @param dy the number of pixels to shift into the y-direction 00300 */ 00301 IntgReichardtPyrBuilder(const int dxnumer, const int dynumer, 00302 const uint denombits, 00303 const integer_math* imath); 00304 00305 // default copy constructor and assignment are okay 00306 // std::deque handles the copying of the individual images 00307 00308 //! cloning constructor 00309 virtual IntgReichardtPyrBuilder* clone() const; 00310 00311 //! Builds a Reichardt pyramid based on a image 00312 virtual ImageSet<int> build(const Image<int>& image, 00313 const int firstlevel, const int depth, 00314 PyramidCache<int>* cache = 0); 00315 00316 //! reset the stored queues - overrides PyrBuilder<T>::reset() 00317 virtual void reset(); 00318 00319 private: 00320 const int itsDXnumer; 00321 const int itsDYnumer; 00322 const uint itsDenomBits; 00323 const integer_math* const itsImath; 00324 std::deque< ImageSet<int> > shifted, unshifted; 00325 }; 00326 00327 // ###################################################################### 00328 /* So things look consistent in everyone's emacs... */ 00329 /* Local Variables: */ 00330 /* mode: c++ */ 00331 /* indent-tabs-mode: nil */ 00332 /* End: */ 00333 00334 #endif // IMAGE_INTEGERMATHOPS_H_DEFINED