vil_sobel_3x3.hxx
Go to the documentation of this file.
1 // This is core/vil/algo/vil_sobel_3x3.hxx
2 #ifndef vil_sobel_3x3_hxx_
3 #define vil_sobel_3x3_hxx_
4 //:
5 // \file
6 // \brief Apply sobel gradient filter to an image
7 // \author Tim Cootes
8 
9 #include "vil_sobel_3x3.h"
10 
11 //: Apply Sobel 3x3 gradient filter to image.
12 // dest has twice as many planes as src, with dest plane (2i) being the i-gradient
13 // of source plane i and dest plane (2i+1) being the j-gradient.
14 template<class srcT, class destT>
16  vil_image_view<destT>& grad_ij)
17 {
18  int np = src.nplanes();
19  int ni = src.ni();
20  int nj = src.nj();
21  grad_ij.set_size(ni,nj,2*np);
22  for (int p=0;p<np;++p)
23  {
25  src.istep(),src.jstep(),
26  grad_ij.top_left_ptr()+2*p*grad_ij.planestep(),
27  grad_ij.istep(),grad_ij.jstep(),
28  grad_ij.top_left_ptr()+(2*p+1)*grad_ij.planestep(),
29  grad_ij.istep(),grad_ij.jstep(), ni,nj);
30  }
31 }
32 
33 //: Apply Sobel 3x3 gradient filter to 2D image
34 template<class srcT, class destT>
36  vil_image_view<destT>& grad_i,
37  vil_image_view<destT>& grad_j)
38 {
39  int np = src.nplanes();
40  int ni = src.ni();
41  int nj = src.nj();
42  grad_i.set_size(ni,nj,np);
43  grad_j.set_size(ni,nj,np);
44  for (int p=0;p<np;++p)
45  {
47  src.istep(),src.jstep(),
48  grad_i.top_left_ptr()+p*grad_i.planestep(),
49  grad_i.istep(),grad_i.jstep(),
50  grad_j.top_left_ptr()+p*grad_j.planestep(),
51  grad_j.istep(),grad_j.jstep(), ni,nj);
52  }
53 }
54 //: run Sobel 3x3 gradient filter on a single plane of an image
55 // Computes both i and j gradients of an ni x nj plane of data
56 template<class srcT, class destT>
57 void vil_sobel_3x3_1plane(const srcT* src,
58  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
59  destT* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
60  destT* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
61  unsigned ni, unsigned nj)
62 {
63  const destT k125=static_cast<destT>(0.125);
64  const destT k25=static_cast<destT>(0.25);
65  const destT zero=static_cast<destT>(0.0);
66 
67  const srcT* s_data = src;
68  destT *gi_data = gi;
69  destT *gj_data = gj;
70 
71  if (ni==0 || nj==0) return;
72  if (ni==1)
73  {
74  // Zero the elements in the column
75  for (unsigned j=0;j<nj;++j)
76  {
77  *gi_data = zero;
78  *gj_data = zero;
79  gi_data += gi_jstep;
80  gj_data += gj_jstep;
81  }
82  return;
83  }
84  if (nj==1)
85  {
86  // Zero the elements in the column
87  for (unsigned i=0;i<ni;++i)
88  {
89  *gi_data = zero;
90  *gj_data = zero;
91  gi_data += gi_istep;
92  gj_data += gj_istep;
93  }
94  return;
95  }
96 
97  // Compute relative grid positions
98  // o1 o2 o3
99  // o4 o5
100  // o6 o7 o8
101  const std::ptrdiff_t o1 = s_jstep - s_istep;
102  const std::ptrdiff_t o2 = s_jstep;
103  const std::ptrdiff_t o3 = s_istep + s_jstep;
104  const std::ptrdiff_t o4 = -s_istep;
105  const std::ptrdiff_t o5 = s_istep;
106  const std::ptrdiff_t o6 = -s_istep - s_jstep;
107  const std::ptrdiff_t o7 = -s_jstep;
108  const std::ptrdiff_t o8 = s_istep - s_jstep;
109 
110  const unsigned ni1 = ni-1;
111  const unsigned nj1 = nj-1;
112 
113  s_data += s_istep + s_jstep;
114  gi_data += gi_jstep;
115  gj_data += gj_jstep;
116 
117  for (unsigned j=1;j<nj1;++j)
118  {
119  const srcT* s = s_data;
120  destT* pgi = gi_data;
121  destT* pgj = gj_data;
122 
123  // Zero the first elements in the rows
124  *pgi = 0; pgi+=gi_istep;
125  *pgj = 0; pgj+=gj_istep;
126 
127  for (unsigned i=1;i<ni1;++i)
128  {
129  // Compute gradient in i
130  // Note: Multiply each element individually
131  // to ensure conversion to destT before addition
132  *pgi = ( k125*static_cast<destT>(s[o3]) + k25*static_cast<destT>(s[o5]) + k125*static_cast<destT>(s[o8]) )
133  - ( k125*static_cast<destT>(s[o1]) + k25*static_cast<destT>(s[o4]) + k125*static_cast<destT>(s[o6]) );
134  // Compute gradient in j
135  *pgj = ( k125*static_cast<destT>(s[o1]) + k25*static_cast<destT>(s[o2]) + k125*static_cast<destT>(s[o3]) )
136  - ( k125*static_cast<destT>(s[o6]) + k25*static_cast<destT>(s[o7]) + k125*static_cast<destT>(s[o8]) );
137 
138  s+=s_istep;
139  pgi += gi_istep;
140  pgj += gj_istep;
141  }
142 
143  // Zero the last elements in the rows
144  *pgi = zero;
145  *pgj = zero;
146 
147  // Move to next row
148  s_data += s_jstep;
149  gi_data += gi_jstep;
150  gj_data += gj_jstep;
151  }
152 
153  // Zero the first and last rows
154  for (unsigned i=0;i<ni;++i)
155  {
156  *gi=zero; gi+=gi_istep;
157  *gj=zero; gj+=gj_istep;
158  *gi_data = zero; gi_data+=gi_istep;
159  *gj_data = zero; gj_data+=gj_istep;
160  }
161 }
162 
163 
164 #undef VIL_SOBEL_3X3_INSTANTIATE
165 #define VIL_SOBEL_3X3_INSTANTIATE(srcT, destT) \
166 template void vil_sobel_3x3(const vil_image_view< srcT >& src, \
167  vil_image_view<destT >& grad_ij); \
168 template void vil_sobel_3x3(const vil_image_view< srcT >& src, \
169  vil_image_view<destT >& grad_i, \
170  vil_image_view<destT >& grad_j)
171 
172 #endif // vil_sobel_3x3_hxx_
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
void vil_sobel_3x3_1plane(const srcT *src, std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep, destT *gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep, destT *gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep, unsigned ni, unsigned nj)
run Sobel 3x3 gradient filter on a single plane of an image.
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.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
unsigned nplanes() const
Number of planes.
void vil_sobel_3x3(const vil_image_view< srcT > &src, vil_image_view< destT > &grad_i, vil_image_view< destT > &grad_j)
Compute gradients of an image using 3x3 Sobel filters.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.
Apply 3x3 sobel operator to image data.