contrib/tbl/vipl/vipl_gaussian_convolution.txx

Go to the documentation of this file.
00001 #ifndef vipl_gaussian_convolution_txx_
00002 #define vipl_gaussian_convolution_txx_
00003 
00004 #include "vipl_gaussian_convolution.h"
00005 #include <vcl_cmath.h> // for vcl_sqrt(), vcl_exp(), vcl_log()
00006 
00007 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00008 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: section_applyop()
00009 {
00010   const ImgIn &in = this->in_data(0);
00011   ImgOut &out = *this->out_data_ptr();
00012   int size = masksize();
00013 
00014   // Make temporary buffer to hold result of first (horizontal) convolution
00015   int width  = stop(this->X_Axis()) - start(this->X_Axis());
00016   int height = stop(this->Y_Axis()) - start(this->Y_Axis());
00017   double* buf = new double[width*height];
00018   if (!buf) return false; // memory allocation failed
00019 
00020   // 1-D mask was generated in preop(), we just use it here:
00021 
00022   // horizontal convolution:
00023   int starty = start(this->Y_Axis());
00024   int stopy = stop(this->Y_Axis());
00025   for (int j = starty; j < stopy; ++j)
00026   {
00027     int buf_j = j - starty;
00028     int startx = start(this->X_Axis(),j);
00029     int stopx = stop(this->X_Axis(),j);
00030     for (int i = startx; i < stopx; ++i) {
00031       int buf_i = i - startx;
00032       double result = mask()[0] * fgetpixel(in, i, j, DataIn(0));
00033       for (int x=1; x<size; ++x)
00034         result += mask()[x] * (getpixel(in, i+x, j, DataIn(0)) + getpixel(in, i-x, j, DataIn(0)));
00035       buf[buf_i+width*buf_j] = result;
00036     }
00037   }
00038   // vertical convolution:
00039   for (int j = starty; j < stopy; ++j)
00040   {
00041     int buf_j = j - starty;
00042     int startx = start(this->X_Axis(),j);
00043     int stopx = stop(this->X_Axis(),j);
00044     for (int i = startx; i < stopx; ++i) {
00045       int buf_i = i - startx;
00046       double result = mask()[0] * buf[buf_i+width*buf_j];
00047       for (int y=1; y<size; ++y) {
00048         if (buf_j+y < height) result += mask()[y] * buf[buf_i+width*(buf_j+y)];
00049         if (buf_j >= y) result += mask()[y] * buf[buf_i+width*(buf_j-y)];
00050       }
00051       fsetpixel(out, i, j, DataOut(result));
00052     }
00053   }
00054   delete[] buf;
00055   return true;
00056 }
00057 
00058 // it is important that the mask be computed in preop, if it was done in
00059 // section_applyop then on a large image it would be computed many times.
00060 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00061 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: preop()
00062 {
00063   // create 1-D mask:
00064   double lc = -2 * vcl_log(cutoff()); // cutoff guaranteed > 0
00065   int radius = (lc<=0) ? 0 : 1 + int(vcl_sqrt(lc)*sigma()); // sigma guaranteed >= 0
00066   int size = radius + 1; // only need half mask, because it is symmetric
00067   ref_masksize() = size;
00068   delete[] ref_mask(); ref_mask() = new double[size];
00069   double s = -0.5/sigma()/sigma();
00070   double halfnorm = vcl_exp(0.25*s) + 1.0;
00071   for (int y=1; y<8; ++y) halfnorm += 2*vcl_exp(y*y*0.0625*0.0625*s);
00072   ref_mask()[0] = 2*halfnorm;
00073   for (int x=1; x<size; ++x)
00074   { // trapezoid approximation (16 pieces) of integral between x-0.5 and x+0.5
00075     ref_mask()[x] = vcl_exp((x-0.5)*(x-0.5)*s) + vcl_exp((x+0.5)*(x+0.5)*s);
00076     for (int y=-7; y<8; ++y) ref_mask()[x] += 2*vcl_exp((x+y*0.0625)*(x+y*0.0625)*s);
00077     halfnorm += mask()[x];
00078   }
00079   for (int x=0; x<size; ++x) ref_mask()[x] /= 2*halfnorm; // normalise mask
00080   return true;
00081 }
00082 
00083 // We destroy the mask in postop, after we are all done filtering
00084 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00085 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: postop()
00086 {
00087   delete[] ref_mask(); ref_mask()=0;
00088   return true;
00089 }
00090 
00091 #endif // vipl_gaussian_convolution_txx_

Generated on Tue Oct 7 05:13:24 2008 for contrib/tbl/vipl by  doxygen 1.5.1