LowPassLpt.C

Go to the documentation of this file.
00001 /*!@file Image/LowPassLpt.C low-pass filtering and smoothing 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: David J. Berg <dberg@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/LowPassLpt.C $
00035 //
00036 
00037 #ifndef IMAGE_LOWPASSLPT_C_DEFINED
00038 #define IMAGE_LOWPASSLPT_C_DEFINED
00039 
00040 #include "Image/LowPassLpt.H"
00041 
00042 #include "Image/Convolutions.H"
00043 #include "Image/LowPass.H"
00044 #include "Image/Image.H"
00045 #include "Image/Kernels.H"
00046 #include "Image/Pixels.H"
00047 #include "rutz/trace.h"
00048 
00049 // ######################################################################
00050 template <class T_or_RGB>
00051 Image<typename promote_trait<T_or_RGB, float>::TP>
00052 lowPassLpt(const Image<T_or_RGB>& src, const uint taps, BorderPolicy policy)
00053 {
00054   if (taps == 5)
00055     if (policy == CROSS_HEMI)
00056       return lowPassLpt5w(lowPass5x(src));
00057     else if (policy == SEPARATE_HEMI)
00058       return lowPass5y(lowPassLpt5r(src));
00059     else
00060       return lowPassLpt5w(lowPassLpt5r(src));
00061   else if (taps == 3)
00062     if (policy == CROSS_HEMI)
00063       return lowPassLpt3w(lowPass3x(src));
00064     else if (policy == SEPARATE_HEMI)
00065       return lowPass3y(lowPassLpt3r(src));
00066     else
00067       return lowPassLpt3w(lowPassLpt3r(src));
00068   else
00069     return Image<typename promote_trait<T_or_RGB, float>::TP>();
00070 }
00071 
00072 
00073 // ######################################################################
00074 template <class T_or_RGB>
00075 Image<typename promote_trait<T_or_RGB, float>::TP>
00076 lowPassLpt3(const Image<T_or_RGB>& src, BorderPolicy policy)
00077 {
00078   if (policy == CROSS_HEMI)
00079     return lowPassLpt3w(lowPass3x(src));
00080   else if (policy == SEPARATE_HEMI)
00081     return lowPass3y(lowPassLpt3r(src));
00082   else
00083     return lowPassLpt3w(lowPassLpt3r(src));
00084 }
00085 
00086 // ######################################################################
00087 template <class T_or_RGB>
00088 Image<typename promote_trait<T_or_RGB, float>::TP>
00089 lowPassLpt3r(const Image<T_or_RGB>& src)
00090 {
00091   //really this should only be for images with even width, but the
00092   // operator will still work so we wont disallow it explicitly.
00093   GVX_TRACE(__PRETTY_FUNCTION__);
00094   const int w = src.getWidth(), h = src.getHeight(),
00095     hf = w / 2, h2 = 2*h;
00096   // promote the source image to float if necessary, so that we do the
00097   // promotion only once for all, rather than many times as we access
00098   // the pixels of the image; if no promotion is necessary, "source"
00099   // will just point to the original data of "src" through the
00100   // copy-on-write/ref-counting behavior of Image:
00101   typedef typename promote_trait<T_or_RGB, float>::TP TF;
00102   const Image<TF> source = src;
00103   if (w < 2)
00104     return source; // nothing to smooth
00105 
00106   Image<TF> result(w, h, NO_INIT);
00107   typename Image<TF>::const_iterator sptr = source.begin();
00108   typename Image<TF>::iterator dptr = result.beginw();
00109 
00110 // Do not use access overload since can access the C array directly.
00111   // the bet is: float computations are faster than int (true for most
00112   // float copros), and int2float converts fast->do not have to divide
00113   // by the coeff sum since we directly use float coeffs.
00114   // notations: in () is the position of dest ptr, and ^ is src ptr
00115   // ########## horizontal pass
00116   for (int j = 0; j < h2; j ++)
00117     {
00118       // leftmost point  [ (2^) 1 ] / 3
00119       *dptr++ = sptr[0] * (2.0F / 3.0F) + sptr[1] * (1.0F / 3.0F);
00120 
00121       // rest of the line up to the vertical meridian [ 1^ (2) 1] / 4
00122       for (int i = 0; i < hf - 2; i ++)
00123         {
00124           *dptr++ = (sptr[0] + sptr[2]) * 0.25F + sptr[1] * 0.5F;
00125           sptr++;
00126         }
00127 
00128       // last point [ 1^ (2) ] / 3
00129       *dptr++ = sptr[0] * (1.0F / 3.0F) + sptr[1] * (2.0F / 3.0F);
00130       sptr += 2;  // sptr back to same position as dptr
00131     }
00132   return result;
00133 }
00134 
00135 // ######################################################################
00136 template <class T_or_RGB>
00137 Image<typename promote_trait<T_or_RGB, float>::TP>
00138 lowPassLpt3w(const Image<T_or_RGB>& src)
00139 {
00140 GVX_TRACE(__PRETTY_FUNCTION__);
00141   const int w = src.getWidth(), h = src.getHeight();
00142   // promote the source image to float if necessary, so that we do the
00143   // promotion only once for all, rather than many times as we access
00144   // the pixels of the image; if no promotion is necessary, "source"
00145   // will just point to the original data of "src" through the
00146   // copy-on-write/ref-counting behavior of Image:
00147   typedef typename promote_trait<T_or_RGB, float>::TP TF;
00148   const Image<TF> source = src;
00149   if (h < 2)
00150     return source; // nothing to smooth
00151   Image<TF> result(w, h, NO_INIT);
00152   typename Image<TF>::const_iterator sptr = source.begin(),
00153     sptrh = source.begin() + w - 1;//the last point in the first image row
00154   typename Image<TF>::iterator dptr = result.beginw();
00155   const int w2 = w * 2; // speedup
00156 
00157   //'<' symbol means opposide side of the image
00158   // ########## vertical pass  (even though we scan horiz for speedup)
00159   // topmost points  ( [1< (2^) 1 ] / 4 )^T
00160   for (int i = 0; i < w; i ++)
00161     {
00162       //at the border get the pixel from the other hemiefield
00163       *dptr++ = (sptrh[0] + sptr[w]) * 0.25F + sptr[0] * 0.5F;
00164       ++sptr;
00165       --sptrh;
00166     }
00167   sptr -= w;  // go back to top-left
00168 
00169   // rest of the column except last point ( [ 1^ (2) 1 ] / 4.0 )^T
00170   for (int j = 0; j < h - 2; j ++)
00171     for (int i = 0; i < w; i ++)
00172       {
00173         *dptr++ = (sptr[0] + sptr[w2]) * 0.25F + sptr[w] * 0.5F;
00174         ++sptr;
00175       }
00176 
00177   // last points ( [ 1^ (2) 1<] / 4 )^T
00178   sptrh += w*h-1;//go to the last point in the image
00179   for (int i = 0; i < w; i ++)
00180     {
00181       *dptr++ = (sptr[0] + sptrh[0]) * 0.25F + sptr[w] * 0.5F;
00182       ++sptr;
00183       --sptrh;
00184     }
00185 
00186   // finished. here, sptr is one line before the end of array.
00187   return result;
00188 }
00189 
00190 // ######################################################################
00191 template <class T_or_RGB>
00192 Image<typename promote_trait<T_or_RGB, float>::TP>
00193 lowPassLpt5(const Image<T_or_RGB>& src, BorderPolicy policy)
00194 {
00195   if (policy == CROSS_HEMI)
00196     return lowPassLpt5w(lowPass5x(src));
00197   else if (policy == SEPARATE_HEMI)
00198     return lowPass5y(lowPassLpt5r(src));
00199   else
00200     return lowPassLpt5w(lowPassLpt5r(src));
00201 }
00202 
00203 // ######################################################################
00204 template <class T_or_RGB> // Anderson's separable kernel: 1/16 * [1 4 6 4 1]
00205 Image<typename promote_trait<T_or_RGB, float>::TP>
00206 lowPassLpt5r(const Image<T_or_RGB>& src)
00207 {
00208   //this operator really only makes sense on even width images but
00209   //since it will still work we wont explicity disallow it.
00210 GVX_TRACE(__PRETTY_FUNCTION__);
00211  const int w = src.getWidth(), h = src.getHeight(),
00212    hf = w/2, h2 = 2*h;
00213   // promote the source image to float if necessary, so that we do the
00214   // promotion only once for all, rather than many times as we access
00215   // the pixels of the image; if no promotion is necessary, "source"
00216   // will just point to the original data of "src" through the
00217   // copy-on-write/ref-counting behavior of Image:
00218   typedef typename promote_trait<T_or_RGB, float>::TP TF;
00219   const Image<TF> source = src;
00220   if (w < 4)
00221     return source; // nothing to smooth
00222   Image<TF> result(w, h, NO_INIT);
00223   typename Image<TF>::const_iterator sptr = source.begin();
00224   typename Image<TF>::iterator dptr = result.beginw();
00225 
00226   //Do not use access overloading since can
00227   // access the C array directly.  the bet is: float
00228   // computations are faster than int (true for most float
00229   // copros), and int2float convert is fast -> do not have to
00230   // divide by the coeff sum since we directly use float
00231   // coeffs.
00232   // notations: in () is the position of dest ptr, and ^ is src ptr
00233   // ########## horizontal pass
00234   for (int j = 0; j < h2; j ++)
00235     {
00236       // leftmost point  [ (6^) 4 1 ] / 11
00237       *dptr++ = sptr[0] * (6.0F / 11.0F) +
00238         sptr[1] * (4.0F / 11.0F) +
00239         sptr[2] * (1.0F / 11.0F);
00240 
00241       // second point    [ 4^ (6) 4 1 ] / 15
00242       *dptr++ = (sptr[0] + sptr[2]) * (4.0F / 15.0F) +
00243         sptr[1] * (6.0F / 15.0F) +
00244         sptr[3] * (1.0F / 15.0F);
00245 
00246       // rest of the line to vertical meridian  [ 1^ 4 (6) 4 1 ] / 16.0
00247       for (int i = 0; i < hf - 4; i ++)
00248         {
00249           *dptr++ = (sptr[0] + sptr[4]) * (1.0F / 16.0F) +
00250             (sptr[1] + sptr[3]) * (4.0F / 16.0F) +
00251             sptr[2]  * (6.0F / 16.0F);
00252           ++sptr;
00253         }
00254 
00255       // before last point [ 1^ 4 (6) 4 ] / 15
00256       *dptr++ = sptr[0] * (1.0F / 15.0F) +
00257         (sptr[1] + sptr[3]) * (4.0F / 15.0F) +
00258         sptr[2] * (6.0F / 15.0F);
00259       ++sptr;
00260 
00261       // last point [ 1^ 4 (6) ] / 11
00262       *dptr++ = sptr[0] * (1.0F / 11.0F) +
00263         sptr[1] * (4.0F / 11.0F) +
00264         sptr[2] * (6.0F / 11.0F);
00265       sptr += 3;  // sptr back to same position as dptr
00266     }
00267   return result;
00268 }
00269 
00270 // ######################################################################
00271 template <class T_or_RGB> // Anderson's separable kernel: 1/16 * [1 4 6 4 1]
00272 Image<typename promote_trait<T_or_RGB, float>::TP>
00273 lowPassLpt5w(const Image<T_or_RGB>& src)
00274 {
00275 GVX_TRACE(__PRETTY_FUNCTION__);
00276   const int w = src.getWidth(), h = src.getHeight();
00277   // promote the source image to float if necessary, so that we do the
00278   // promotion only once for all, rather than many times as we access
00279   // the pixels of the image; if no promotion is necessary, "source"
00280   // will just point to the original data of "src" through the
00281   // copy-on-write/ref-counting behavior of Image:
00282   typedef typename promote_trait<T_or_RGB, float>::TP TF;
00283   const Image<TF> source = src;
00284   if (h < 4)
00285     return source; // nothing to smooth
00286   Image<TF> result(w, h, NO_INIT);
00287   typename Image<TF>::const_iterator sptr = source.begin(),
00288     sptrh = source.begin()+w-1;//the last point in the first image row
00289   typename Image<TF>::iterator dptr = result.beginw();
00290 
00291   // ########## vertical pass  (even though we scan horiz for speedup)
00292   const int w2 = w * 2, w3 = w * 3, w4 = w * 4; // speedup
00293   //'<' symbol means opposite side of the image
00294   // topmost points  ( [1< 4< (6^) 4 1 ] / 16 )^T
00295   for (int i = 0; i < w; i ++)
00296     {
00297       *dptr++ = sptr[0] * (6.0F / 16.0F) +
00298         (sptr[w] + sptrh[0] ) * (4.0F / 16.0F) +
00299         (sptr[w2] + sptrh[w2] ) * (1.0F / 16.0F);
00300       ++sptr;
00301       --sptrh;
00302     }
00303   sptr -= w;  // go back to top-left
00304   sptrh += w;//go back to last point in first row
00305 
00306   // second topmost points  ( [1< 4^ (6) 4 1 ] / 16 )^T
00307   for (int i = 0; i < w; i ++)
00308     {
00309       *dptr++ = (sptr[0] + sptr[w2]) * (4.0F / 16.0F) +
00310         sptr[w] * (6.0F / 16.0F) +
00311         (sptr[w3] + sptrh[0]) * (1.0F / 16.0F);
00312       ++sptr;
00313       --sptrh;
00314     }
00315   sptr -= w;  // go back to top-left
00316 
00317   // rest of the column except last 2 points ( [ 1^ 4 (6) 4 1 ] / 16 )T
00318   for (int j = 0; j < h - 4; j ++)
00319     for (int i = 0; i < w; i ++)
00320       {
00321         *dptr++ = (sptr[ 0] + sptr[w4]) * (1.0F / 16.0F) +
00322           (sptr[ w] + sptr[w3]) * (4.0F / 16.0F) +
00323           sptr[w2]  * (6.0F / 16.0F);
00324         sptr++;
00325       }
00326 
00327   sptrh = source.end();//the last point in the image
00328   // before last points ( [ 1^ 4 (6) 4 1< ] / 16 )T
00329   for (int i = 0; i < w; i ++)
00330     {
00331       *dptr++ = (sptr[0] + sptrh[0]) * (1.0F / 16.0F) +
00332         (sptr[w] + sptr[w3]) * (4.0F / 16.0F) +
00333         sptr[w2] * (6.0F / 16.0F);
00334       ++sptr;
00335       --sptrh;
00336     }
00337   --sptrh;//how we are the last pixel in the second to last row.
00338   // last points ( [ 1^ 4 (6) 4< 1< ] / 16 )T
00339   for (int i = 0; i < w; i ++)
00340     {
00341       *dptr++ = (sptr[0] + sptrh[0]) * (1.0F / 16.0F) +
00342         (sptr[w] + sptrh[w]) * (4.0F / 16.0F) +
00343         sptr[w2] * (6.0F / 16.0F);
00344       ++sptr;
00345       --sptrh;
00346     }
00347   // finished. here, sptr is two lines before the end of array.
00348   return result;
00349 }
00350 
00351 // ######################################################################
00352 // Include the explicit instantiations
00353 // ######################################################################
00354 #include "inst/Image/LowPassLpt.I"
00355 
00356 template
00357 Image<promote_trait<double, float>::TP>
00358 lowPassLpt(const Image<double>& src, const uint taps,
00359            BorderPolicy policy);
00360 
00361 template
00362 Image<promote_trait<double, float>::TP>
00363 lowPassLpt3(const Image<double>& src, BorderPolicy policy);
00364 
00365 template
00366 Image<promote_trait<double, float>::TP>
00367 lowPassLpt3r(const Image<double>& src);
00368 
00369 template
00370 Image<promote_trait<double, float>::TP>
00371 lowPassLpt3w(const Image<double>& src);
00372 
00373 template
00374 Image<promote_trait<double, float>::TP>
00375 lowPassLpt5(const Image<double>& src, BorderPolicy policy);
00376 
00377 template
00378 Image<promote_trait<double, float>::TP>
00379 lowPassLpt5r(const Image<double>& src);
00380 
00381 template
00382 Image<promote_trait<double, float>::TP>
00383 lowPassLpt5w(const Image<double>& src);
00384 
00385 // ######################################################################
00386 /* So things look consistent in everyone's emacs... */
00387 /* Local Variables: */
00388 /* mode: c++ */
00389 /* indent-tabs-mode: nil */
00390 /* End: */
00391 
00392 #endif // IMAGE_LOWPASSLPT_C_DEFINED
Generated on Sun May 8 08:40:55 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3