core/vil/algo/vil_sobel_3x3.txx
Go to the documentation of this file.
00001 // This is core/vil/algo/vil_sobel_3x3.txx
00002 #ifndef vil_sobel_3x3_txx_
00003 #define vil_sobel_3x3_txx_
00004 //:
00005 // \file
00006 // \brief Apply sobel gradient filter to an image
00007 // \author Tim Cootes
00008 
00009 #include "vil_sobel_3x3.h"
00010 
00011 //: Apply Sobel 3x3 gradient filter to image.
00012 //  dest has twice as many planes as src, with dest plane (2i) being the i-gradient
00013 //  of source plane i and dest plane (2i+1) being the j-gradient.
00014 template<class srcT, class destT>
00015 void vil_sobel_3x3(const vil_image_view<srcT>& src,
00016                    vil_image_view<destT>& grad_ij)
00017 {
00018   int np = src.nplanes();
00019   int ni = src.ni();
00020   int nj = src.nj();
00021   grad_ij.set_size(ni,nj,2*np);
00022   for (int p=0;p<np;++p)
00023   {
00024     vil_sobel_3x3_1plane(src.top_left_ptr()+p*src.planestep(),
00025                          src.istep(),src.jstep(),
00026                          grad_ij.top_left_ptr()+2*p*grad_ij.planestep(),
00027                          grad_ij.istep(),grad_ij.jstep(),
00028                          grad_ij.top_left_ptr()+(2*p+1)*grad_ij.planestep(),
00029                          grad_ij.istep(),grad_ij.jstep(), ni,nj);
00030   }
00031 }
00032 
00033 //: Apply Sobel 3x3 gradient filter to 2D image
00034 template<class srcT, class destT>
00035 void vil_sobel_3x3(const vil_image_view<srcT>& src,
00036                    vil_image_view<destT>& grad_i,
00037                    vil_image_view<destT>& grad_j)
00038 {
00039   int np = src.nplanes();
00040   int ni = src.ni();
00041   int nj = src.nj();
00042   grad_i.set_size(ni,nj,np);
00043   grad_j.set_size(ni,nj,np);
00044   for (int p=0;p<np;++p)
00045   {
00046     vil_sobel_3x3_1plane(src.top_left_ptr()+p*src.planestep(),
00047                          src.istep(),src.jstep(),
00048                          grad_i.top_left_ptr()+p*grad_i.planestep(),
00049                          grad_i.istep(),grad_i.jstep(),
00050                          grad_j.top_left_ptr()+p*grad_j.planestep(),
00051                          grad_j.istep(),grad_j.jstep(), ni,nj);
00052   }
00053 }
00054 //: run Sobel 3x3 gradient filter on a single plane of an image
00055 //  Computes both i and j gradients of an ni x nj plane of data
00056 template<class srcT, class destT>
00057 void vil_sobel_3x3_1plane(const srcT* src,
00058                           vcl_ptrdiff_t s_istep, vcl_ptrdiff_t s_jstep,
00059                           destT* gi, vcl_ptrdiff_t gi_istep, vcl_ptrdiff_t gi_jstep,
00060                           destT* gj, vcl_ptrdiff_t gj_istep, vcl_ptrdiff_t gj_jstep,
00061                           unsigned ni, unsigned nj)
00062 {
00063   const destT k125=static_cast<destT>(0.125);
00064   const destT k25=static_cast<destT>(0.25);
00065   const destT zero=static_cast<destT>(0.0);
00066 
00067   const srcT* s_data = src;
00068   destT *gi_data = gi;
00069   destT *gj_data = gj;
00070 
00071   if (ni==0 || nj==0) return;
00072   if (ni==1)
00073   {
00074       // Zero the elements in the column
00075     for (unsigned j=0;j<nj;++j)
00076     {
00077       *gi_data = zero;
00078       *gj_data = zero;
00079       gi_data += gi_jstep;
00080       gj_data += gj_jstep;
00081     }
00082     return;
00083   }
00084   if (nj==1)
00085   {
00086       // Zero the elements in the column
00087     for (unsigned i=0;i<ni;++i)
00088     {
00089       *gi_data = zero;
00090       *gj_data = zero;
00091       gi_data += gi_istep;
00092       gj_data += gj_istep;
00093     }
00094     return;
00095   }
00096 
00097   // Compute relative grid positions
00098   //  o1 o2 o3
00099   //  o4    o5
00100   //  o6 o7 o8
00101   const vcl_ptrdiff_t o1 = s_jstep - s_istep;
00102   const vcl_ptrdiff_t o2 = s_jstep;
00103   const vcl_ptrdiff_t o3 = s_istep + s_jstep;
00104   const vcl_ptrdiff_t o4 = -s_istep;
00105   const vcl_ptrdiff_t o5 = s_istep;
00106   const vcl_ptrdiff_t o6 = -s_istep - s_jstep;
00107   const vcl_ptrdiff_t o7 = -s_jstep;
00108   const vcl_ptrdiff_t o8 = s_istep - s_jstep;
00109 
00110   const unsigned ni1 = ni-1;
00111   const unsigned nj1 = nj-1;
00112 
00113   s_data += s_istep + s_jstep;
00114   gi_data += gi_jstep;
00115   gj_data += gj_jstep;
00116 
00117   for (unsigned j=1;j<nj1;++j)
00118   {
00119     const srcT* s = s_data;
00120     destT* pgi = gi_data;
00121     destT* pgj = gj_data;
00122 
00123     // Zero the first elements in the rows
00124     *pgi = 0; pgi+=gi_istep;
00125     *pgj = 0; pgj+=gj_istep;
00126 
00127     for (unsigned i=1;i<ni1;++i)
00128     {
00129       // Compute gradient in i
00130       // Note: Multiply each element individually
00131       //      to ensure conversion to destT before addition
00132       *pgi = ( k125*static_cast<destT>(s[o3]) + k25*static_cast<destT>(s[o5]) + k125*static_cast<destT>(s[o8]) )
00133            - ( k125*static_cast<destT>(s[o1]) + k25*static_cast<destT>(s[o4]) + k125*static_cast<destT>(s[o6]) );
00134       // Compute gradient in j
00135       *pgj = ( k125*static_cast<destT>(s[o1]) + k25*static_cast<destT>(s[o2]) + k125*static_cast<destT>(s[o3]) )
00136            - ( k125*static_cast<destT>(s[o6]) + k25*static_cast<destT>(s[o7]) + k125*static_cast<destT>(s[o8]) );
00137 
00138       s+=s_istep;
00139       pgi += gi_istep;
00140       pgj += gj_istep;
00141     }
00142 
00143     // Zero the last elements in the rows
00144     *pgi = zero;
00145     *pgj = zero;
00146 
00147     // Move to next row
00148     s_data  += s_jstep;
00149     gi_data += gi_jstep;
00150     gj_data += gj_jstep;
00151   }
00152 
00153   // Zero the first and last rows
00154   for (unsigned i=0;i<ni;++i)
00155   {
00156     *gi=zero; gi+=gi_istep;
00157     *gj=zero; gj+=gj_istep;
00158     *gi_data = zero; gi_data+=gi_istep;
00159     *gj_data = zero; gj_data+=gj_istep;
00160   }
00161 }
00162 
00163 
00164 #undef VIL_SOBEL_3X3_INSTANTIATE
00165 #define VIL_SOBEL_3X3_INSTANTIATE(srcT, destT) \
00166 template void vil_sobel_3x3(const vil_image_view< srcT >& src, \
00167                             vil_image_view<destT >& grad_ij); \
00168 template void vil_sobel_3x3(const vil_image_view< srcT >& src, \
00169                             vil_image_view<destT >& grad_i, \
00170                             vil_image_view<destT >& grad_j)
00171 
00172 #endif // vil_sobel_3x3_txx_