contrib/mul/vil3d/algo/vil3d_normalised_correlation_3d.h
Go to the documentation of this file.
00001 // This is mul/vil3d/algo/vil3d_normalised_correlation_3d.h
00002 #ifndef vil3d_normalised_correlation_3d_h_
00003 #define vil3d_normalised_correlation_3d_h_
00004 //:
00005 // \file
00006 // \brief 3D normalised correlation
00007 // \author Tim Cootes
00008 
00009 #include <vcl_compiler.h>
00010 #include <vcl_cassert.h>
00011 #include <vcl_cmath.h>  // for vcl_sqrt()
00012 #include <vil3d/vil3d_image_view.h>
00013 
00014 //: Evaluate dot product between kernel and src_im
00015 // Assumes that the kernel has been normalised to have zero mean
00016 // and unit variance
00017 // \relatesalso vil3d_image_view
00018 template <class srcT, class kernelT, class accumT>
00019 inline accumT vil_norm_corr_2d_at_pt(const srcT *src_im, vcl_ptrdiff_t s_istep,
00020                                      vcl_ptrdiff_t s_jstep, vcl_ptrdiff_t s_kstep,
00021                                      vcl_ptrdiff_t s_pstep,
00022                                      const vil3d_image_view<kernelT>& kernel,
00023                                      accumT)
00024 {
00025   unsigned ni = kernel.ni();
00026   unsigned nj = kernel.nj();
00027   unsigned nk = kernel.nk();
00028   unsigned np = kernel.nplanes();
00029 
00030   vcl_ptrdiff_t k_istep = kernel.istep(),
00031                 k_jstep = kernel.jstep(),
00032                 k_kstep = kernel.kstep();
00033 
00034   accumT sum=0;
00035   accumT mean=0;
00036   accumT sum_sq=0;
00037   for (unsigned p = 0; p<np; ++p)
00038   {
00039     // Select first slice of p-th plane
00040     const srcT*  src_slice  = src_im + p*s_pstep;
00041     const kernelT* k_slice =  kernel.origin_ptr() + p*kernel.planestep();
00042 
00043     for (unsigned int k=0;k<nk;++k,src_slice+=s_kstep,k_slice+=k_kstep)
00044     {
00045       // Select first row of k-th slice on p-th plane
00046       const srcT*  src_row  = src_slice;
00047       const kernelT* k_row =  k_slice;
00048 
00049       for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,k_row+=k_jstep)
00050       {
00051         const srcT* sp = src_row;
00052         const kernelT* kp = k_row;
00053         // Sum over j-th row
00054         for (unsigned int i=0;i<ni;++i, sp += s_istep, kp += k_istep)
00055         {
00056           sum += accumT(*sp) * accumT(*kp);
00057           mean+= accumT(*sp);
00058           sum_sq += accumT(*sp) * accumT(*sp);
00059         }
00060       }
00061     }
00062   }
00063 
00064   long n=ni*nj*nk*np;
00065   mean/=n;
00066   accumT var = sum_sq/n - mean*mean;
00067   return var<=0 ? 0 : sum/vcl_sqrt(var);
00068 }
00069 
00070 //: Normalised cross-correlation of (pre-normalised) kernel with srcT.
00071 // Each dimension of dest is resized to (1+src_im.nX()-kernel.nX())
00072 // (a one plane image).
00073 // On exit dest(x,y,z) = sum_ijk src_im(x+i,y+j,y+k)*kernel(i,j,k)/sd_under_region
00074 //
00075 // Assumes that the kernel has been normalised to have zero mean
00076 // and unit variance
00077 // \relatesalso vil3d_image_view
00078 template <class srcT, class destT, class kernelT, class accumT>
00079 inline void vil3d_normalised_correlation_3d(const vil3d_image_view<srcT>& src_im,
00080                                             vil3d_image_view<destT>& dest_im,
00081                                             const vil3d_image_view<kernelT>& kernel,
00082                                             accumT ac)
00083 {
00084   unsigned ni = 1+src_im.ni()-kernel.ni(); assert(1+src_im.ni() >= kernel.ni());
00085   unsigned nj = 1+src_im.nj()-kernel.nj(); assert(1+src_im.nj() >= kernel.nj());
00086   unsigned nk = 1+src_im.nk()-kernel.nk(); assert(1+src_im.nk() >= kernel.nk());
00087   vcl_ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
00088   vcl_ptrdiff_t s_kstep = src_im.kstep(), s_pstep = src_im.planestep();
00089 
00090   dest_im.set_size(ni,nj,nk,1);
00091   vcl_ptrdiff_t d_istep = dest_im.istep(),
00092                 d_jstep = dest_im.jstep(),
00093                 d_kstep = dest_im.kstep();
00094 
00095    // Select first slice of p-th plane
00096   const srcT*  src_slice  = src_im.origin_ptr();
00097   destT* dest_slice = dest_im.origin_ptr();
00098 
00099   for (unsigned k=0;k<nk;++k,src_slice+=s_kstep,dest_slice+=d_kstep)
00100   {
00101     // Select first row of k-th slice on p-th plane
00102     const srcT* src_row  = src_slice;
00103     destT* dest_row = dest_slice;
00104 
00105     for (unsigned j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
00106     {
00107       const srcT* sp = src_row;
00108       destT* dp = dest_row;
00109       for (unsigned i=0;i<ni;++i, sp += s_istep, dp += d_istep)
00110         *dp =(destT)vil_norm_corr_2d_at_pt(sp,s_istep,s_jstep,s_kstep,
00111                                            s_pstep,kernel,ac);
00112       // Convolve at src(i,j,k)
00113     }
00114  }
00115 }
00116 
00117 #endif // vil3d_normalised_correlation_3d_h_