00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #ifndef IMAGE_LOWPASS_C_DEFINED
00039 #define IMAGE_LOWPASS_C_DEFINED
00040 
00041 #include "Image/LowPass.H"
00042 
00043 #include "Image/Convolutions.H"
00044 #include "Image/Image.H"
00045 #include "Image/Kernels.H"
00046 #include "Image/Pixels.H"
00047 #include "rutz/trace.h"
00048 
00049 namespace
00050 {
00051   
00052   template <class T>
00053   T median3scalar(T a, T b, T c)
00054   {
00055     if (b < a) { T t = b; b = a; a = t; }
00056     if (c < b) { T t = c; c = b; b = t; }
00057     if (b < a) { T t = b; b = a; a = t; }
00058 
00059     return b;
00060   }
00061 
00062   
00063   template <class T>
00064   PixRGB<T> median3scalar(PixRGB<T> a, PixRGB<T> b, PixRGB<T> c)
00065   {
00066     return PixRGB<T>(median3scalar(a.p[0], b.p[0], c.p[0]),
00067                      median3scalar(a.p[1], b.p[1], c.p[1]),
00068                      median3scalar(a.p[2], b.p[2], c.p[2]));
00069   }
00070 
00071   Image<PixRGB<float> > lowPass3x_rgb(const Image<PixRGB<float> >& src)
00072   {
00073     const int w = src.getWidth(), h = src.getHeight();
00074     if (w < 2) return src; 
00075     Image<PixRGB<float> > result(w, h, NO_INIT);
00076     Image<PixRGB<float> >::const_iterator sptr = src.begin();
00077     Image<PixRGB<float> >::iterator dptr = result.beginw();
00078 
00079     
00080     
00081     
00082     
00083     
00084     
00085     
00086     for (int j = 0; j < h; j ++)
00087       {
00088         
00089         dptr->setRed(sptr[0].red() * (2.0F / 3.0F)
00090           + sptr[1].red() * (1.0F / 3.0F));
00091         dptr->setGreen(sptr[0].green() * (2.0F / 3.0F)
00092           + sptr[1].green() * (1.0F / 3.0F));
00093         dptr->setBlue(sptr[0].blue() * (2.0F / 3.0F)
00094           + sptr[1].blue() * (1.0F / 3.0F));
00095         ++dptr;
00096 
00097         
00098         for (int i = 0; i < w - 2; i ++)
00099           {
00100             dptr->setRed((sptr[0].red() + sptr[2].red())
00101               * 0.25F + sptr[1].red() * 0.5F);
00102             dptr->setGreen((sptr[0].green() + sptr[2].green())
00103               * 0.25F + sptr[1].green() * 0.5F);
00104             dptr->setBlue((sptr[0].blue() + sptr[2].blue())
00105               * 0.25F + sptr[1].blue() * 0.5F);
00106             ++dptr;
00107             ++sptr;
00108           }
00109 
00110         
00111         dptr->setRed(sptr[0].red() * (1.0F / 3.0f)
00112           + sptr[1].red() * (2.0F / 3.0F));
00113         dptr->setGreen(sptr[0].green() * (1.0F / 3.0f)
00114           + sptr[1].green() * (2.0F / 3.0F));
00115         dptr->setBlue(sptr[0].blue() * (1.0F / 3.0f)
00116           + sptr[1].blue() * (2.0F / 3.0F));
00117         ++dptr;
00118         sptr += 2;  
00119       }
00120     return result;
00121   }
00122 
00123   Image<PixRGB<float> > lowPass3y_rgb(const Image<PixRGB<float> >& src)
00124   {
00125     const int w = src.getWidth(), h = src.getHeight();
00126     if (h < 2) return src; 
00127     Image<PixRGB<float> > result(w, h, NO_INIT);
00128     Image<PixRGB<float> >::const_iterator sptr = src.begin();
00129     Image<PixRGB<float> >::iterator dptr = result.beginw();
00130     const int w2 = w * 2; 
00131 
00132     
00133     
00134     for (int i = 0; i < w; i ++)
00135       {
00136         
00137         dptr->setRed(sptr[0].red() * (2.0F / 3.0F)
00138           + sptr[w].red() * (1.0F / 3.0F));
00139         dptr->setGreen(sptr[0].green() * (2.0F / 3.0F)
00140           + sptr[w].green() * (1.0F / 3.0F));
00141         dptr->setBlue(sptr[0].blue() * (2.0F / 3.0F)
00142           + sptr[w].blue() * (1.0F / 3.0F));
00143         ++dptr;
00144         ++sptr;
00145       }
00146     sptr -= w;  
00147 
00148     
00149     for (int j = 0; j < h - 2; j ++)
00150       for (int i = 0; i < w; i ++)
00151         {
00152           
00153           dptr->setRed((sptr[0].red() + sptr[w2].red())
00154             * 0.25F + sptr[w].red() * 0.5F);
00155           dptr->setGreen((sptr[0].green() + sptr[w2].green())
00156             * 0.25F + sptr[w].green() * 0.5F);
00157           dptr->setBlue((sptr[0].blue() + sptr[w2].blue())
00158             * 0.25F + sptr[w].blue() * 0.5F);
00159           ++dptr;
00160           ++sptr;
00161         }
00162 
00163     
00164     for (int i = 0; i < w; i ++)
00165       {
00166         
00167         dptr->setRed(sptr[0].red() * (1.0F / 3.0F) + sptr[w].red()
00168           * (2.0F / 3.0F));
00169         dptr->setGreen(sptr[0].green() * (1.0F / 3.0F) + sptr[w].green()
00170           * (2.0F / 3.0F));
00171         dptr->setBlue(sptr[0].blue() * (1.0F / 3.0F) + sptr[w].blue()
00172           * (2.0F / 3.0F));
00173         ++dptr;
00174         ++sptr;
00175       }
00176 
00177     
00178     return result;
00179   }
00180 }
00181 
00182 
00183 template <>
00184 Image<promote_trait<PixRGB<float>, float>::TP>
00185 lowPass3x(const Image<PixRGB<float> >& src)
00186 {
00187 GVX_TRACE(__PRETTY_FUNCTION__);
00188   return lowPass3x_rgb(src);
00189 }
00190 
00191 
00192 template <class T>
00193 Image<typename promote_trait<T, float>::TP>
00194 lowPass3x(const Image<T>& src)
00195 {
00196 GVX_TRACE(__PRETTY_FUNCTION__);
00197   const int w = src.getWidth(), h = src.getHeight();
00198   
00199   
00200   
00201   
00202   
00203   typedef typename promote_trait<T, float>::TP TF;
00204   const Image<TF> source = src;
00205   if (w < 2) return source; 
00206   Image<TF> result(w, h, NO_INIT);
00207   typename Image<TF>::const_iterator sptr = source.begin();
00208   typename Image<TF>::iterator dptr = result.beginw();
00209 
00210   
00211   
00212   
00213   
00214   
00215   
00216   
00217   for (int j = 0; j < h; j ++)
00218     {
00219       
00220       *dptr++ = sptr[0] * (2.0F / 3.0F) + sptr[1] * (1.0F / 3.0F);
00221 
00222       
00223       for (int i = 0; i < w - 2; i ++)
00224         {
00225           *dptr++ = (sptr[0] + sptr[2]) * 0.25F + sptr[1] * 0.5F;
00226           sptr++;
00227         }
00228 
00229       
00230       *dptr++ = sptr[0] * (1.0F / 3.0F) + sptr[1] * (2.0F / 3.0F);
00231       sptr += 2;  
00232     }
00233   return result;
00234 }
00235 
00236 
00237 template <>
00238 Image<promote_trait<PixRGB<float>, float>::TP>
00239 lowPass3y(const Image<PixRGB<float> >& src)
00240 {
00241 GVX_TRACE(__PRETTY_FUNCTION__);
00242   return lowPass3y_rgb(src);
00243 }
00244 
00245 
00246 template <class T>
00247 Image<typename promote_trait<T, float>::TP>
00248 lowPass3y(const Image<T>& src)
00249 {
00250 GVX_TRACE(__PRETTY_FUNCTION__);
00251   const int w = src.getWidth(), h = src.getHeight();
00252   
00253   
00254   
00255   
00256   
00257   typedef typename promote_trait<T, float>::TP TF;
00258   const Image<TF> source = src;
00259   if (h < 2) return source; 
00260   Image<TF> result(w, h, NO_INIT);
00261   typename Image<TF>::const_iterator sptr = source.begin();
00262   typename Image<TF>::iterator dptr = result.beginw();
00263   const int w2 = w * 2; 
00264 
00265   
00266   
00267   for (int i = 0; i < w; i ++)
00268     {
00269       *dptr++ = sptr[0] * (2.0F / 3.0F) + sptr[w] * (1.0F / 3.0F);
00270       sptr++;
00271     }
00272   sptr -= w;  
00273 
00274   
00275   for (int j = 0; j < h - 2; j ++)
00276     for (int i = 0; i < w; i ++)
00277       {
00278         *dptr++ = (sptr[0] + sptr[w2]) * 0.25F + sptr[w] * 0.5F;
00279         sptr++;
00280       }
00281 
00282   
00283   for (int i = 0; i < w; i ++)
00284     {
00285       *dptr++ = sptr[0] * (1.0F / 3.0F) + sptr[w] * (2.0F / 3.0F);
00286       sptr++;
00287     }
00288 
00289   
00290   return result;
00291 }
00292 
00293 
00294 template <class T> 
00295 Image<typename promote_trait<T, float>::TP>
00296 lowPass5x(const Image<T>& src)
00297 {
00298 GVX_TRACE(__PRETTY_FUNCTION__);
00299   const int w = src.getWidth(), h = src.getHeight();
00300   
00301   
00302   
00303   
00304   
00305   typedef typename promote_trait<T, float>::TP TF;
00306   const Image<TF> source = src;
00307   if (w < 2) return source; 
00308   Image<TF> result(w, h, NO_INIT);
00309   typename Image<TF>::const_iterator sptr = source.begin();
00310   typename Image<TF>::iterator dptr = result.beginw();
00311 
00312   if (w == 2) 
00313     for (int j = 0; j < h; j ++)
00314       {
00315         
00316         *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[1] * (4.0F / 10.0F);
00317 
00318         
00319         *dptr++ = sptr[0] * (4.0F / 10.0F) + sptr[1] * (6.0F / 10.0F);
00320 
00321         sptr += 2;  
00322       }
00323   else if (w == 3) 
00324     for (int j = 0; j < h; j ++)
00325       {
00326         
00327         *dptr++ = sptr[0] * (6.0F / 11.0F) +
00328           sptr[1] * (4.0F / 11.0F) +
00329           sptr[2] * (1.0F / 11.0F);
00330 
00331         
00332         *dptr++ = (sptr[0] + sptr[2]) * (4.0F / 14.0F) +
00333           sptr[1] * (6.0F / 14.0F);
00334 
00335         
00336         *dptr++ = sptr[0] * (1.0F / 11.0F) +
00337           sptr[1] * (4.0F / 11.0F) +
00338           sptr[2] * (6.0F / 11.0F);
00339 
00340         sptr += 3;  
00341       }
00342   else  
00343         
00344         
00345         
00346         
00347         
00348         
00349         
00350         
00351         
00352     for (int j = 0; j < h; j ++)
00353       {
00354         
00355         *dptr++ = sptr[0] * (6.0F / 11.0F) +
00356           sptr[1] * (4.0F / 11.0F) +
00357           sptr[2] * (1.0F / 11.0F);
00358 
00359         
00360         *dptr++ = (sptr[0] + sptr[2]) * (4.0F / 15.0F) +
00361           sptr[1] * (6.0F / 15.0F) +
00362           sptr[3] * (1.0F / 15.0F);
00363 
00364         
00365         for (int i = 0; i < w - 4; i ++)
00366           {
00367             *dptr++ = (sptr[0] + sptr[4]) * (1.0F / 16.0F) +
00368               (sptr[1] + sptr[3]) * (4.0F / 16.0F) +
00369               sptr[2]  * (6.0F / 16.0F);
00370             sptr++;
00371           }
00372 
00373         
00374         *dptr++ = sptr[0] * (1.0F / 15.0F) +
00375           (sptr[1] + sptr[3]) * (4.0F / 15.0F) +
00376           sptr[2] * (6.0F / 15.0F);
00377         sptr++;
00378 
00379         
00380         *dptr++ = sptr[0] * (1.0F / 11.0F) +
00381           sptr[1] * (4.0F / 11.0F) +
00382           sptr[2] * (6.0F / 11.0F);
00383         sptr += 3;  
00384       }
00385   return result;
00386 }
00387 
00388 
00389 template <class T> 
00390 Image<typename promote_trait<T, float>::TP>
00391 lowPass5y(const Image<T>& src)
00392 {
00393 GVX_TRACE(__PRETTY_FUNCTION__);
00394   const int w = src.getWidth(), h = src.getHeight();
00395   
00396   
00397   
00398   
00399   
00400   typedef typename promote_trait<T, float>::TP TF;
00401   const Image<TF> source = src;
00402   if (h < 2) return source; 
00403   Image<TF> result(w, h, NO_INIT);
00404   typename Image<TF>::const_iterator sptr = source.begin();
00405   typename Image<TF>::iterator dptr = result.beginw();
00406 
00407   
00408   const int w2 = w * 2, w3 = w * 3, w4 = w * 4; 
00409 
00410   if (h == 2) 
00411     {
00412       
00413       for (int i = 0; i < w; i ++)
00414         {
00415           *dptr++ = sptr[0] * (6.0F / 10.0F) +
00416             sptr[w] * (4.0F / 10.0F);
00417           sptr++;
00418         }
00419       sptr -= w;  
00420 
00421       
00422       for (int i = 0; i < w; i ++)
00423         {
00424           *dptr++ = sptr[0] * (4.0F / 10.0F) +
00425             sptr[w] * (6.0F / 10.0F);
00426           sptr++;
00427         }
00428     }
00429   else if (h == 3) 
00430     {
00431       
00432       for (int i = 0; i < w; i ++)
00433         {
00434           *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00435             sptr[ w] * (4.0F / 11.0F) +
00436             sptr[w2] * (1.0F / 11.0F);
00437           sptr++;
00438         }
00439       sptr -= w;  
00440 
00441       
00442       for (int i = 0; i < w; i ++)
00443         {
00444           *dptr++ = (sptr[ 0] + sptr[w2]) * (4.0F / 14.0F) +
00445             sptr[ w] * (6.0F / 14.0F);
00446           sptr++;
00447         }
00448       sptr -= w;  
00449 
00450       
00451       for (int i = 0; i < w; i ++)
00452         {
00453           *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00454             sptr[ w] * (4.0F / 11.0F) +
00455             sptr[w2] * (6.0F / 11.0F);
00456           sptr++;
00457         }
00458     }
00459   else  
00460     {
00461       
00462       for (int i = 0; i < w; i ++)
00463         {
00464           *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00465             sptr[ w] * (4.0F / 11.0F) +
00466             sptr[w2] * (1.0F / 11.0F);
00467           sptr++;
00468         }
00469       sptr -= w;  
00470 
00471       
00472       for (int i = 0; i < w; i ++)
00473         {
00474           *dptr++ = (sptr[ 0] + sptr[w2]) * (4.0F / 15.0F) +
00475             sptr[ w] * (6.0F / 15.0F) +
00476             sptr[w3] * (1.0F / 15.0F);
00477           sptr++;
00478         }
00479       sptr -= w;  
00480 
00481       
00482       for (int j = 0; j < h - 4; j ++)
00483         for (int i = 0; i < w; i ++)
00484           {
00485             *dptr++ = (sptr[ 0] + sptr[w4]) * (1.0F / 16.0F) +
00486               (sptr[ w] + sptr[w3]) * (4.0F / 16.0F) +
00487               sptr[w2]  * (6.0F / 16.0F);
00488             sptr++;
00489           }
00490 
00491       
00492       for (int i = 0; i < w; i ++)
00493         {
00494           *dptr++ = sptr[ 0] * (1.0F / 15.0F) +
00495             (sptr[ w] + sptr[w3]) * (4.0F / 15.0F) +
00496             sptr[w2] * (6.0F / 15.0F);
00497           sptr++;
00498         }
00499 
00500       
00501       for (int i = 0; i < w; i ++)
00502         {
00503           *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00504             sptr[ w] * (4.0F / 11.0F) +
00505             sptr[w2] * (6.0F / 11.0F);
00506           sptr++;
00507         }
00508       
00509     }
00510   return result;
00511 }
00512 
00513 
00514 template <class T> 
00515 Image<typename promote_trait<T, float>::TP>
00516 lowPass5xDecX(const Image<T>& src, const int factor)
00517 {
00518 GVX_TRACE(__PRETTY_FUNCTION__);
00519   ASSERT(factor > 0);
00520 
00521   
00522   if (factor == 1) return lowPass5x(src);
00523 
00524   
00525   const int w = src.getWidth(), h = src.getHeight();
00526   int w2 = w / factor;
00527   if (w2 == 0) w2 = 1; 
00528 
00529   
00530   
00531   
00532   
00533   
00534   typedef typename promote_trait<T, float>::TP TF;
00535   const Image<TF> source = src;
00536   if (w < 2) return source; 
00537 
00538   Image<TF> result(w2, h, NO_INIT);
00539   typename Image<TF>::const_iterator sptr = source.begin();
00540   typename Image<TF>::iterator dptr = result.beginw();
00541 
00542   if (w == 2) 
00543     for (int j = 0; j < h; j ++)
00544       {
00545         
00546         *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[1] * (4.0F / 10.0F);
00547 
00548         sptr += 2;  
00549       }
00550   else if (w == 3) 
00551     for (int j = 0; j < h; j ++)
00552       {
00553         
00554         
00555         *dptr++ = sptr[0] * (6.0F / 11.0F) +
00556           sptr[1] * (4.0F / 11.0F) +
00557           sptr[2] * (1.0F / 11.0F);
00558 
00559         
00560 
00561         sptr += 3;  
00562       }
00563   else  
00564         
00565         
00566         
00567         
00568         
00569         
00570         
00571         
00572         
00573     for (int j = 0; j < h; j ++)
00574       {
00575         int i1 = 0, i2 = 0;
00576         typename Image<TF>::const_iterator sptr2 = sptr;
00577 
00578 
00579         
00580         *dptr++ = sptr2[0] * (6.0F / 11.0F) +
00581           sptr2[1] * (4.0F / 11.0F) +
00582           sptr2[2] * (1.0F / 11.0F);
00583         ++i2;
00584         i1 += factor;
00585 
00586         
00587         sptr2 += (factor-2);
00588 
00589         
00590         while ((i1 < (w-2)) && (i2 < w2))
00591           {
00592             *dptr++ = (sptr2[0] + sptr2[4]) * (1.0F / 16.0F) +
00593               (sptr2[1] + sptr2[3]) * (4.0F / 16.0F) +
00594               sptr2[2]  * (6.0F / 16.0F);
00595             i1 += factor; sptr2 += factor;
00596             ++i2;
00597           }
00598 
00599         
00600         if ((i2 < w2) && (i1 == (w-2)))
00601           {
00602             sptr2 = sptr + w - 4;
00603             
00604             *dptr++ = sptr2[0] * (1.0F / 15.0F) +
00605               (sptr2[1] + sptr2[3]) * (4.0F / 15.0F) +
00606               sptr2[2] * (6.0F / 15.0F);
00607             i1 += factor;
00608             ++i2;
00609           }
00610 
00611         
00612         if ((i2 < w2) && (i1 == (w-1)))
00613           {
00614             sptr2 = sptr + w - 3;
00615             
00616             *dptr++ = sptr2[0] * (1.0F / 11.0F) +
00617               sptr2[1] * (4.0F / 11.0F) +
00618               sptr2[2] * (6.0F / 11.0F);
00619             ++i2;
00620           }
00621         sptr += w;
00622       }
00623   return result;
00624 }
00625 
00626 
00627 template <class T> 
00628 Image<typename promote_trait<T, float>::TP>
00629 lowPass5yDecY(const Image<T>& src, const int factor)
00630 {
00631 GVX_TRACE(__PRETTY_FUNCTION__);
00632   ASSERT(factor > 0);
00633 
00634   
00635   if (factor == 1) return lowPass5y(src);
00636 
00637   
00638   const int w = src.getWidth(), h = src.getHeight();
00639   int h2 = h / factor;
00640   if (h2 == 0) h2 = 1; 
00641 
00642   
00643   
00644   
00645   
00646   
00647   typedef typename promote_trait<T, float>::TP TF;
00648   const Image<TF> source = src;
00649   if (h < 2) return source; 
00650 
00651   Image<TF> result(w, h2, NO_INIT);
00652   typename Image<TF>::const_iterator sptr = source.begin();
00653   typename Image<TF>::iterator dptr = result.beginw();
00654 
00655   
00656   const int w2 = w * 2, w3 = w * 3, w4 = w * 4; 
00657 
00658   if (h == 2) 
00659     {
00660       
00661       for (int i = 0; i < w; i ++)
00662         {
00663           *dptr++ = sptr[0] * (6.0F / 10.0F) + sptr[w] * (4.0F / 10.0F);
00664           sptr++;
00665         }
00666       sptr -= w;  
00667     }
00668   else if (h == 3) 
00669     {
00670       
00671       for (int i = 0; i < w; i ++)
00672         {
00673           *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00674             sptr[ w] * (4.0F / 11.0F) +
00675             sptr[w2] * (1.0F / 11.0F);
00676           sptr++;
00677         }
00678       sptr -= w;  
00679 
00680       
00681     }
00682   else  
00683     {
00684       int i1 = 0, i2 = 0;
00685       const int skip = (factor - 1) * w;
00686 
00687       
00688       for (int i = 0; i < w; i ++)
00689         {
00690           *dptr++ = sptr[ 0] * (6.0F / 11.0F) +
00691             sptr[ w] * (4.0F / 11.0F) +
00692             sptr[w2] * (1.0F / 11.0F);
00693           sptr++;
00694         }
00695       sptr -= w;  
00696       ++i2;
00697       i1 += factor;
00698 
00699       
00700       sptr += (skip - w);
00701 
00702       
00703       while((i1 < (h-2)) && (i2 < h2))
00704         {
00705           for (int i = 0; i < w; i ++)
00706             {
00707               *dptr++ = (sptr[ 0] + sptr[w4]) * (1.0F / 16.0F) +
00708                 (sptr[ w] + sptr[w3]) * (4.0F / 16.0F) +
00709                 sptr[w2]  * (6.0F / 16.0F);
00710               sptr++;
00711             }
00712           sptr += skip;
00713           i1 += factor;
00714           ++ i2;
00715         }
00716 
00717       
00718       if ((i2 < h2) && (i1 == (h-2)))
00719         {
00720           sptr = source.end() - w4;
00721           
00722           for (int i = 0; i < w; i ++)
00723             {
00724               *dptr++ = sptr[ 0] * (1.0F / 15.0F) +
00725                 (sptr[ w] + sptr[w3]) * (4.0F / 15.0F) +
00726                 sptr[w2] * (6.0F / 15.0F);
00727               sptr++;
00728             }
00729           i1 += factor;
00730           ++i2;
00731         }
00732 
00733       
00734       if ((i2 < h2) && (i1 == (h-1)))
00735         {
00736           sptr = source.end() - w3;
00737           
00738           for (int i = 0; i < w; i ++)
00739             {
00740               *dptr++ = sptr[ 0] * (1.0F / 11.0F) +
00741                 sptr[ w] * (4.0F / 11.0F) +
00742                 sptr[w2] * (6.0F / 11.0F);
00743               sptr++;
00744             }
00745         }
00746     }
00747   return result;
00748 }
00749 
00750 
00751 template <class T>
00752 Image<typename promote_trait<T, float>::TP>
00753 lowPass9x(const Image<T>& src)
00754 {
00755 GVX_TRACE(__PRETTY_FUNCTION__);
00756   const int w = src.getWidth(), h = src.getHeight();
00757   
00758   
00759   
00760   
00761   
00762   typedef typename promote_trait<T, float>::TP TF;
00763   const Image<TF> source = src;
00764   if (w < 2) return source; 
00765   Image<TF> result(w, h, NO_INIT);
00766   typename Image<TF>::const_iterator sptr = source.begin();
00767   typename Image<TF>::iterator dptr = result.beginw();
00768 
00769   if (w < 9)  
00770     {
00771       float kernel[9] = { 1.0F / 256.0F, 8.0F / 256.0F, 28.0F / 256.0F,
00772                           56.0F / 256.0F, 70.0F / 256.0F, 56.0F / 256.0F,
00773                           28.0F / 256.0F, 8.0F / 256.0F, 1.0F / 256.0F };
00774       return sepFilter(src, kernel, NULL, 9, 0,
00775                        CONV_BOUNDARY_CLEAN);
00776     }
00777 
00778   
00779   for (int j = 0; j < h; j ++)
00780     {
00781       
00782       *dptr++ = sptr[0] * (70.0F / 163.0F) +
00783         sptr[1] * (56.0F / 163.0F) +
00784         sptr[2] * (28.0F / 163.0F) +
00785         sptr[3] * ( 8.0F / 163.0F) +
00786         sptr[4] * ( 1.0F / 163.0F);
00787       *dptr++ = (sptr[0] + sptr[2]) * (56.0F / 219.0F) +
00788         sptr[1] * (70.0F / 219.0F) +
00789         sptr[3] * (28.0F / 219.0F) +
00790         sptr[4] * ( 8.0F / 219.0F) +
00791         sptr[5] * ( 1.0F / 219.0F);
00792       *dptr++ = (sptr[0] + sptr[4]) * (28.0F / 247.0F) +
00793         (sptr[1] + sptr[3]) * (56.0F / 247.0F) +
00794         sptr[2] * (70.0F / 247.0F) +
00795         sptr[5] * ( 8.0F / 247.0F) +
00796         sptr[6] * ( 1.0F / 247.0F);
00797       *dptr++ = (sptr[0] + sptr[6]) * ( 8.0F / 255.0F) +
00798         (sptr[1] + sptr[5]) * (28.0F / 255.0F) +
00799         (sptr[2] + sptr[4]) * (56.0F / 255.0F) +
00800         sptr[3] * (70.0F / 255.0F) +
00801         sptr[7] * ( 1.0F / 255.0F);
00802 
00803       
00804       for (int i = 0; i < w - 8; i ++)
00805         {
00806           *dptr++ = (sptr[0] + sptr[8]) * ( 1.0F / 256.0F) +
00807             (sptr[1] + sptr[7]) * ( 8.0F / 256.0F) +
00808             (sptr[2] + sptr[6]) * (28.0F / 256.0F) +
00809             (sptr[3] + sptr[5]) * (56.0F / 256.0F) +
00810             sptr[4] * (70.0F / 256.0F);
00811           sptr ++;
00812         }
00813 
00814       
00815       *dptr++ = sptr[0] * ( 1.0F / 255.0F) +
00816         (sptr[1] + sptr[7]) * ( 8.0F / 255.0F) +
00817         (sptr[2] + sptr[6]) * (28.0F / 255.0F) +
00818         (sptr[3] + sptr[5]) * (56.0F / 255.0F) +
00819         sptr[4] * (70.0F / 255.0F);
00820       sptr ++;
00821       *dptr++ = sptr[0] * ( 1.0F / 247.0F) +
00822         sptr[1] * ( 8.0F / 247.0F) +
00823         (sptr[2] + sptr[6]) * (28.0F / 247.0F) +
00824         (sptr[3] + sptr[5]) * (56.0F / 247.0F) +
00825         sptr[4] * (70.0F / 247.0F);
00826       sptr ++;
00827       *dptr++ = sptr[0] * ( 1.0F / 219.0F) +
00828         sptr[1] * ( 8.0F / 219.0F) +
00829         sptr[2] * (28.0F / 219.0F) +
00830         (sptr[3] + sptr[5]) * (56.0F / 219.0F) +
00831         sptr[4] * (70.0F / 219.0F);
00832       sptr ++;
00833       *dptr++ = sptr[0] * ( 1.0F / 163.0F) +
00834         sptr[1] * ( 8.0F / 163.0F) +
00835         sptr[2] * (28.0F / 163.0F) +
00836         sptr[3] * (56.0F / 163.0F) +
00837         sptr[4] * (70.0F / 163.0F);
00838       sptr += 5;  
00839     }
00840   return result;
00841 }
00842 
00843 
00844 template <class T>
00845 Image<typename promote_trait<T, float>::TP>
00846 lowPass9y(const Image<T>& src)
00847 {
00848 GVX_TRACE(__PRETTY_FUNCTION__);
00849   const int w = src.getWidth(), h = src.getHeight();
00850   
00851   
00852   
00853   
00854   
00855   typedef typename promote_trait<T, float>::TP TF;
00856   const Image<TF> source = src;
00857   if (h < 2) return source; 
00858   Image<TF> result(w, h, NO_INIT);
00859   typename Image<TF>::const_iterator sptr = source.begin();
00860   typename Image<TF>::iterator dptr = result.beginw();
00861 
00862   if (h < 9)  
00863     {
00864       float kernel[9] = { 1.0F / 256.0F, 8.0F / 256.0F, 28.0F / 256.0F,
00865                           56.0F / 256.0F, 70.0F / 256.0F, 56.0F / 256.0F,
00866                           28.0F / 256.0F, 8.0F / 256.0F, 1.0F / 256.0F };
00867       return sepFilter(src, NULL, kernel, 0, 9,
00868                        CONV_BOUNDARY_CLEAN);
00869     }
00870 
00871   
00872   const int w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w,
00873     w7 = w6 + w,  w8 = w7 + w;  
00874   for (int i = 0; i < w; i ++)
00875     {
00876       *dptr++ = sptr[ 0] * (70.0F / 163.0F) +
00877         sptr[ w] * (56.0F / 163.0F) +
00878         sptr[w2] * (28.0F / 163.0F) +
00879         sptr[w3] * ( 8.0F / 163.0F) +
00880         sptr[w4] * ( 1.0F / 163.0F);
00881       sptr ++;
00882     }
00883   sptr -= w; 
00884   for (int i = 0; i < w; i ++)
00885     {
00886       *dptr++ = (sptr[ 0] + sptr[w2]) * (56.0F / 219.0F) +
00887         sptr[ w] * (70.0F / 219.0F) +
00888         sptr[w3] * (28.0F / 219.0F) +
00889         sptr[w4] * ( 8.0F / 219.0F) +
00890         sptr[w5] * ( 1.0F / 219.0F);
00891       sptr ++;
00892     }
00893   sptr -= w; 
00894   for (int i = 0; i < w; i ++)
00895     {
00896       *dptr++ = (sptr[ 0] + sptr[w4]) * (28.0F / 247.0F) +
00897         (sptr[ w] + sptr[w3]) * (56.0F / 247.0F) +
00898         sptr[w2] * (70.0F / 247.0F) +
00899         sptr[w5] * ( 8.0F / 247.0F) +
00900         sptr[w6] * ( 1.0F / 247.0F);
00901       sptr ++;
00902     }
00903   sptr -= w; 
00904   for (int i = 0; i < w; i ++)
00905     {
00906       *dptr++ = (sptr[ 0] + sptr[w6]) * ( 8.0F / 255.0F) +
00907         (sptr[ w] + sptr[w5]) * (28.0F / 255.0F) +
00908         (sptr[w2] + sptr[w4]) * (56.0F / 255.0F) +
00909         sptr[w3] * (70.0F / 255.0F) +
00910         sptr[w7] * ( 1.0F / 255.0F);
00911       sptr ++;
00912     }
00913   sptr -= w;   
00914   for (int j = 0; j < h - 8; j ++)
00915     for (int i = 0; i < w; i ++)
00916       {
00917         *dptr++ = (sptr[ 0] + sptr[w8]) * ( 1.0F / 256.0F) +
00918           (sptr[ w] + sptr[w7]) * ( 8.0F / 256.0F) +
00919           (sptr[w2] + sptr[w6]) * (28.0F / 256.0F) +
00920           (sptr[w3] + sptr[w5]) * (56.0F / 256.0F) +
00921           sptr[w4]  * (70.0F / 256.0F);
00922         sptr ++;
00923       }
00924   for (int i = 0; i < w; i ++)
00925     {
00926       *dptr++ = sptr[ 0] * ( 1.0F / 255.0F) +
00927         (sptr[ w] + sptr[w7]) * ( 8.0F / 255.0F) +
00928         (sptr[w2] + sptr[w6]) * (28.0F / 255.0F) +
00929         (sptr[w3] + sptr[w5]) * (56.0F / 255.0F) +
00930         sptr[w4] * (70.0F / 255.0F);
00931       sptr ++;
00932     }
00933   for (int i = 0; i < w; i ++)
00934     {
00935       *dptr++ = sptr[ 0] * ( 1.0F / 247.0F) +
00936         sptr[ w] * ( 8.0F / 247.0F) +
00937         (sptr[w2] + sptr[w6]) * (28.0F / 247.0F) +
00938         (sptr[w3] + sptr[w5]) * (56.0F / 247.0F) +
00939         sptr[w4] * (70.0F / 247.0F);
00940       sptr ++;
00941     }
00942   for (int i = 0; i < w; i ++)
00943     {
00944       *dptr++ = sptr[ 0] * ( 1.0F / 219.0F) +
00945         sptr[ w] * ( 8.0F / 219.0F) +
00946         sptr[w2] * (28.0F / 219.0F) +
00947         (sptr[w3] + sptr[w5]) * (56.0F / 219.0F) +
00948         sptr[w4] * (70.0F / 219.0F);
00949       sptr ++;
00950     }
00951   for (int i = 0; i < w; i ++)
00952     {
00953       *dptr++ = sptr[ 0] * ( 1.0F / 163.0F) +
00954         sptr[ w] * ( 8.0F / 163.0F) +
00955         sptr[w2] * (28.0F / 163.0F) +
00956         sptr[w3] * (56.0F / 163.0F) +
00957         sptr[w4] * (70.0F / 163.0F);
00958       sptr ++;
00959     }
00960   return result;
00961 }
00962 
00963 
00964 template <class T>
00965 Image<typename promote_trait<T, float>::TP>
00966 lowPass3(const Image<T>& src, const bool go_x, const bool go_y)
00967 {
00968   Image<typename promote_trait<T, float>::TP> result = src;
00969   if (go_x) result = lowPass3x(result);
00970   if (go_y) result = lowPass3y(result);
00971   return result;
00972 }
00973 
00974 
00975 template <class T>
00976 Image<typename promote_trait<T, float>::TP>
00977 lowPass5(const Image<T>& src, const bool go_x, const bool go_y)
00978 {
00979   Image<typename promote_trait<T, float>::TP> result = src;
00980   if (go_x) result = lowPass5x(result);
00981   if (go_y) result = lowPass5y(result);
00982   return result;
00983 }
00984 
00985 
00986 template <class T>
00987 Image<typename promote_trait<T, float>::TP>
00988 lowPass9(const Image<T>& src, const bool go_x, const bool go_y)
00989 {
00990   Image<typename promote_trait<T, float>::TP> result = src;
00991   if (go_x) result = lowPass9x(result);
00992   if (go_y) result = lowPass9y(result);
00993   return result;
00994 }
00995 
00996 
00997 template <class T>
00998 Image<typename promote_trait<T, float>::TP>
00999 lowPass(const int N, const Image<T>& src,
01000         const bool go_x = true, const bool go_y = true)
01001 {
01002   Image<typename promote_trait<T, float>::TP> result = src;
01003   if (go_x) result = lowPassX(N, result);
01004   if (go_y) result = lowPassY(N, result);
01005   return result;
01006 }
01007 
01008 
01009 template <class T>
01010 Image<typename promote_trait<T, float>::TP>
01011 lowPassX(const int N, const Image<T>& src)
01012 {
01013 GVX_TRACE(__PRETTY_FUNCTION__);
01014   switch (N)
01015     {
01016     case 3: return lowPass3x(src);
01017     case 5: return lowPass5x(src);
01018     case 9: return lowPass9x(src);
01019     default: break;
01020     }
01021 
01022   const Image<float> kern = binomialKernel(N);
01023   ASSERT(kern.getWidth() == N);
01024   ASSERT(kern.getHeight() == 1);
01025   return sepFilter(src, kern.getArrayPtr(), NULL, N, 0,
01026                    CONV_BOUNDARY_CLEAN);
01027 }
01028 
01029 
01030 template <class T>
01031 Image<typename promote_trait<T, float>::TP>
01032 lowPassY(const int N, const Image<T>& src)
01033 {
01034 GVX_TRACE(__PRETTY_FUNCTION__);
01035   switch (N)
01036     {
01037     case 3: return lowPass3y(src);
01038     case 5: return lowPass5y(src);
01039     case 9: return lowPass9y(src);
01040     default: break;
01041     }
01042 
01043   const Image<float> kern = binomialKernel(N);
01044   ASSERT(kern.getWidth() == N);
01045   ASSERT(kern.getHeight() == 1);
01046   return sepFilter(src, NULL, kern.getArrayPtr(), 0, N,
01047                    CONV_BOUNDARY_CLEAN);
01048 }
01049 
01050 
01051 template <class T>
01052 Image<T> median3x(const Image<T>& in)
01053 {
01054   if (in.getWidth() < 3) return in;
01055 
01056   const int w = in.getWidth();
01057   const int h = in.getHeight();
01058 
01059   Image<T> result(in.getDims(), NO_INIT);
01060 
01061   typename Image<T>::const_iterator sptr = in.begin();
01062   typename Image<T>::iterator dptr = result.beginw();
01063 
01064   for (int y = 0; y < h; ++y)
01065     for (int x = 0; x < w; ++x)
01066       {
01067         if (x == 0 || x == w-1)
01068           *dptr = *sptr;
01069         else
01070           *dptr = median3scalar(sptr[-1], sptr[0], sptr[1]);
01071 
01072         ++dptr;
01073         ++sptr;
01074       }
01075 
01076   return result;
01077 }
01078 
01079 
01080 template <class T>
01081 Image<T> median3y(const Image<T>& in)
01082 {
01083   if (in.getHeight() < 3) return in;
01084 
01085   const int w = in.getWidth();
01086   const int h = in.getHeight();
01087 
01088   Image<T> result(in.getDims(), NO_INIT);
01089 
01090   typename Image<T>::const_iterator sptr = in.begin();
01091   typename Image<T>::iterator dptr = result.beginw();
01092 
01093   for (int y = 0; y < h; ++y)
01094     {
01095       if (y == 0 || y == h-1)
01096         for (int x = 0; x < w; ++x)
01097             *dptr++ = *sptr++;
01098       else
01099         for (int x = 0; x < w; ++x)
01100           {
01101             *dptr = median3scalar(sptr[-w], sptr[0], sptr[w]);
01102 
01103             ++dptr;
01104             ++sptr;
01105           }
01106     }
01107 
01108   return result;
01109 }
01110 
01111 
01112 template <class T>
01113 Image<T> median3(const Image<T>& in, bool go_x, bool go_y)
01114 {
01115   Image<T> result = in;
01116   if (go_x) result = median3x(result);
01117   if (go_y) result = median3y(result);
01118   return result;
01119 }
01120 
01121 
01122 template <class T>
01123 Image<typename promote_trait<T, float>::TP>
01124 convGauss(const Image<T>& src, const float sigmaX, const float sigmaY,
01125           const float threshperc)
01126 {
01127 GVX_TRACE(__PRETTY_FUNCTION__);
01128   Image<typename promote_trait<T, float>::TP> result = src;
01129   Image <float> kernel;
01130   if (sigmaX > 0.0)
01131     {
01132       kernel = gaussian<float>(0.0F, sigmaX, result.getWidth(),threshperc);
01133       result = sepFilter(result, kernel, Image<float>(),
01134                          CONV_BOUNDARY_CLEAN);
01135     }
01136   if (sigmaY > 0.0)
01137     {
01138       kernel = gaussian<float>(0.0F, sigmaY, src.getHeight(), threshperc);
01139       result = sepFilter(result, Image<float>(), kernel,
01140                          CONV_BOUNDARY_CLEAN);
01141     }
01142   return result;
01143 }
01144 
01145 
01146 #include "inst/Image/LowPass.I"
01147 
01148 template
01149 Image<promote_trait<double, float>::TP>
01150 lowPass3(const Image<double>& src, const bool, const bool);
01151 
01152 template
01153 Image<promote_trait<double, float>::TP>
01154 lowPass5(const Image<double>& src, const bool, const bool);
01155 
01156 template
01157 Image<promote_trait<double, float>::TP>
01158 lowPass3x(const Image<double>& src);
01159 
01160 template
01161 Image<promote_trait<double, float>::TP>
01162 lowPass3y(const Image<double>& src);
01163 
01164 template
01165 Image<promote_trait<double, float>::TP>
01166 lowPass5x(const Image<double>& src);
01167 
01168 template
01169 Image<promote_trait<double, float>::TP>
01170 lowPass5y(const Image<double>& src);
01171 
01172 
01173 
01174 
01175 
01176 
01177 
01178 
01179 #endif // IMAGE_LOWPASS_C_DEFINED