Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

vil_gauss_reduce.cxx

Go to the documentation of this file.
00001 // This is core/vil/algo/vil_gauss_reduce.cxx
00002 #include "vil_gauss_reduce.h"
00003 //:
00004 // \file
00005 // \brief Functions to smooth and sub-sample an image in one direction
00006 // \author Tim Cootes
00007 
00008 #include <vcl_cmath.h>
00009 #include <vcl_cassert.h>
00010 #include <vxl_config.h> // for vxl_byte
00011 #include <vnl/vnl_erf.h>
00012 #include <vnl/vnl_math.h>
00013 
00014 //: Smooth and subsample single plane src_im in x to produce dest_im
00015 //  Applies 1-5-8-5-1 filter in x, then samples
00016 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1] elements of dest
00017 
00018 VCL_DEFINE_SPECIALIZATION
00019 void vil_gauss_reduce_1plane(const vxl_byte* src_im,
00020                              unsigned src_ni, unsigned src_nj,
00021                              vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00022                              vxl_byte* dest_im,
00023                              vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00024 {
00025   vxl_byte* d_row = dest_im;
00026   const vxl_byte* s_row = src_im;
00027   vcl_ptrdiff_t sxs2 = s_x_step*2;
00028   unsigned ni2 = (src_ni-3)/2;
00029   for (unsigned y=0;y<src_nj;++y)
00030   {
00031     // Set first element of row
00032     *d_row = vnl_math_rnd(0.071f * s_row[sxs2]
00033                         + 0.357f * s_row[s_x_step]
00034                         + 0.572f * s_row[0]);
00035 
00036     vxl_byte * d = d_row + d_x_step;
00037     const vxl_byte* s = s_row + sxs2;
00038     for (unsigned x=0;x<ni2;++x)
00039     {
00040       *d = vnl_math_rnd(0.05*s[-sxs2]    + 0.05*s[sxs2]
00041                       + 0.25*s[-s_x_step]+ 0.25*s[s_x_step]
00042                       + 0.4*s[0]);
00043 
00044       d += d_x_step;
00045       s += sxs2;
00046     }
00047     // Set last elements of row
00048     *d = vnl_math_rnd(0.071f * s[-sxs2]
00049                     + 0.357f * s[-s_x_step]
00050                     + 0.572f * s[0]);
00051 
00052     d_row += d_y_step;
00053     s_row += s_y_step;
00054   }
00055 }
00056 
00057 //: Smooth and subsample single plane src_im in x to produce dest_im
00058 //  Applies 1-5-8-5-1 filter in x, then samples
00059 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1] elements of dest
00060 VCL_DEFINE_SPECIALIZATION
00061 void vil_gauss_reduce_1plane(const float* src_im,
00062                              unsigned src_ni, unsigned src_nj,
00063                              vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00064                              float* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00065 {
00066   float* d_row = dest_im;
00067   const float* s_row = src_im;
00068   vcl_ptrdiff_t sxs2 = s_x_step*2;
00069   unsigned ni2 = (src_ni-3)/2;
00070   for (unsigned y=0;y<src_nj;++y)
00071   {
00072     // Set first element of row
00073     *d_row =  0.071f * s_row[sxs2]
00074             + 0.357f * s_row[s_x_step]
00075             + 0.572f * s_row[0];
00076     float * d = d_row + d_x_step;
00077     const float* s = s_row + sxs2;
00078     for (unsigned x=0;x<ni2;++x)
00079     {
00080       *d =  0.05f*(s[-sxs2] + s[sxs2])
00081           + 0.25f*(s[-s_x_step]+ s[s_x_step])
00082           + 0.40f*s[0];
00083 
00084       d += d_x_step;
00085       s += sxs2;
00086     }
00087     // Set last elements of row
00088     *d =  0.071f * s[-sxs2]
00089         + 0.357f * s[-s_x_step]
00090         + 0.572f * s[0];
00091 
00092     d_row += d_y_step;
00093     s_row += s_y_step;
00094   }
00095 }
00096 
00097 
00098 //: Smooth and subsample single plane src_im in x to produce dest_im
00099 //  Applies 1-5-8-5-1 filter in x, then samples
00100 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1] elements of dest
00101 VCL_DEFINE_SPECIALIZATION
00102 void vil_gauss_reduce_1plane(const double* src_im,
00103                              unsigned src_ni, unsigned src_nj,
00104                              vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00105                              double* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00106 {
00107   double* d_row = dest_im;
00108   const double* s_row = src_im;
00109   vcl_ptrdiff_t sxs2 = s_x_step*2;
00110   unsigned ni2 = (src_ni-3)/2;
00111   for (unsigned y=0;y<src_nj;++y)
00112   {
00113     // Set first element of row
00114     *d_row =  0.071 * s_row[sxs2]
00115             + 0.357 * s_row[s_x_step]
00116             + 0.572 * s_row[0];
00117     double * d = d_row + d_x_step;
00118     const double* s = s_row + sxs2;
00119     for (unsigned x=0;x<ni2;++x)
00120     {
00121       *d =  0.05f*(s[-sxs2] + s[sxs2])
00122           + 0.25f*(s[-s_x_step]+ s[s_x_step])
00123           + 0.40f*s[0];
00124 
00125       d += d_x_step;
00126       s += sxs2;
00127     }
00128     // Set last elements of row
00129     *d =  0.071f * s[-sxs2]
00130         + 0.357f * s[-s_x_step]
00131         + 0.572f * s[0];
00132 
00133     d_row += d_y_step;
00134     s_row += s_y_step;
00135   }
00136 }
00137 
00138 //: Smooth and subsample single plane src_im in x to produce dest_im
00139 //  Applies 1-5-8-5-1 filter in x, then samples
00140 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1] elements of dest
00141 VCL_DEFINE_SPECIALIZATION
00142 void vil_gauss_reduce_1plane(const int* src_im,
00143                              unsigned src_ni, unsigned src_nj,
00144                              vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00145                              int* dest_im,
00146                              vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00147 {
00148   int* d_row = dest_im;
00149   const int* s_row = src_im;
00150   vcl_ptrdiff_t sxs2 = s_x_step*2;
00151   unsigned ni2 = (src_ni-3)/2;
00152   for (unsigned y=0;y<src_nj;++y)
00153   {
00154     // Set first element of row
00155     *d_row = vnl_math_rnd(0.071f * s_row[sxs2]
00156                         + 0.357f * s_row[s_x_step]
00157                         + 0.572f * s_row[0]);
00158 
00159     int * d = d_row + d_x_step;
00160     const int* s = s_row + sxs2;
00161     for (unsigned x=0;x<ni2;++x)
00162     {
00163       *d = vnl_math_rnd(0.05*s[-sxs2] + 0.25*s[-s_x_step] +
00164                         0.05*s[ sxs2] + 0.25*s[ s_x_step] +
00165                         0.4 *s[0]);
00166 
00167       d += d_x_step;
00168       s += sxs2;
00169     }
00170     // Set last elements of row
00171     *d = vnl_math_rnd(0.071f * s[-sxs2]
00172                     + 0.357f * s[-s_x_step]
00173                     + 0.572f * s[0]);
00174 
00175     d_row += d_y_step;
00176     s_row += s_y_step;
00177   }
00178 }
00179 
00180 //: Smooth and subsample single plane src_im in x to produce dest_im
00181 //  Applies 1-5-8-5-1 filter in x, then samples
00182 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1] elements of dest
00183 VCL_DEFINE_SPECIALIZATION
00184 void vil_gauss_reduce_1plane(const vxl_int_16* src_im,
00185                              unsigned src_ni, unsigned src_nj,
00186                              vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00187                              vxl_int_16* dest_im,
00188                              vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00189 {
00190   vxl_int_16* d_row = dest_im;
00191   const vxl_int_16* s_row = src_im;
00192   vcl_ptrdiff_t sxs2 = s_x_step*2;
00193   unsigned ni2 = (src_ni-3)/2;
00194   for (unsigned y=0;y<src_nj;++y)
00195   {
00196     // Set first element of row
00197     *d_row = vnl_math_rnd(0.071f * s_row[sxs2]
00198                         + 0.357f * s_row[s_x_step]
00199                         + 0.572f * s_row[0]);
00200 
00201     vxl_int_16 * d = d_row + d_x_step;
00202     const vxl_int_16* s = s_row + sxs2;
00203     for (unsigned x=0;x<ni2;++x)
00204     {
00205       // The 0.5 offset in the following ensures rounding
00206       *d = vxl_int_16(0.5 + 0.05*s[-sxs2] + 0.25*s[-s_x_step]
00207                     + 0.05*s[ sxs2] + 0.25*s[ s_x_step]
00208                     + 0.4 *s[0]);
00209 
00210       d += d_x_step;
00211       s += sxs2;
00212     }
00213     // Set last elements of row
00214     *d = vnl_math_rnd(0.071f * s[-sxs2]
00215                     + 0.357f * s[-s_x_step]
00216                     + 0.572f * s[0]);
00217 
00218     d_row += d_y_step;
00219     s_row += s_y_step;
00220   }
00221 }
00222 
00223 //: Smooth and subsample single plane src_im in x, result is 2/3rd size
00224 //  Applies alternate 1-3-1, 1-1 filter in x, then samples
00225 //  every other pixel.  Fills [0,(2*ni+1)/3-1][0,nj-1] elements of dest
00226 //
00227 //  Note, 131 filter only an approximation
00228 VCL_DEFINE_SPECIALIZATION
00229 void vil_gauss_reduce_2_3_1plane(const float* src_im,
00230                                  unsigned src_ni, unsigned src_nj,
00231                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00232                                  float* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00233 {
00234   float* d_row = dest_im;
00235   const float* s_row = src_im;
00236   vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00237   unsigned d_ni = (2*src_ni+1)/3;
00238   unsigned d_ni2 = d_ni/2;
00239   for (unsigned y=0;y<src_nj;++y)
00240   {
00241     // Set first elements of row
00242     d_row[0]        = 0.75f*s_row[0] + 0.25f*s_row[s_x_step];
00243     d_row[d_x_step] = 0.5f*s_row[s_x_step] + 0.5f*s_row[sxs2];
00244     float * d = d_row + 2*d_x_step;
00245     const float* s = s_row + sxs3;
00246     for (unsigned x=1;x<d_ni2;++x)
00247     {
00248       *d = 0.2f*(s[-s_x_step] + s[s_x_step])+0.6f*s[0];
00249       d += d_x_step;
00250       *d = 0.5f*(s[s_x_step] + s[sxs2]);
00251       d += d_x_step;
00252       s += sxs3;
00253     }
00254     // Set last elements of row
00255     if (src_ni%3==1) *d=0.75f*s[-s_x_step] + 0.25f*s[0];
00256     else
00257     if (src_ni%3==2) *d=0.2f*(s[-s_x_step] + s[s_x_step])+0.6f*s[0];
00258 
00259     d_row += d_y_step;
00260     s_row += s_y_step;
00261   }
00262 }
00263 
00264 //: Smooth and subsample single plane src_im in x, result is 2/3rd size
00265 //  Applies alternate 1-3-1, 1-1 filter in x, then samples
00266 //  every other pixel.  Fills [0,(2*ni+1)/3-1][0,nj-1] elements of dest
00267 //
00268 //  Note, 131 filter only an approximation
00269 VCL_DEFINE_SPECIALIZATION
00270 void vil_gauss_reduce_2_3_1plane(const double* src_im,
00271                                  unsigned src_ni, unsigned src_nj,
00272                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00273                                  double* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00274 {
00275   double* d_row = dest_im;
00276   const double* s_row = src_im;
00277   vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00278   unsigned d_ni = (2*src_ni+1)/3;
00279   unsigned d_ni2 = d_ni/2;
00280   for (unsigned y=0;y<src_nj;++y)
00281   {
00282     // Set first elements of row
00283     d_row[0]        = 0.75*s_row[0] + 0.25*s_row[s_x_step];
00284     d_row[d_x_step] = 0.5*s_row[s_x_step] + 0.5*s_row[sxs2];
00285     double * d = d_row + 2*d_x_step;
00286     const double* s = s_row + sxs3;
00287     for (unsigned x=1;x<d_ni2;++x)
00288     {
00289       *d = 0.2*(s[-s_x_step] + s[s_x_step])+0.6*s[0];
00290       d += d_x_step;
00291       *d = 0.5*(s[s_x_step] + s[sxs2]);
00292       d += d_x_step;
00293       s += sxs3;
00294     }
00295     // Set last elements of row
00296     if (src_ni%3==1) *d=0.75*s[-s_x_step] + 0.25*s[0];
00297     else
00298     if (src_ni%3==2) *d=0.2*(s[-s_x_step] + s[s_x_step])+0.6*s[0];
00299 
00300     d_row += d_y_step;
00301     s_row += s_y_step;
00302   }
00303 }
00304 
00305 //: Smooth and subsample single plane src_im in x, result is 2/3rd size
00306 //  Applies alternate 1-3-1, 1-1 filter in x, then samples
00307 //  every other pixel.  Fills [0,(2*ni+1)/3-1][0,nj-1] elements of dest
00308 //
00309 //  Note, 131 filter only an approximation
00310 VCL_DEFINE_SPECIALIZATION
00311 void vil_gauss_reduce_2_3_1plane(const vxl_byte* src_im,
00312                                  unsigned src_ni, unsigned src_nj,
00313                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00314                                  vxl_byte* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00315 {
00316   vxl_byte* d_row = dest_im;
00317   const vxl_byte* s_row = src_im;
00318   vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00319   unsigned d_ni = (2*src_ni+1)/3;
00320   unsigned d_ni2 = d_ni/2;
00321   for (unsigned y=0;y<src_nj;++y)
00322   {
00323     // Set first elements of row
00324     // The 0.5 offset in the following ensures rounding
00325     d_row[0]        = vxl_byte(0.5f + 0.75f*s_row[0] + 0.25f*s_row[s_x_step]);
00326     d_row[d_x_step] = vxl_byte(0.5f + 0.5f*s_row[s_x_step] + 0.5f*s_row[sxs2]);
00327     vxl_byte * d = d_row + 2*d_x_step;
00328     const vxl_byte* s = s_row + sxs3;
00329     for (unsigned x=1;x<d_ni2;++x)
00330     {
00331       *d = vxl_byte(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00332       d += d_x_step;
00333       *d = vxl_byte(0.5f + 0.5f*(s[s_x_step]  + s[sxs2]));
00334       d += d_x_step;
00335       s += sxs3;
00336     }
00337     // Set last elements of row
00338     if (src_ni%3==1)
00339       *d = vxl_byte(0.5f + 0.75f*s[-s_x_step] + 0.25f*s[0]);
00340     else if (src_ni%3==2)
00341       *d = vxl_byte(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00342 
00343     d_row += d_y_step;
00344     s_row += s_y_step;
00345   }
00346 }
00347 
00348 
00349 //: Smooth and subsample single plane src_im in x, result is 2/3rd size
00350 //  Applies alternate 1-3-1, 1-1 filter in x, then samples
00351 //  every other pixel.  Fills [0,(2*ni+1)/3-1][0,nj-1] elements of dest
00352 //
00353 //  Note, 131 filter only an approximation
00354 VCL_DEFINE_SPECIALIZATION
00355 void vil_gauss_reduce_2_3_1plane(const int* src_im,
00356                                  unsigned src_ni, unsigned src_nj,
00357                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00358                                  int* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00359 {
00360   int* d_row = dest_im;
00361   const int* s_row = src_im;
00362   vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00363   unsigned d_ni = (2*src_ni+1)/3;
00364   unsigned d_ni2 = d_ni/2;
00365   for (unsigned y=0;y<src_nj;++y)
00366   {
00367     // Set first elements of row
00368     // The 0.5 offset in the following ensures rounding
00369     d_row[0]        = int(0.5f + 0.75f*s_row[0] + 0.25f*s_row[s_x_step]);
00370     d_row[d_x_step] = int(0.5f + 0.5f*s_row[s_x_step] + 0.5f*s_row[sxs2]);
00371     int * d = d_row + 2*d_x_step;
00372     const int* s = s_row + sxs3;
00373     for (unsigned x=1;x<d_ni2;++x)
00374     {
00375       *d = int(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00376       d += d_x_step;
00377       *d = int(0.5f + 0.5f*(s[s_x_step]  + s[sxs2]));
00378       d += d_x_step;
00379       s += sxs3;
00380     }
00381     // Set last elements of row
00382     if (src_ni%3==1)
00383       *d = int(0.5f + 0.75f*s[-s_x_step] + 0.25f*s[0]);
00384     else if (src_ni%3==2)
00385       *d = int(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00386 
00387     d_row += d_y_step;
00388     s_row += s_y_step;
00389   }
00390 }
00391 
00392 //: Smooth and subsample single plane src_im in x, result is 2/3rd size
00393 //  Applies alternate 1-3-1, 1-1 filter in x, then samples
00394 //  every other pixel.  Fills [0,(2*ni+1)/3-1][0,nj-1] elements of dest
00395 //
00396 //  Note, 131 filter only an approximation
00397 VCL_DEFINE_SPECIALIZATION
00398 void vil_gauss_reduce_2_3_1plane(const vxl_int_16* src_im,
00399                                  unsigned src_ni, unsigned src_nj,
00400                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00401                                  vxl_int_16* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00402 {
00403   vxl_int_16* d_row = dest_im;
00404   const vxl_int_16* s_row = src_im;
00405   vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00406   unsigned d_ni = (2*src_ni+1)/3;
00407   unsigned d_ni2 = d_ni/2;
00408   for (unsigned y=0;y<src_nj;++y)
00409   {
00410     // Set first elements of row
00411     // The 0.5 offset in the following ensures rounding
00412     d_row[0]        = vxl_int_16(0.5f + 0.75f*s_row[0] + 0.25f*s_row[s_x_step]);
00413     d_row[d_x_step] = vxl_int_16(0.5f + 0.5f*s_row[s_x_step] + 0.5f*s_row[sxs2]);
00414     vxl_int_16 * d = d_row + 2*d_x_step;
00415     const vxl_int_16* s = s_row + sxs3;
00416     for (unsigned x=1;x<d_ni2;++x)
00417     {
00418       *d = int(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00419       d += d_x_step;
00420       *d = int(0.5f + 0.5f*(s[s_x_step]  + s[sxs2]));
00421       d += d_x_step;
00422       s += sxs3;
00423     }
00424     // Set last elements of row
00425     if (src_ni%3==1)
00426       *d = vxl_int_16(0.5f + 0.75f*s[-s_x_step] + 0.25f*s[0]);
00427     else if (src_ni%3==2)
00428       *d = vxl_int_16(0.5f + 0.2f*(s[-s_x_step] + s[s_x_step]) + 0.6f*s[0]);
00429 
00430     d_row += d_y_step;
00431     s_row += s_y_step;
00432   }
00433 }
00434 
00435 //: Smooth and subsample single plane src_im in x to produce dest_im using 121 filter in x and y
00436 //  Smoothes with a 3x3 filter and subsamples
00437 VCL_DEFINE_SPECIALIZATION
00438 void vil_gauss_reduce_121_1plane(const vxl_byte* src_im,
00439                                  unsigned src_ni, unsigned src_nj,
00440                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00441                                  vxl_byte* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00442 {
00443   vcl_ptrdiff_t sxs2 = s_x_step*2;
00444   vcl_ptrdiff_t sys2 = s_y_step*2;
00445   vxl_byte* d_row = dest_im+d_y_step;
00446   const vxl_byte* s_row1 = src_im + s_y_step;
00447   const vxl_byte* s_row2 = s_row1 + s_y_step;
00448   const vxl_byte* s_row3 = s_row2 + s_y_step;
00449   unsigned ni2 = (src_ni-2)/2;
00450   unsigned nj2 = (src_nj-2)/2;
00451   for (unsigned y=0;y<nj2;++y)
00452   {
00453     // Set first element of row
00454     *d_row = *s_row2;
00455     vxl_byte * d = d_row + d_x_step;
00456     const vxl_byte* s1 = s_row1 + sxs2;
00457     const vxl_byte* s2 = s_row2 + sxs2;
00458     const vxl_byte* s3 = s_row3 + sxs2;
00459     for (unsigned x=0;x<ni2;++x)
00460     {
00461       // The following is a little inefficient - could group terms to reduce arithmetic
00462       // Add 0.5 so that truncating effectively rounds
00463       *d = vxl_byte( 0.0625f * s1[-s_x_step] + 0.125f * s1[0] + 0.0625f * s1[s_x_step]
00464                    + 0.1250f * s2[-s_x_step] + 0.250f * s2[0] + 0.1250f * s2[s_x_step]
00465                    + 0.0625f * s3[-s_x_step] + 0.125f * s3[0] + 0.0625f * s3[s_x_step] +0.5);
00466 
00467       d += d_x_step;
00468       s1 += sxs2;
00469       s2 += sxs2;
00470       s3 += sxs2;
00471     }
00472     // Set last elements of row
00473     if (src_ni&1)
00474       *d = *s2;
00475 
00476     d_row += d_y_step;
00477     s_row1 += sys2;
00478     s_row2 += sys2;
00479     s_row3 += sys2;
00480   }
00481 
00482   // Need to set first and last rows as well
00483 
00484   // Dest image should be (src_ni+1)/2 x (src_nj+1)/2
00485   const vxl_byte* s0 = src_im;
00486   unsigned ni=(src_ni+1)/2;
00487   for (unsigned i=0;i<ni;++i)
00488   {
00489     dest_im[i]= *s0;
00490     s0+=sxs2;
00491   }
00492 
00493   if (src_nj&1)
00494   {
00495     unsigned yhi = (src_nj-1)/2;
00496     vxl_byte* dest_last_row = dest_im + yhi*d_y_step;
00497     const vxl_byte* s_last = src_im + yhi*sys2;
00498     for (unsigned i=0;i<ni;++i)
00499     {
00500       dest_last_row[i]= *s_last;
00501       s_last+=sxs2;
00502     }
00503   }
00504 }
00505 
00506 
00507 //: Smooth and subsample single plane src_im in x to produce dest_im using 121 filter in x and y
00508 //  Smoothes with a 3x3 filter and subsamples
00509 VCL_DEFINE_SPECIALIZATION
00510 void vil_gauss_reduce_121_1plane(const float* src_im,
00511                                  unsigned src_ni, unsigned src_nj,
00512                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00513                                  float* dest_im,
00514                                  vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00515 {
00516   vcl_ptrdiff_t sxs2 = s_x_step*2;
00517   vcl_ptrdiff_t sys2 = s_y_step*2;
00518   float* d_row = dest_im+d_y_step;
00519   const float* s_row1 = src_im + s_y_step;
00520   const float* s_row2 = s_row1 + s_y_step;
00521   const float* s_row3 = s_row2 + s_y_step;
00522   unsigned ni2 = (src_ni-2)/2;
00523   unsigned nj2 = (src_nj-2)/2;
00524   for (unsigned y=0;y<nj2;++y)
00525   {
00526     // Set first element of row
00527     *d_row = *s_row2;
00528     float * d = d_row + d_x_step;
00529     const float* s1 = s_row1 + sxs2;
00530     const float* s2 = s_row2 + sxs2;
00531     const float* s3 = s_row3 + sxs2;
00532     for (unsigned x=0;x<ni2;++x)
00533     {
00534       // The following is a little inefficient - could group terms to reduce arithmetic
00535       *d =   0.0625f * s1[-s_x_step] + 0.125f * s1[0] + 0.0625f * s1[s_x_step]
00536            + 0.1250f * s2[-s_x_step] + 0.250f * s2[0] + 0.1250f * s2[s_x_step]
00537            + 0.0625f * s3[-s_x_step] + 0.125f * s3[0] + 0.0625f * s3[s_x_step];
00538 
00539       d += d_x_step;
00540       s1 += sxs2;
00541       s2 += sxs2;
00542       s3 += sxs2;
00543     }
00544     // Set last elements of row
00545     if (src_ni&1)
00546       *d = *s2;
00547 
00548     d_row += d_y_step;
00549     s_row1 += sys2;
00550     s_row2 += sys2;
00551     s_row3 += sys2;
00552   }
00553 
00554   // Need to set first and last rows as well
00555 
00556   // Dest image should be (src_ni+1)/2 x (src_nj+1)/2
00557   const float* s0 = src_im;
00558   unsigned ni=(src_ni+1)/2;
00559   for (unsigned i=0;i<ni;++i)
00560   {
00561     dest_im[i]= *s0;
00562     s0+=sxs2;
00563   }
00564 
00565   if (src_nj&1)
00566   {
00567     unsigned yhi = (src_nj-1)/2;
00568     float* dest_last_row = dest_im + yhi*d_y_step;
00569     const float* s_last = src_im + yhi*sys2;
00570     for (unsigned i=0;i<ni;++i)
00571     {
00572       dest_last_row[i]= *s_last;
00573       s_last+=sxs2;
00574     }
00575   }
00576 }
00577 
00578 
00579 //: Smooth and subsample single plane src_im in x to produce dest_im using 121 filter in x and y
00580 //  Smoothes with a 3x3 filter and subsamples
00581 VCL_DEFINE_SPECIALIZATION
00582 void vil_gauss_reduce_121_1plane(const double* src_im,
00583                                  unsigned src_ni, unsigned src_nj,
00584                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00585                                  double* dest_im,
00586                                  vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00587 {
00588   vcl_ptrdiff_t sxs2 = s_x_step*2;
00589   vcl_ptrdiff_t sys2 = s_y_step*2;
00590   double* d_row = dest_im+d_y_step;
00591   const double* s_row1 = src_im + s_y_step;
00592   const double* s_row2 = s_row1 + s_y_step;
00593   const double* s_row3 = s_row2 + s_y_step;
00594   unsigned ni2 = (src_ni-2)/2;
00595   unsigned nj2 = (src_nj-2)/2;
00596   for (unsigned y=0;y<nj2;++y)
00597   {
00598     // Set first element of row
00599     *d_row = *s_row2;
00600     double * d = d_row + d_x_step;
00601     const double* s1 = s_row1 + sxs2;
00602     const double* s2 = s_row2 + sxs2;
00603     const double* s3 = s_row3 + sxs2;
00604     for (unsigned x=0;x<ni2;++x)
00605     {
00606       // The following is a little inefficient - could group terms to reduce arithmetic
00607       *d =   0.0625 * s1[-s_x_step] + 0.125 * s1[0] + 0.0625 * s1[s_x_step]
00608            + 0.1250 * s2[-s_x_step] + 0.250 * s2[0] + 0.1250 * s2[s_x_step]
00609            + 0.0625 * s3[-s_x_step] + 0.125 * s3[0] + 0.0625 * s3[s_x_step];
00610 
00611       d += d_x_step;
00612       s1 += sxs2;
00613       s2 += sxs2;
00614       s3 += sxs2;
00615     }
00616     // Set last elements of row
00617     if (src_ni&1)
00618       *d = *s2;
00619 
00620     d_row += d_y_step;
00621     s_row1 += sys2;
00622     s_row2 += sys2;
00623     s_row3 += sys2;
00624   }
00625 
00626   // Need to set first and last rows as well
00627 
00628   // Dest image should be (src_ni+1)/2 x (src_nj+1)/2
00629   const double* s0 = src_im;
00630   unsigned ni=(src_ni+1)/2;
00631   for (unsigned i=0;i<ni;++i)
00632   {
00633     dest_im[i]= *s0;
00634     s0+=sxs2;
00635   }
00636 
00637   if (src_nj&1)
00638   {
00639     unsigned yhi = (src_nj-1)/2;
00640     double* dest_last_row = dest_im + yhi*d_y_step;
00641     const double* s_last = src_im + yhi*sys2;
00642     for (unsigned i=0;i<ni;++i)
00643     {
00644       dest_last_row[i]= *s_last;
00645       s_last+=sxs2;
00646     }
00647   }
00648 }
00649 
00650 
00651 //: Smooth and subsample single plane src_im in x to produce dest_im using 121 filter in x and y
00652 //  Smoothes with a 3x3 filter and subsamples
00653 VCL_DEFINE_SPECIALIZATION
00654 void vil_gauss_reduce_121_1plane(const int* src_im,
00655                                  unsigned src_ni, unsigned src_nj,
00656                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00657                                  int* dest_im,
00658                                  vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00659 {
00660   vcl_ptrdiff_t sxs2 = s_x_step*2;
00661   vcl_ptrdiff_t sys2 = s_y_step*2;
00662   int* d_row = dest_im+d_y_step;
00663   const int* s_row1 = src_im + s_y_step;
00664   const int* s_row2 = s_row1 + s_y_step;
00665   const int* s_row3 = s_row2 + s_y_step;
00666   unsigned ni2 = (src_ni-2)/2;
00667   unsigned nj2 = (src_nj-2)/2;
00668   for (unsigned y=0;y<nj2;++y)
00669   {
00670     // Set first element of row
00671     *d_row = *s_row2;
00672     int * d = d_row + d_x_step;
00673     const int* s1 = s_row1 + sxs2;
00674     const int* s2 = s_row2 + sxs2;
00675     const int* s3 = s_row3 + sxs2;
00676     for (unsigned x=0;x<ni2;++x)
00677     {
00678       // The following is a little inefficient - could group terms to reduce arithmetic
00679       // Add 0.5 so that truncating effectively rounds
00680       *d = int( 0.0625f * s1[-s_x_step] + 0.125f * s1[0] + 0.0625f * s1[s_x_step]
00681               + 0.1250f * s2[-s_x_step] + 0.250f * s2[0] + 0.1250f * s2[s_x_step]
00682               + 0.0625f * s3[-s_x_step] + 0.125f * s3[0] + 0.0625f * s3[s_x_step] +0.5);
00683 
00684       d += d_x_step;
00685       s1 += sxs2;
00686       s2 += sxs2;
00687       s3 += sxs2;
00688     }
00689     // Set last elements of row
00690     if (src_ni&1)
00691       *d = *s2;
00692 
00693     d_row += d_y_step;
00694     s_row1 += sys2;
00695     s_row2 += sys2;
00696     s_row3 += sys2;
00697   }
00698 
00699   // Need to set first and last rows as well
00700 
00701   // Dest image should be (src_ni+1)/2 x (src_nj+1)/2
00702   const int* s0 = src_im;
00703   unsigned ni=(src_ni+1)/2;
00704   for (unsigned i=0;i<ni;++i)
00705   {
00706     dest_im[i]= *s0;
00707     s0+=sxs2;
00708   }
00709 
00710   if (src_nj&1)
00711   {
00712     unsigned yhi = (src_nj-1)/2;
00713     int* dest_last_row = dest_im + yhi*d_y_step;
00714     const int* s_last = src_im + yhi*sys2;
00715     for (unsigned i=0;i<ni;++i)
00716     {
00717       dest_last_row[i]= *s_last;
00718       s_last+=sxs2;
00719     }
00720   }
00721 }
00722 
00723 //: Smooth and subsample single plane src_im in x to produce dest_im using 121 filter in x and y
00724 //  Smoothes with a 3x3 filter and subsamples
00725 VCL_DEFINE_SPECIALIZATION
00726 void vil_gauss_reduce_121_1plane(const vxl_int_16* src_im,
00727                                  unsigned src_ni, unsigned src_nj,
00728                                  vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00729                                  vxl_int_16* dest_im,
00730                                  vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00731 {
00732   vcl_ptrdiff_t sxs2 = s_x_step*2;
00733   vcl_ptrdiff_t sys2 = s_y_step*2;
00734   vxl_int_16* d_row = dest_im+d_y_step;
00735   const vxl_int_16* s_row1 = src_im + s_y_step;
00736   const vxl_int_16* s_row2 = s_row1 + s_y_step;
00737   const vxl_int_16* s_row3 = s_row2 + s_y_step;
00738   unsigned ni2 = (src_ni-2)/2;
00739   unsigned nj2 = (src_nj-2)/2;
00740   for (unsigned y=0;y<nj2;++y)
00741   {
00742     // Set first element of row
00743     *d_row = *s_row2;
00744     vxl_int_16 * d = d_row + d_x_step;
00745     const vxl_int_16* s1 = s_row1 + sxs2;
00746     const vxl_int_16* s2 = s_row2 + sxs2;
00747     const vxl_int_16* s3 = s_row3 + sxs2;
00748     for (unsigned x=0;x<ni2;++x)
00749     {
00750       // The following is a little inefficient - could group terms to reduce arithmetic
00751       // Add 0.5 so that truncating effectively rounds
00752       *d = vxl_int_16( 0.0625f * s1[-s_x_step] + 0.125f * s1[0] + 0.0625f * s1[s_x_step]
00753                      + 0.1250f * s2[-s_x_step] + 0.250f * s2[0] + 0.1250f * s2[s_x_step]
00754                      + 0.0625f * s3[-s_x_step] + 0.125f * s3[0] + 0.0625f * s3[s_x_step] +0.5);
00755 
00756       d += d_x_step;
00757       s1 += sxs2;
00758       s2 += sxs2;
00759       s3 += sxs2;
00760     }
00761     // Set last elements of row
00762     if (src_ni&1)
00763       *d = *s2;
00764 
00765     d_row += d_y_step;
00766     s_row1 += sys2;
00767     s_row2 += sys2;
00768     s_row3 += sys2;
00769   }
00770 
00771   // Need to set first and last rows as well
00772 
00773   // Dest image should be (src_ni+1)/2 x (src_nj+1)/2
00774   const vxl_int_16* s0 = src_im;
00775   unsigned ni=(src_ni+1)/2;
00776   for (unsigned i=0;i<ni;++i)
00777   {
00778     dest_im[i]= *s0;
00779     s0+=sxs2;
00780   }
00781 
00782   if (src_nj&1)
00783   {
00784     unsigned yhi = (src_nj-1)/2;
00785     vxl_int_16* dest_last_row = dest_im + yhi*d_y_step;
00786     const vxl_int_16* s_last = src_im + yhi*sys2;
00787     for (unsigned i=0;i<ni;++i)
00788     {
00789       dest_last_row[i]= *s_last;
00790       s_last+=sxs2;
00791     }
00792   }
00793 }
00794 
00795 
00796 vil_gauss_reduce_params::vil_gauss_reduce_params(double scaleStep)
00797 {
00798   assert(scaleStep> 1.0  && scaleStep<=2.0);
00799   scale_step_ = scaleStep;
00800   // This arrangement gives close to a 1-5-8-5-1 filter for scalestep of 2.0;
00801   // and 0-0-1-0-0 for a scale step close to 1.0;
00802   double z = 1/vcl_sqrt(2.0*(scaleStep-1.0));
00803   filt0_ = vnl_erf(0.5 * z) - vnl_erf(-0.5 * z);
00804   filt1_ = vnl_erf(1.5 * z) - vnl_erf(0.5 * z);
00805   filt2_ = vnl_erf(2.5 * z) - vnl_erf(1.5 * z);
00806 
00807   double five_tap_total = 2*(filt2_ + filt1_) + filt0_;
00808 #if 0
00809   double four_tap_total = filt2_ + 2*(filt1_) + filt0_;
00810   double three_tap_total = filt2_ + filt1_ + filt0_;
00811 #endif
00812 
00813   //  Calculate 3 tap half Gaussian filter assuming constant edge extension
00814   filt_edge0_ = (filt0_ + filt1_ + filt2_) / five_tap_total;
00815   filt_edge1_ = filt1_ / five_tap_total;
00816   filt_edge2_ = filt2_ / five_tap_total;
00817 #if 0
00818   filt_edge0_ = 1.0;
00819   filt_edge1_ = 0.0;
00820   filt_edge2_ = 0.0;
00821 #endif
00822   //  Calculate 4 tap skewed Gaussian filter assuming constant edge extension
00823   filt_pen_edge_n1_ = (filt1_+filt2_) / five_tap_total;
00824   filt_pen_edge0_ = filt0_ / five_tap_total;
00825   filt_pen_edge1_ = filt1_ / five_tap_total;
00826   filt_pen_edge2_ = filt2_ / five_tap_total;
00827 
00828   //  Calculate 5 tap Gaussian filter
00829   filt0_ = filt0_ / five_tap_total;
00830   filt1_ = filt1_ / five_tap_total;
00831   filt2_ = filt2_ / five_tap_total;
00832 
00833   assert(filt_edge0_ > filt_edge1_);
00834   assert(filt_edge1_ > filt_edge2_);
00835 }

Generated on Thu Jan 10 14:39:59 2008 for core/vil by  doxygen 1.4.4