vil_sobel_1x3.hxx
Go to the documentation of this file.
1 // This is core/vil/algo/vil_sobel_1x3.hxx
2 #ifndef vil_sobel_1x3_hxx_
3 #define vil_sobel_1x3_hxx_
4 //:
5 // \file
6 // \brief Apply sobel gradient filter to an image
7 // \author Tim Cootes
8 
9 #include "vil_sobel_1x3.h"
10 
11 //: Apply Sobel 1x3 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  unsigned np = src.nplanes();
19  unsigned ni = src.ni();
20  unsigned nj = src.nj();
21  grad_ij.set_size(ni,nj,2*np);
22  for (unsigned 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 1x3 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  unsigned np = src.nplanes();
40  unsigned ni = src.ni();
41  unsigned nj = src.nj();
42  grad_i.set_size(ni,nj,np);
43  grad_j.set_size(ni,nj,np);
44  for (unsigned 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 
55 template<class srcT, class destT>
56 void vil_sobel_1x3_1plane(const srcT* src,
57  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
58  destT* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
59  destT* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
60  unsigned ni, unsigned nj)
61 {
62  const destT point5=static_cast<destT>(0.5);
63  const destT zero=static_cast<destT>(0.0);
64 
65  const srcT* s_data = src;
66  destT* gi_data = gi;
67  destT* gj_data = gj;
68 
69  if (ni==0 || nj==0) return;
70  if (ni==1)
71  {
72  // Zero the elements in the column
73  for (unsigned j=0;j<nj;++j)
74  {
75  *gi_data = zero;
76  *gj_data = zero;
77  gi_data += gi_jstep;
78  gj_data += gj_jstep;
79  }
80  return;
81  }
82  if (nj==1)
83  {
84  // Zero the elements in the column
85  for (unsigned i=0;i<ni;++i)
86  {
87  *gi_data = zero;
88  *gj_data = zero;
89  gi_data += gi_istep;
90  gj_data += gj_istep;
91  }
92  return;
93  }
94 
95  // Compute relative grid positions
96  // o2
97  // o4 o5
98  // o7
99  const std::ptrdiff_t o2 = s_jstep;
100  const std::ptrdiff_t o4 = -s_istep;
101  const std::ptrdiff_t o5 = s_istep;
102  const std::ptrdiff_t o7 = -s_jstep;
103 
104  const unsigned ni1 = ni-1;
105  const unsigned nj1 = nj-1;
106 
107  s_data += s_istep + s_jstep;
108  gi_data += gi_jstep;
109  gj_data += gj_jstep;
110  for (unsigned j=1;j<nj1;++j)
111  {
112  const srcT* s = s_data;
113  destT* pgi = gi_data;
114  destT* pgj = gj_data;
115 
116  // Zero the first elements in the rows
117  *pgi = zero; pgi+=gi_istep;
118  *pgj = zero; pgj+=gj_istep;
119 
120 
121  for (unsigned i=1;i<ni1;++i)
122  {
123  // Compute gradient in i
124  // Note: Multiply each element individually
125  // to ensure conversion to double before addition
126  *pgi = point5*static_cast<destT>(s[o5]) - point5*static_cast<destT>(s[o4]);
127  // Compute gradient in j
128  *pgj = point5*static_cast<destT>(s[o2]) - point5*static_cast<destT>(s[o7]);
129 
130  s+=s_istep;
131  pgi += gi_istep;
132  pgj += gj_istep;
133  }
134 
135  // Zero the last elements in the rows
136  *pgi = zero;
137  *pgj = zero;
138 
139  // Move to next row
140  s_data += s_jstep;
141  gi_data += gi_jstep;
142  gj_data += gj_jstep;
143  }
144 
145  // Zero the first and last rows
146  for (unsigned i=0;i<ni;++i)
147  {
148  *gi=zero; gi+=gi_istep;
149  *gj=zero; gj+=gj_istep;
150  *gi_data = zero; gi_data+=gi_istep;
151  *gj_data = zero; gj_data+=gj_istep;
152  }
153 }
154 
155 
156 
157 #undef VIL_SOBEL_1X3_INSTANTIATE
158 #define VIL_SOBEL_1X3_INSTANTIATE(srcT, destT) \
159 template void vil_sobel_1x3(const vil_image_view< srcT >& src, \
160  vil_image_view<destT >& grad_ij); \
161 template void vil_sobel_1x3(const vil_image_view< srcT >& src, \
162  vil_image_view<destT >& grad_i, \
163  vil_image_view<destT >& grad_j)
164 
165 #endif // vil_sobel_1x3_hxx_
void vil_sobel_1x3(const vil_image_view< srcT > &src, vil_image_view< destT > &grad_i, vil_image_view< destT > &grad_j)
Compute gradients of an image using 1x3 Sobel filters.
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.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
unsigned nplanes() const
Number of planes.
Apply 1x3 sobel operator to image data.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.
void vil_sobel_1x3_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)
Compute gradients of single plane of 2D data using 1x3 Sobel filters.