core/vil/algo/vil_sobel_1x3.txx
Go to the documentation of this file.
00001 // This is core/vil/algo/vil_sobel_1x3.txx
00002 #ifndef vil_sobel_1x3_txx_
00003 #define vil_sobel_1x3_txx_
00004 //:
00005 // \file
00006 // \brief Apply sobel gradient filter to an image
00007 // \author Tim Cootes
00008 
00009 #include "vil_sobel_1x3.h"
00010 
00011 //: Apply Sobel 1x3 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_1x3(const vil_image_view<srcT>& src,
00016                    vil_image_view<destT>& grad_ij)
00017 {
00018   unsigned np = src.nplanes();
00019   unsigned ni = src.ni();
00020   unsigned nj = src.nj();
00021   grad_ij.set_size(ni,nj,2*np);
00022   for (unsigned p=0;p<np;++p)
00023   {
00024     vil_sobel_1x3_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 1x3 gradient filter to 2D image
00034 template<class srcT, class destT>
00035 void vil_sobel_1x3(const vil_image_view<srcT>& src,
00036                    vil_image_view<destT>& grad_i,
00037                    vil_image_view<destT>& grad_j)
00038 {
00039   unsigned np = src.nplanes();
00040   unsigned ni = src.ni();
00041   unsigned nj = src.nj();
00042   grad_i.set_size(ni,nj,np);
00043   grad_j.set_size(ni,nj,np);
00044   for (unsigned p=0;p<np;++p)
00045   {
00046     vil_sobel_1x3_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 
00055 template<class srcT, class destT>    
00056 void vil_sobel_1x3_1plane(const srcT* src,
00057                           vcl_ptrdiff_t s_istep, vcl_ptrdiff_t s_jstep,
00058                           destT* gi, vcl_ptrdiff_t gi_istep, vcl_ptrdiff_t gi_jstep,
00059                           destT* gj, vcl_ptrdiff_t gj_istep, vcl_ptrdiff_t gj_jstep,
00060                           unsigned ni, unsigned nj)
00061 {
00062   const destT point5=static_cast<destT>(0.5);
00063   const destT zero=static_cast<destT>(0.0);
00064 
00065   const srcT* s_data = src;
00066   destT* gi_data = gi;
00067   destT* gj_data = gj;
00068 
00069   if (ni==0 || nj==0) return;
00070   if (ni==1)
00071   {
00072       // Zero the elements in the column
00073     for (unsigned j=0;j<nj;++j)
00074     {
00075       *gi_data = zero;
00076       *gj_data = zero;
00077       gi_data += gi_jstep;
00078       gj_data += gj_jstep;
00079     }
00080     return;
00081   }
00082   if (nj==1)
00083   {
00084       // Zero the elements in the column
00085     for (unsigned i=0;i<ni;++i)
00086     {
00087       *gi_data = zero;
00088       *gj_data = zero;
00089       gi_data += gi_istep;
00090       gj_data += gj_istep;
00091     }
00092     return;
00093   }
00094 
00095   // Compute relative grid positions
00096   //     o2
00097   //  o4    o5
00098   //     o7
00099   const vcl_ptrdiff_t o2 = s_jstep;
00100   const vcl_ptrdiff_t o4 = -s_istep;
00101   const vcl_ptrdiff_t o5 = s_istep;
00102   const vcl_ptrdiff_t o7 = -s_jstep;
00103 
00104   const unsigned ni1 = ni-1;
00105   const unsigned nj1 = nj-1;
00106 
00107   s_data += s_istep + s_jstep;
00108   gi_data += gi_jstep;
00109   gj_data += gj_jstep;
00110   for (unsigned j=1;j<nj1;++j)
00111   {
00112     const srcT* s = s_data;
00113     destT* pgi = gi_data;
00114     destT* pgj = gj_data;
00115 
00116     // Zero the first elements in the rows
00117     *pgi = zero; pgi+=gi_istep;
00118     *pgj = zero; pgj+=gj_istep;
00119 
00120 
00121     for (unsigned i=1;i<ni1;++i)
00122     {
00123       // Compute gradient in i
00124       // Note: Multiply each element individually
00125       //      to ensure conversion to double before addition
00126       *pgi = point5*static_cast<destT>(s[o5]) - point5*static_cast<destT>(s[o4]);
00127       // Compute gradient in j
00128       *pgj = point5*static_cast<destT>(s[o2]) - point5*static_cast<destT>(s[o7]);
00129 
00130       s+=s_istep;
00131       pgi += gi_istep;
00132       pgj += gj_istep;
00133     }
00134 
00135     // Zero the last elements in the rows
00136     *pgi = zero;
00137     *pgj = zero;
00138 
00139     // Move to next row
00140     s_data  += s_jstep;
00141     gi_data += gi_jstep;
00142     gj_data += gj_jstep;
00143   }
00144 
00145   // Zero the first and last rows
00146   for (unsigned i=0;i<ni;++i)
00147   {
00148     *gi=zero; gi+=gi_istep;
00149     *gj=zero; gj+=gj_istep;
00150     *gi_data = zero; gi_data+=gi_istep;
00151     *gj_data = zero; gj_data+=gj_istep;
00152   }
00153 }
00154 
00155 
00156 
00157 #undef VIL_SOBEL_1X3_INSTANTIATE
00158 #define VIL_SOBEL_1X3_INSTANTIATE(srcT, destT) \
00159 template void vil_sobel_1x3(const vil_image_view< srcT >& src, \
00160                             vil_image_view<destT >& grad_ij); \
00161 template void vil_sobel_1x3(const vil_image_view< srcT >& src, \
00162                             vil_image_view<destT >& grad_i, \
00163                             vil_image_view<destT >& grad_j)
00164 
00165 #endif // vil_sobel_1x3_txx_