PyrBuilder.C

Go to the documentation of this file.
00001 /*!@file Image/PyrBuilder.C Classes for building dyadic pyramids */
00002 
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: Laurent Itti <itti@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/PyrBuilder.C $
00035 // $Id: PyrBuilder.C 14473 2011-02-03 20:36:39Z dberg $
00036 //
00037 
00038 #include "Image/PyrBuilder.H"
00039 
00040 #include "Image/Image.H"
00041 #include "Image/ImageSet.H"
00042 #include "Image/ColorOps.H"
00043 #include "Image/CutPaste.H"
00044 #include "Image/FilterOps.H"
00045 #include "Image/MathOps.H"
00046 #include "Image/ShapeOps.H"
00047 #include "Image/Pixels.H"
00048 #include "Image/PyramidCache.H"
00049 #include "Image/PyramidOps.H"
00050 #include "rutz/trace.h"
00051 
00052 // ######################################################################
00053 // ##### PyrBuilder functions:
00054 // ######################################################################
00055 
00056 // ######################################################################
00057 template <class T>
00058 PyrBuilder<T>::PyrBuilder()
00059 {
00060 GVX_TRACE(__PRETTY_FUNCTION__);
00061 }
00062 
00063 // ######################################################################
00064 template <class T>
00065 PyrBuilder<T>::~PyrBuilder()
00066 {
00067 GVX_TRACE(__PRETTY_FUNCTION__);
00068 }
00069 
00070 // ######################################################################
00071 template <class T>
00072 void PyrBuilder<T>::reset()
00073 {
00074 GVX_TRACE(__PRETTY_FUNCTION__);
00075 }
00076 
00077 // ######################################################################
00078 // ##### GaussianPyrBuilder Functions:
00079 // ######################################################################
00080 
00081 template <class T>
00082 GaussianPyrBuilder<T>::GaussianPyrBuilder(int filter_size) :
00083   PyrBuilder<T>(), itsFiltSize(filter_size)
00084 {
00085 GVX_TRACE(__PRETTY_FUNCTION__);
00086 }
00087 
00088 template <class T>
00089 ImageSet<T> GaussianPyrBuilder<T>::build(const Image<T>& img,
00090                                          const int firstlevel,
00091                                          const int depth,
00092                                          PyramidCache<T>* cache)
00093 {
00094 GVX_TRACE(__PRETTY_FUNCTION__);
00095 
00096   const ImageSet<T>* const cached =
00097     (cache != 0 && itsFiltSize == 5)
00098     ? cache->gaussian5.get(img) // may be null if there is no cached pyramid
00099     : 0;
00100 
00101   return (cached != 0)
00102     ? *cached
00103     : buildPyrGaussian(img, firstlevel, depth, itsFiltSize);
00104 }
00105 
00106 template <class T> inline
00107 GaussianPyrBuilder<T>* GaussianPyrBuilder<T>::clone() const
00108 {
00109 GVX_TRACE(__PRETTY_FUNCTION__);
00110   return new GaussianPyrBuilder<T>(*this);
00111 }
00112 
00113 // ######################################################################
00114 // ##### GaussianRadialPyrBuilder Functions:
00115 // ######################################################################
00116 
00117 template <class T>
00118 GaussianRadialPyrBuilder<T>::GaussianRadialPyrBuilder() :
00119   PyrBuilder<T>()
00120 {
00121 GVX_TRACE(__PRETTY_FUNCTION__);
00122 }
00123 
00124 template <class T>
00125 ImageSet<T> GaussianRadialPyrBuilder<T>::build(const Image<T>& img,
00126                                          const int firstlevel,
00127                                          const int depth,
00128                                          PyramidCache<T>* cache)
00129 {
00130 GVX_TRACE(__PRETTY_FUNCTION__);
00131 
00132  const ImageSet<T>* const cached = (cache != 0)
00133    ? cache->gaussian5.get(img) // may be null if there is no cached pyramid
00134    : 0;
00135 
00136  return (cached != 0)
00137    ? *cached
00138    : buildRadialPyrGaussian(img, firstlevel, depth);
00139 }
00140 
00141 template <class T> inline
00142 GaussianRadialPyrBuilder<T>* GaussianRadialPyrBuilder<T>::clone() const
00143 {
00144 GVX_TRACE(__PRETTY_FUNCTION__);
00145   return new GaussianRadialPyrBuilder<T>(*this);
00146 }
00147 
00148 // ######################################################################
00149 // ##### ConvolvePyrBuilder Functions:
00150 // ######################################################################
00151 
00152 template <class T>
00153 ConvolvePyrBuilder<T>::
00154 ConvolvePyrBuilder(const Image<float>& filt,
00155                    ConvolutionBoundaryStrategy boundary) :
00156   PyrBuilder<T>(), itsFilt(filt), itsBoundary(boundary)
00157 {
00158 GVX_TRACE(__PRETTY_FUNCTION__);
00159 }
00160 
00161 template <class T>
00162 ImageSet<T> ConvolvePyrBuilder<T>::build(const Image<T>& img,
00163                                          const int firstlevel,
00164                                          const int depth,
00165                                          PyramidCache<T>* cache)
00166 {
00167 GVX_TRACE(__PRETTY_FUNCTION__);
00168   return buildPyrConvolve(img, firstlevel, depth, itsFilt, itsBoundary);
00169 }
00170 
00171 template <class T>
00172 ConvolvePyrBuilder<T>* ConvolvePyrBuilder<T>::clone() const
00173 {
00174 GVX_TRACE(__PRETTY_FUNCTION__);
00175   return new ConvolvePyrBuilder<T>(*this);
00176 }
00177 
00178 // ######################################################################
00179 // ##### RGBConvolvePyrBuilder Functions:
00180 // ######################################################################
00181 
00182 template <class T>
00183 RGBConvolvePyrBuilder<T>::
00184 RGBConvolvePyrBuilder(const Image<float>& rfilt,
00185                       const Image<float>& gfilt,
00186                       const Image<float>& bfilt,
00187                       ConvolutionBoundaryStrategy boundary) :
00188   PyrBuilder<T>(), itsRFilt(rfilt), itsGFilt(rfilt), itsBFilt(rfilt),
00189   itsBoundary(boundary)
00190 {
00191 GVX_TRACE(__PRETTY_FUNCTION__);
00192 }
00193 
00194 template <class T>
00195 ImageSet<T> RGBConvolvePyrBuilder<T>::
00196 build(const Image< PixRGB<T> >& img,
00197       const int firstlevel,
00198       const int depth,
00199       PyramidCache<T>* cache)
00200 {
00201 GVX_TRACE(__PRETTY_FUNCTION__);
00202   Image<T> r, g, b; getComponents(img, r, g, b);
00203   ImageSet<T> rset = buildPyrConvolve(r, firstlevel, depth, itsRFilt, itsBoundary);
00204   ImageSet<T> gset = buildPyrConvolve(g, firstlevel, depth, itsGFilt, itsBoundary);
00205   ImageSet<T> bset = buildPyrConvolve(b, firstlevel, depth, itsBFilt, itsBoundary);
00206   ImageSet<T> result(depth);
00207 
00208   for (int lev = firstlevel; lev < depth; ++lev)
00209     result[lev] = (rset[lev] + gset[lev] + bset[lev]) / 3;
00210 
00211   return result;
00212 }
00213 
00214 template <class T>
00215 ImageSet<T> RGBConvolvePyrBuilder<T>::
00216 build(const Image<T>& img,
00217       const int firstlevel,
00218       const int depth,
00219       PyramidCache<T>* cache)
00220 {
00221 GVX_TRACE(__PRETTY_FUNCTION__);
00222   LFATAL("Cannot process greyscale images");
00223   return ImageSet<T>();
00224 }
00225 
00226 template <class T>
00227 ImageSet< PixRGB<T> > RGBConvolvePyrBuilder<T>::
00228 build2(const Image< PixRGB<T> >& img,
00229        const int firstlevel,
00230        const int depth,
00231        PyramidCache<T>* cache)
00232 {
00233 GVX_TRACE(__PRETTY_FUNCTION__);
00234   Image<T> r, g, b; getComponents(img, r, g, b);
00235   ImageSet<T> rset = buildPyrConvolve(r, firstlevel, depth, itsRFilt, itsBoundary);
00236   ImageSet<T> gset = buildPyrConvolve(g, firstlevel, depth, itsGFilt, itsBoundary);
00237   ImageSet<T> bset = buildPyrConvolve(b, firstlevel, depth, itsBFilt, itsBoundary);
00238   ImageSet< PixRGB<T> > result(depth);
00239 
00240   for (int lev = firstlevel; lev < depth; ++lev)
00241     result[lev] = makeRGB (rset[lev], gset[lev], bset[lev]);
00242 
00243   return result;
00244 }
00245 
00246 template <class T>
00247 RGBConvolvePyrBuilder<T>* RGBConvolvePyrBuilder<T>::clone() const
00248 {
00249 GVX_TRACE(__PRETTY_FUNCTION__);
00250   return new RGBConvolvePyrBuilder<T>(*this);
00251 }
00252 
00253 // ######################################################################
00254 // ##### LaplacianPyrBuilder Functions:
00255 // ######################################################################
00256 
00257 template <class T>
00258 LaplacianPyrBuilder<T>::LaplacianPyrBuilder(const int filter_size) :
00259   PyrBuilder<T>(), itsFiltSize(filter_size)
00260 {
00261 GVX_TRACE(__PRETTY_FUNCTION__);
00262 }
00263 
00264 template <class T>
00265 ImageSet<T> LaplacianPyrBuilder<T>::build(const Image<T>& img,
00266                                           const int firstlevel,
00267                                           const int depth,
00268                                           PyramidCache<T>* cache)
00269 {
00270 GVX_TRACE(__PRETTY_FUNCTION__);
00271   return buildPyrLaplacian(img, firstlevel, depth, itsFiltSize);
00272 }
00273 
00274 template <class T> inline
00275 LaplacianPyrBuilder<T>* LaplacianPyrBuilder<T>::clone() const
00276 {
00277 GVX_TRACE(__PRETTY_FUNCTION__);
00278   return new LaplacianPyrBuilder<T>(*this);
00279 }
00280 
00281 // ######################################################################
00282 // ##### OrientedPyrBuilder Functions:
00283 // ######################################################################
00284 
00285 template <class T>
00286 OrientedPyrBuilder<T>::OrientedPyrBuilder(const int filter_size,
00287                                           const float theta,
00288                                           const float intens,
00289                                           const bool usetab) :
00290   PyrBuilder<T>(), itsFiltSize(filter_size), itsAngle(theta),
00291   itsGaborIntens(intens), itsUseTab(usetab)
00292 {
00293 GVX_TRACE(__PRETTY_FUNCTION__);
00294 }
00295 
00296 template <class T>
00297 ImageSet<T> OrientedPyrBuilder<T>::build(const Image<T>& img,
00298                                          const int firstlevel,
00299                                          const int depth,
00300                                          PyramidCache<T>* cache)
00301 {
00302 GVX_TRACE(__PRETTY_FUNCTION__);
00303 
00304   const ImageSet<T>* const lplc =
00305     (cache != 0 && itsFiltSize == 9)
00306     ? cache->laplacian9.get(img) // may be null if there is no cached pyramid
00307     : 0;
00308 
00309   return lplc != 0
00310     ? buildPyrOrientedFromLaplacian<T>(*lplc,
00311                                        itsFiltSize, itsAngle, itsGaborIntens,
00312                                        itsUseTab)
00313     : buildPyrOriented(img, firstlevel, depth,
00314                        itsFiltSize, itsAngle, itsGaborIntens, itsUseTab);
00315 }
00316 
00317 template <class T>
00318 OrientedPyrBuilder<T>* OrientedPyrBuilder<T>::clone() const
00319 {
00320 GVX_TRACE(__PRETTY_FUNCTION__);
00321   return new OrientedPyrBuilder<T>(*this);
00322 }
00323 
00324 
00325 // ######################################################################
00326 // ##### GenericPyrBuilder Functions:
00327 // ######################################################################
00328 
00329 template <class T>
00330 GenericPyrBuilder<T>::GenericPyrBuilder(const PyramidType typ,
00331                                         const float gabor_theta,
00332                                         const float intens) :
00333   PyrBuilder<T>(), itsPtype(typ), itsGaborAngle(gabor_theta),
00334   itsGaborIntens(intens)
00335 {
00336 GVX_TRACE(__PRETTY_FUNCTION__);
00337 }
00338 
00339 template <class T>
00340 ImageSet<T> GenericPyrBuilder<T>::build(const Image<T>& image,
00341                                         const int firstlevel,
00342                                         const int depth,
00343                                         PyramidCache<T>* cache)
00344 {
00345 GVX_TRACE(__PRETTY_FUNCTION__);
00346   return buildPyrGeneric(image, firstlevel, depth, itsPtype,
00347                          itsGaborAngle, itsGaborIntens);
00348 }
00349 
00350 template <class T>
00351 GenericPyrBuilder<T>* GenericPyrBuilder<T>::clone() const
00352 {
00353 GVX_TRACE(__PRETTY_FUNCTION__);
00354   return new GenericPyrBuilder<T>(*this);
00355 }
00356 
00357 // ######################################################################
00358 // ##### ReichardtPyrBuilder Functions:
00359 // ######################################################################
00360 template <class T>
00361 ReichardtPyrBuilder<T>::ReichardtPyrBuilder(const float dx,
00362                                             const float dy,
00363                                             const PyramidType typ,
00364                                             const float gabor_theta,
00365                                             const float intens) :
00366   PyrBuilder<T>(), itsDX(dx), itsDY(dy), itsPtype(typ),
00367   itsGaborAngle(gabor_theta), itsGaborIntens(intens)
00368 {
00369 GVX_TRACE(__PRETTY_FUNCTION__);
00370 }
00371 
00372 template <class T>
00373 ImageSet<T> ReichardtPyrBuilder<T>::build(const Image<T>& image,
00374                                           const int firstlevel,
00375                                           const int depth,
00376                                           PyramidCache<T>* cache)
00377 {
00378 GVX_TRACE(__PRETTY_FUNCTION__);
00379   const ImageSet<T>* const cached =
00380     (cache != 0 && itsPtype == Gaussian5)
00381     ? cache->gaussian5.get(image) // may be null if there is no cached pyramid
00382     : 0;
00383 
00384   // create a pyramid with the input image
00385   ImageSet<T> upyr =
00386     cached != 0
00387     ? *cached
00388     : buildPyrGeneric(image, firstlevel, depth, itsPtype,
00389                       itsGaborAngle, itsGaborIntens);
00390   // create an empty pyramid
00391   ImageSet<T> spyr(depth);
00392 
00393   // fill the empty pyramid with the shifted version
00394   for (int i = firstlevel; i < depth; ++i)
00395     spyr[i] = shiftImage(upyr[i], itsDX, itsDY);
00396 
00397   // store both pyramids in the deques
00398   unshifted.push_back(upyr);
00399   shifted.push_back(spyr);
00400 
00401   ImageSet<T> result(depth);
00402 
00403   // so, it's our first time? Pretend the pyramid before this was
00404   // the same as the current one ...
00405   if (unshifted.size() == 1)
00406     {
00407       unshifted.push_back(upyr);
00408       shifted.push_back(spyr);
00409     }
00410 
00411   // need to pop off old pyramid?
00412   if (unshifted.size() == 3)
00413     {
00414       unshifted.pop_front();
00415       shifted.pop_front();
00416     }
00417 
00418   // compute the Reichardt maps
00419   for (int i = firstlevel; i < depth; ++i)
00420     {
00421       result[i] =
00422         (unshifted.back()[i] * shifted.front()[i]) -
00423         (unshifted.front()[i] * shifted.back()[i]);
00424     }
00425 
00426   return result;
00427 }
00428 
00429 // ######################################################################
00430 template <class T>
00431 ReichardtPyrBuilder<T>* ReichardtPyrBuilder<T>::clone() const
00432 {
00433 GVX_TRACE(__PRETTY_FUNCTION__);
00434   return new ReichardtPyrBuilder<T>(*this);
00435 }
00436 
00437 // ######################################################################
00438 template <class T>
00439 void ReichardtPyrBuilder<T>::reset()
00440 {
00441 GVX_TRACE(__PRETTY_FUNCTION__);
00442   shifted.clear();
00443   unshifted.clear();
00444 }
00445 
00446 // ######################################################################
00447 // ##### TemplateMatchPyrBuilder Functions:
00448 // ######################################################################
00449 TemplateMatchPyrBuilder::TemplateMatchPyrBuilder(const Image<float>& templ) :
00450   PyrBuilder<float>(), itsFilt(templ)
00451 {
00452 GVX_TRACE(__PRETTY_FUNCTION__);
00453 }
00454 
00455 // ######################################################################
00456 TemplateMatchPyrBuilder* TemplateMatchPyrBuilder::clone() const
00457 {
00458 GVX_TRACE(__PRETTY_FUNCTION__);
00459   return new TemplateMatchPyrBuilder(*this);
00460 }
00461 
00462 // ######################################################################
00463 ImageSet<float> TemplateMatchPyrBuilder::build(const Image<float>& image,
00464                                                const int firstlevel,
00465                                                const int depth,
00466                                                PyramidCache<float>* cache)
00467 {
00468 GVX_TRACE(__PRETTY_FUNCTION__);
00469   ImageSet<float> result(depth);
00470   if (0 >= firstlevel)
00471     result[0] = templateMatch(image);
00472   Image<float> prev_scale = image;
00473 
00474   for (int lev = 1; lev < depth; ++lev)
00475     {
00476       Image<float> cur_scale = prev_scale;
00477 
00478       cur_scale = decX(lowPass5x(cur_scale));
00479       cur_scale = decY(lowPass5y(cur_scale));
00480 
00481       // Save the unconvolved image at this scale to be used as the
00482       // starting point for the next scale
00483       prev_scale = cur_scale;
00484 
00485       if (lev >= firstlevel)
00486         result[lev] = templateMatch(cur_scale);
00487     }
00488 
00489   return result;
00490 }
00491 
00492 // ######################################################################
00493 Image<float> TemplateMatchPyrBuilder::templateMatch(const Image<float>& img)
00494 {
00495 GVX_TRACE(__PRETTY_FUNCTION__);
00496   Image<float> conv = convolve(img, itsFilt,
00497                                CONV_BOUNDARY_ZERO);
00498   Image<float> conv2 = convolve(binaryReverse(img, 255.0f), itsFilt,
00499                                 CONV_BOUNDARY_ZERO);
00500   return takeMax(conv, conv2);
00501 }
00502 
00503 // ######################################################################
00504 // ##### GaborPyrBuilder Functions:
00505 // ######################################################################
00506 template <class T>
00507 GaborPyrBuilder<T>::GaborPyrBuilder(double angle,
00508                                     double filter_period,
00509                                     double elongation,
00510                                     int size,
00511                                     int buildFlags) :
00512   PyrBuilder<T>(),
00513   itsAngle(angle),
00514   itsPeriod(filter_period),
00515   itsElongation(elongation),
00516   itsSize(size),
00517   itsBuildFlags(buildFlags)
00518 {
00519 GVX_TRACE(__PRETTY_FUNCTION__);
00520 }
00521 
00522 // ######################################################################
00523 template <class T>
00524 GaborPyrBuilder<T>* GaborPyrBuilder<T>::clone() const
00525 {
00526 GVX_TRACE(__PRETTY_FUNCTION__);
00527   return new GaborPyrBuilder<T>(*this);
00528 }
00529 
00530 // ######################################################################
00531 template <class T>
00532 ImageSet<T> GaborPyrBuilder<T>::build(const Image<T>& img,
00533                                       const int firstlevel,
00534                                       const int depth,
00535                                       PyramidCache<T>* cache)
00536 {
00537 GVX_TRACE(__PRETTY_FUNCTION__);
00538   return buildPyrGabor(img, firstlevel, depth,
00539                        itsAngle, itsPeriod, itsElongation,
00540                        itsSize, itsBuildFlags);
00541 }
00542 
00543 // ######################################################################
00544 template <class T>
00545 ImageSet<T> GaborPyrBuilder<T>::input(const ImageSet<T>& pyr)
00546 {
00547 GVX_TRACE(__PRETTY_FUNCTION__);
00548   return buildPyrGabor(pyr, itsAngle, itsPeriod, itsElongation,
00549                        itsSize, itsBuildFlags);
00550 }
00551 
00552 // ######################################################################
00553 // ##### Instantiations
00554 // ######################################################################
00555 template class GaborPyrBuilder<float>;
00556 template class RGBConvolvePyrBuilder<float>;
00557 
00558 #define INSTANTIATE(T) \
00559 template class PyrBuilder< T >; \
00560 template class GenericPyrBuilder< T >; \
00561 template class GaussianPyrBuilder< T >; \
00562 template class GaussianRadialPyrBuilder< T >; \
00563 template class ConvolvePyrBuilder< T >; \
00564 template class LaplacianPyrBuilder< T >; \
00565 template class OrientedPyrBuilder< T >; \
00566 template class ReichardtPyrBuilder< T >; \
00567 
00568 template class PyrBuilder<int>;
00569 
00570 #ifdef INVT_INST_BYTE
00571 INSTANTIATE(byte);
00572 INSTANTIATE(PixRGB<byte>);
00573 #endif
00574 #ifdef INVT_INST_INT16
00575 INSTANTIATE(int16);
00576 INSTANTIATE(PixRGB<int16>);
00577 #endif
00578 #ifdef INVT_INST_INT32
00579 INSTANTIATE(int32);
00580 INSTANTIATE(PixRGB<int32>);
00581 #endif
00582 #ifdef INVT_INST_FLOAT
00583 INSTANTIATE(float);
00584 INSTANTIATE(PixRGB<float>);
00585 #endif
00586 
00587 /* So things look consistent in everyone's emacs... */
00588 /* Local Variables: */
00589 /* indent-tabs-mode: nil */
00590 /* End: */
Generated on Sun May 8 08:40:57 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3