vil_normalised_correlation_2d.h
Go to the documentation of this file.
1 // This is core/vil/algo/vil_normalised_correlation_2d.h
2 #ifndef vil_normalised_correlation_2d_h_
3 #define vil_normalised_correlation_2d_h_
4 //:
5 // \file
6 // \brief 2D normalised correlation
7 // \author Tim Cootes
8 
9 #include <cmath>
10 #include <cstddef>
11 #include <vil/vil_image_view.h>
12 #ifdef _MSC_VER
13 # include <vcl_msvc_warnings.h>
14 #endif
15 #include <cassert>
16 
17 //: Evaluate dot product between kernel and src_im
18 // Assumes that the kernel has been normalised to have zero mean
19 // and unit variance
20 // \relatesalso vil_image_view
21 template <class srcT, class kernelT, class accumT>
22 inline accumT vil_norm_corr_2d_at_pt(const srcT *src_im, std::ptrdiff_t s_istep,
23  std::ptrdiff_t s_jstep, std::ptrdiff_t s_pstep,
24  const vil_image_view<kernelT>& kernel,
25  accumT)
26 {
27  unsigned ni = kernel.ni();
28  unsigned nj = kernel.nj();
29  unsigned np = kernel.nplanes();
30 
31  std::ptrdiff_t k_istep = kernel.istep(), k_jstep = kernel.jstep();
32 
33  accumT sum=0;
34  accumT mean=0;
35  accumT sum_sq=0;
36  for (unsigned p = 0; p<np; ++p)
37  {
38  // Select first row of p-th plane
39  const srcT* src_row = src_im + p*s_pstep;
40  const kernelT* k_row = kernel.top_left_ptr() + p*kernel.planestep();
41 
42  for (unsigned int j=0;j<nj;++j,src_row+=s_jstep,k_row+=k_jstep)
43  {
44  const srcT* sp = src_row;
45  const kernelT* kp = k_row;
46  // Sum over j-th row
47  for (unsigned int i=0;i<ni;++i, sp += s_istep, kp += k_istep)
48  {
49  sum += accumT(*sp)*accumT(*kp);
50  mean+= accumT(*sp);
51  sum_sq += accumT(*sp)*accumT(*sp);
52  }
53  }
54  }
55 
56  long n=ni*nj*np;
57  mean/=(accumT)n;
58  accumT var = sum_sq/(accumT)n - mean*mean;
59  return var<=0 ? 0 : sum/std::sqrt(var);
60 }
61 
62 //: Normalised cross-correlation of (pre-normalised) kernel with srcT.
63 // dest is resized to (1+src_im.ni()-kernel.ni())x(1+src_im.nj()-kernel.nj())
64 // (a one plane image).
65 // On exit dest(x,y) = sum_ij src_im(x+i,y+j)*kernel(i,j)/sd_under_region
66 //
67 // Assumes that the kernel has been normalised to have zero mean
68 // and unit variance
69 // \relatesalso vil_image_view
70 template <class srcT, class destT, class kernelT, class accumT>
72  vil_image_view<destT>& dest_im,
73  const vil_image_view<kernelT>& kernel,
74  accumT ac)
75 {
76  unsigned ni = 1+src_im.ni()-kernel.ni(); assert(1+src_im.ni() >= kernel.ni());
77  unsigned nj = 1+src_im.nj()-kernel.nj(); assert(1+src_im.nj() >= kernel.nj());
78  std::ptrdiff_t s_istep = src_im.istep(), s_jstep = src_im.jstep();
79  std::ptrdiff_t s_pstep = src_im.planestep();
80 
81  dest_im.set_size(ni,nj,1);
82  std::ptrdiff_t d_istep = dest_im.istep(),d_jstep = dest_im.jstep();
83 
84  // Select first row of p-th plane
85  const srcT* src_row = src_im.top_left_ptr();
86  destT* dest_row = dest_im.top_left_ptr();
87 
88  for (unsigned j=0;j<nj;++j,src_row+=s_jstep,dest_row+=d_jstep)
89  {
90  const srcT* sp = src_row;
91  destT* dp = dest_row;
92  for (unsigned i=0;i<ni;++i, sp += s_istep, dp += d_istep)
93  *dp =(destT)vil_norm_corr_2d_at_pt(sp,s_istep,s_jstep,s_pstep,kernel,ac);
94  // Convolve at src(i,j)
95  }
96 }
97 
98 #endif // vil_normalised_correlation_2d_h_
void vil_normalised_correlation_2d(const vil_image_view< srcT > &src_im, vil_image_view< destT > &dest_im, const vil_image_view< kernelT > &kernel, accumT ac)
Normalised cross-correlation of (pre-normalised) kernel with srcT.
accumT vil_norm_corr_2d_at_pt(const srcT *src_im, std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep, std::ptrdiff_t s_pstep, const vil_image_view< kernelT > &kernel, accumT)
Evaluate dot product between kernel and src_im.
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
void set_size(unsigned ni, unsigned nj) override
resize current planes to ni x nj.
std::ptrdiff_t jstep() const
Add this to your pixel pointer to get next j pixel.
unsigned ni() const
Width.
unsigned nj() const
Height.
std::ptrdiff_t planestep() const
Add this to your pixel pointer to get pixel on next plane.
A base class reference-counting view of some image data.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
unsigned nplanes() const
Number of planes.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.