vil_sobel_3x3.cxx
Go to the documentation of this file.
1 // This is core/vil/algo/vil_sobel_3x3.cxx
2 #include "vil_sobel_3x3.h"
3 //:
4 // \file
5 // \brief Apply gradient operator to 2D planes of data
6 // \author Tim Cootes
7 
8 //: Compute gradients of single plane of 2D data using 3x3 Sobel filters
9 // Computes both i and j gradients of an ni x nj plane of data
10 template <>
11 void vil_sobel_3x3_1plane(const unsigned char* src,
12  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
13  float* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
14  float* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
15  unsigned ni, unsigned nj)
16 {
17  const unsigned char* s_data = src;
18  float *gi_data = gi;
19  float *gj_data = gj;
20 
21  if (ni==0 || nj==0) return;
22  if (ni==1)
23  {
24  // Zero the elements in the column
25  for (unsigned j=0;j<nj;++j)
26  {
27  *gi_data = 0;
28  *gj_data = 0;
29  gi_data += gi_jstep;
30  gj_data += gj_jstep;
31  }
32  return;
33  }
34  if (nj==1)
35  {
36  // Zero the elements in the column
37  for (unsigned i=0;i<ni;++i)
38  {
39  *gi_data = 0;
40  *gj_data = 0;
41  gi_data += gi_istep;
42  gj_data += gj_istep;
43  }
44  return;
45  }
46 
47  // Compute relative grid positions
48  // o1 o2 o3
49  // o4 o5
50  // o6 o7 o8
51  const std::ptrdiff_t o1 = s_jstep - s_istep;
52  const std::ptrdiff_t o2 = s_jstep;
53  const std::ptrdiff_t o3 = s_istep + s_jstep;
54  const std::ptrdiff_t o4 = -s_istep;
55  const std::ptrdiff_t o5 = s_istep;
56  const std::ptrdiff_t o6 = -s_istep - s_jstep;
57  const std::ptrdiff_t o7 = -s_jstep;
58  const std::ptrdiff_t o8 = s_istep - s_jstep;
59 
60  const unsigned ni1 = ni-1;
61  const unsigned nj1 = nj-1;
62 
63  s_data += s_istep + s_jstep;
64  gi_data += gi_jstep;
65  gj_data += gj_jstep;
66 
67  for (unsigned j=1;j<nj1;++j)
68  {
69  const unsigned char* s = s_data;
70  float* pgi = gi_data;
71  float* pgj = gj_data;
72 
73  // Zero the first elements in the rows
74  *pgi = 0; pgi+=gi_istep;
75  *pgj = 0; pgj+=gj_istep;
76 
77  for (unsigned i=1;i<ni1;++i)
78  {
79  // Compute gradient in i
80  // Note: Multiply each element individually
81  // to ensure conversion to float before addition
82  *pgi = (0.125f*s[o3] + 0.25f*s[o5] + 0.125f*s[o8])
83  - (0.125f*s[o1] + 0.25f*s[o4] + 0.125f*s[o6]);
84  // Compute gradient in j
85  *pgj = (0.125f*s[o1] + 0.25f*s[o2] + 0.125f*s[o3])
86  - (0.125f*s[o6] + 0.25f*s[o7] + 0.125f*s[o8]);
87 
88  s+=s_istep;
89  pgi += gi_istep;
90  pgj += gj_istep;
91  }
92 
93  // Zero the last elements in the rows
94  *pgi = 0;
95  *pgj = 0;
96 
97  // Move to next row
98  s_data += s_jstep;
99  gi_data += gi_jstep;
100  gj_data += gj_jstep;
101  }
102 
103  // Zero the first and last rows
104  for (unsigned i=0;i<ni;++i)
105  {
106  *gi=0; gi+=gi_istep;
107  *gj=0; gj+=gj_istep;
108  *gi_data = 0; gi_data+=gi_istep;
109  *gj_data = 0; gj_data+=gj_istep;
110  }
111 }
112 
113 //: Compute gradients of single plane of 2D data using 3x3 Sobel filters
114 // Computes both i and j gradients of an ni x nj plane of data
115 template <>
116 void vil_sobel_3x3_1plane(const unsigned char* src,
117  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
118  double* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
119  double* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
120  unsigned ni, unsigned nj)
121 {
122  const unsigned char* s_data = src;
123  double *gi_data = gi;
124  double *gj_data = gj;
125 
126  if (ni==0 || nj==0) return;
127  if (ni==1)
128  {
129  // Zero the elements in the column
130  for (unsigned j=0;j<nj;++j)
131  {
132  *gi_data = 0;
133  *gj_data = 0;
134  gi_data += gi_jstep;
135  gj_data += gj_jstep;
136  }
137  return;
138  }
139  if (nj==1)
140  {
141  // Zero the elements in the column
142  for (unsigned i=0;i<ni;++i)
143  {
144  *gi_data = 0;
145  *gj_data = 0;
146  gi_data += gi_istep;
147  gj_data += gj_istep;
148  }
149  return;
150  }
151 
152  // Compute relative grid positions
153  // o1 o2 o3
154  // o4 o5
155  // o6 o7 o8
156  const std::ptrdiff_t o1 = s_jstep - s_istep;
157  const std::ptrdiff_t o2 = s_jstep;
158  const std::ptrdiff_t o3 = s_istep + s_jstep;
159  const std::ptrdiff_t o4 = -s_istep;
160  const std::ptrdiff_t o5 = s_istep;
161  const std::ptrdiff_t o6 = -s_istep - s_jstep;
162  const std::ptrdiff_t o7 = -s_jstep;
163  const std::ptrdiff_t o8 = s_istep - s_jstep;
164 
165  const unsigned ni1 = ni-1;
166  const unsigned nj1 = nj-1;
167 
168  s_data += s_istep + s_jstep;
169  gi_data += gi_jstep;
170  gj_data += gj_jstep;
171 
172  for (unsigned j=1;j<nj1;++j)
173  {
174  const unsigned char* s = s_data;
175  double* pgi = gi_data;
176  double* pgj = gj_data;
177 
178  // Zero the first elements in the rows
179  *pgi = 0; pgi+=gi_istep;
180  *pgj = 0; pgj+=gj_istep;
181 
182  for (unsigned i=1;i<ni1;++i)
183  {
184  // Compute gradient in i
185  // Note: Multiply each element individually
186  // to ensure conversion to double before addition
187  *pgi = (0.125*s[o3] + 0.25*s[o5] + 0.125*s[o8])
188  - (0.125*s[o1] + 0.25*s[o4] + 0.125*s[o6]);
189  // Compute gradient in j
190  *pgj = (0.125*s[o1] + 0.25*s[o2] + 0.125*s[o3])
191  - (0.125*s[o6] + 0.25*s[o7] + 0.125*s[o8]);
192 
193  s+=s_istep;
194  pgi += gi_istep;
195  pgj += gj_istep;
196  }
197 
198  // Zero the last elements in the rows
199  *pgi = 0;
200  *pgj = 0;
201 
202  // Move to next row
203  s_data += s_jstep;
204  gi_data += gi_jstep;
205  gj_data += gj_jstep;
206  }
207 
208  // Zero the first and last rows
209  for (unsigned i=0;i<ni;++i)
210  {
211  *gi=0; gi+=gi_istep;
212  *gj=0; gj+=gj_istep;
213  *gi_data = 0; gi_data+=gi_istep;
214  *gj_data = 0; gj_data+=gj_istep;
215  }
216 }
217 
218 //: Compute gradients of single plane of 2D data using 3x3 Sobel filters
219 // Computes both x and j gradients of an nx x nj plane of data
220 template <>
221 void vil_sobel_3x3_1plane(const float* src,
222  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
223  float* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
224  float* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
225  unsigned ni, unsigned nj)
226 {
227  const float* s_data = src;
228  float *gi_data = gi;
229  float *gj_data = gj;
230 
231  if (ni==0 || nj==0) return;
232  if (ni==1)
233  {
234  // Zero the elements in the column
235  for (unsigned j=0;j<nj;++j)
236  {
237  *gi_data = 0;
238  *gj_data = 0;
239  gi_data += gi_jstep;
240  gj_data += gj_jstep;
241  }
242  return;
243  }
244  if (nj==1)
245  {
246  // Zero the elements in the column
247  for (unsigned i=0;i<ni;++i)
248  {
249  *gi_data = 0;
250  *gj_data = 0;
251  gi_data += gi_istep;
252  gj_data += gj_istep;
253  }
254  return;
255  }
256 
257  // Compute relative grid positions
258  // o1 o2 o3
259  // o4 o5
260  // o6 o7 o8
261  const std::ptrdiff_t o1 = s_jstep - s_istep;
262  const std::ptrdiff_t o2 = s_jstep;
263  const std::ptrdiff_t o3 = s_istep + s_jstep;
264  const std::ptrdiff_t o4 = -s_istep;
265  const std::ptrdiff_t o5 = s_istep;
266  const std::ptrdiff_t o6 = -s_istep - s_jstep;
267  const std::ptrdiff_t o7 = -s_jstep;
268  const std::ptrdiff_t o8 = s_istep - s_jstep;
269 
270  const unsigned ni1 = ni-1;
271  const unsigned nj1 = nj-1;
272 
273  s_data += s_istep + s_jstep;
274  gi_data += gi_jstep;
275  gj_data += gj_jstep;
276 
277  for (unsigned j=1;j<nj1;++j)
278  {
279  const float* s = s_data;
280  float* pgi = gi_data;
281  float* pgj = gj_data;
282 
283  // Zero the first elements in the rows
284  *pgi = 0; pgi+=gi_istep;
285  *pgj = 0; pgj+=gj_istep;
286 
287  for (unsigned i=1;i<ni1;++i)
288  {
289  // Compute gradient in i
290  *pgi = 0.125f*(s[o3]+s[o8] - (s[o1]+s[o6])) + 0.25f*(s[o5]-s[o4]);
291  // Compute gradient in j
292  *pgj = 0.125f*(s[o1]+s[o3] - (s[o6]+s[o8])) + 0.25f*(s[o2]-s[o7]);
293 
294  s+=s_istep;
295  pgi += gi_istep;
296  pgj += gj_istep;
297  }
298 
299  // Zero the last elements in the rows
300  *pgi = 0;
301  *pgj = 0;
302 
303  // Move to next row
304  s_data += s_jstep;
305  gi_data += gi_jstep;
306  gj_data += gj_jstep;
307  }
308 
309  // Zero the first and last rows
310  for (unsigned i=0;i<ni;++i)
311  {
312  *gi=0; gi+=gi_istep;
313  *gj=0; gj+=gj_istep;
314  *gi_data = 0; gi_data+=gi_istep;
315  *gj_data = 0; gj_data+=gj_istep;
316  }
317 }
318 
319 //: Compute gradients of single plane of 2D data using 3x3 Sobel filters
320 // Computes both x and j gradients of an nx x nj plane of data
321 template <>
322 void vil_sobel_3x3_1plane(const double* src,
323  std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep,
324  double* gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep,
325  double* gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep,
326  unsigned ni, unsigned nj)
327 {
328  const double* s_data = src;
329  double *gi_data = gi;
330  double *gj_data = gj;
331 
332  if (ni==0 || nj==0) return;
333  if (ni==1)
334  {
335  // Zero the elements in the column
336  for (unsigned j=0;j<nj;++j)
337  {
338  *gi_data = 0;
339  *gj_data = 0;
340  gi_data += gi_jstep;
341  gj_data += gj_jstep;
342  }
343  return;
344  }
345  if (nj==1)
346  {
347  // Zero the elements in the column
348  for (unsigned i=0;i<ni;++i)
349  {
350  *gi_data = 0;
351  *gj_data = 0;
352  gi_data += gi_istep;
353  gj_data += gj_istep;
354  }
355  return;
356  }
357 
358  // Compute relative grid positions
359  // o1 o2 o3
360  // o4 o5
361  // o6 o7 o8
362  const std::ptrdiff_t o1 = s_jstep - s_istep;
363  const std::ptrdiff_t o2 = s_jstep;
364  const std::ptrdiff_t o3 = s_istep + s_jstep;
365  const std::ptrdiff_t o4 = -s_istep;
366  const std::ptrdiff_t o5 = s_istep;
367  const std::ptrdiff_t o6 = -s_istep - s_jstep;
368  const std::ptrdiff_t o7 = -s_jstep;
369  const std::ptrdiff_t o8 = s_istep - s_jstep;
370 
371  const unsigned ni1 = ni-1;
372  const unsigned nj1 = nj-1;
373 
374  s_data += s_istep + s_jstep;
375  gi_data += gi_jstep;
376  gj_data += gj_jstep;
377 
378  for (unsigned j=1;j<nj1;++j)
379  {
380  const double* s = s_data;
381  double* pgi = gi_data;
382  double* pgj = gj_data;
383 
384  // Zero the first elements in the rows
385  *pgi = 0; pgi+=gi_istep;
386  *pgj = 0; pgj+=gj_istep;
387 
388  for (unsigned i=1;i<ni1;++i)
389  {
390  // Compute gradient in i
391  *pgi = 0.125*(s[o3]+s[o8] - (s[o1]+s[o6])) + 0.25*(s[o5]-s[o4]);
392  // Compute gradient in j
393  *pgj = 0.125*(s[o1]+s[o3] - (s[o6]+s[o8])) + 0.25*(s[o2]-s[o7]);
394 
395  s+=s_istep;
396  pgi += gi_istep;
397  pgj += gj_istep;
398  }
399 
400  // Zero the last elements in the rows
401  *pgi = 0;
402  *pgj = 0;
403 
404  // Move to next row
405  s_data += s_jstep;
406  gi_data += gi_jstep;
407  gj_data += gj_jstep;
408  }
409 
410  // Zero the first and last rows
411  for (unsigned i=0;i<ni;++i)
412  {
413  *gi=0; gi+=gi_istep;
414  *gj=0; gj+=gj_istep;
415  *gi_data = 0; gi_data+=gi_istep;
416  *gj_data = 0; gj_data+=gj_istep;
417  }
418 }
void vil_sobel_3x3_1plane(const unsigned char *src, std::ptrdiff_t s_istep, std::ptrdiff_t s_jstep, float *gi, std::ptrdiff_t gi_istep, std::ptrdiff_t gi_jstep, float *gj, std::ptrdiff_t gj_istep, std::ptrdiff_t gj_jstep, unsigned ni, unsigned nj)
Compute gradients of single plane of 2D data using 3x3 Sobel filters.
Apply 3x3 sobel operator to image data.