Fawkes API  Fawkes Development Version
sobel.cpp
1 
2 /***************************************************************************
3  * sobel.cpp - Implementation of a Sobel filter
4  *
5  * Created: Thu May 12 13:20:43 2005
6  * Copyright 2005-2012 Tim Niemueller [www.niemueller.de]
7  ****************************************************************************/
8 
9 /* This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version. A runtime exception applies to
13  * this software (see LICENSE.GPL_WRE file mentioned below for details).
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
21  */
22 
23 #include <core/exception.h>
24 #include <fvfilters/sobel.h>
25 
26 #ifdef HAVE_IPP
27 # include <ippi.h>
28 #elif defined(HAVE_OPENCV)
29 # include <opencv2/opencv.hpp>
30 #else
31 # error "Neither IPP nor OpenCV available"
32 #endif
33 
34 namespace firevision {
35 
36 /** @class FilterSobel <fvfilters/sobel.h>
37  * Sobel filter.
38  * @author Tim Niemueller
39  */
40 
41 /** Constructor.
42  * @param ori edge orientation
43  */
44 FilterSobel::FilterSobel(orientation_t ori) : Filter("FilterSobel")
45 {
46 }
47 
48 /** Generate a sobel kernel for the given orientation.
49  * @param k matrix for the kernel of size 3x3, contains three
50  * lines concatenated into an one dimensional array.
51  * @param ori requested orientation of the filter
52  */
53 static inline void
54 generate_kernel(
55 #ifdef HAVE_IPP
56  int *k,
57 #else
58  float *k,
59 #endif
60  orientation_t ori)
61 {
62  // k is the kernel
63  switch (ori) {
64  case ORI_DEG_0:
65  case ORI_DEG_360:
66  k[0] = 1;
67  k[1] = 2;
68  k[2] = 1;
69  k[3] = 0;
70  k[4] = 0;
71  k[5] = 0;
72  k[6] = -1;
73  k[7] = -2;
74  k[8] = -1;
75  break;
76  case ORI_DEG_45:
77  k[0] = 2;
78  k[1] = 1;
79  k[2] = 0;
80  k[3] = 1;
81  k[4] = 0;
82  k[5] = -1;
83  k[6] = 0;
84  k[7] = -1;
85  k[8] = -2;
86  break;
87  case ORI_DEG_90:
88  k[0] = 1;
89  k[1] = 0;
90  k[2] = -1;
91  k[3] = 2;
92  k[4] = 0;
93  k[5] = -2;
94  k[6] = 1;
95  k[7] = 0;
96  k[8] = -1;
97  break;
98  case ORI_DEG_135:
99  k[0] = 0;
100  k[1] = -1;
101  k[2] = -2;
102  k[3] = 1;
103  k[4] = 0;
104  k[5] = -1;
105  k[6] = 2;
106  k[7] = 1;
107  k[8] = 0;
108  break;
109  case ORI_DEG_180:
110  k[0] = -1;
111  k[1] = -2;
112  k[2] = -1;
113  k[3] = 0;
114  k[4] = 0;
115  k[5] = 0;
116  k[6] = 1;
117  k[7] = 2;
118  k[8] = 1;
119  break;
120  case ORI_DEG_225:
121  k[0] = -2;
122  k[1] = -1;
123  k[2] = 0;
124  k[3] = -1;
125  k[4] = 0;
126  k[5] = 1;
127  k[6] = 0;
128  k[7] = 1;
129  k[8] = 2;
130  break;
131  case ORI_DEG_270:
132  k[0] = -1;
133  k[1] = 0;
134  k[2] = 1;
135  k[3] = -2;
136  k[4] = 0;
137  k[5] = 2;
138  k[6] = -1;
139  k[7] = 0;
140  k[8] = 1;
141  break;
142  case ORI_DEG_315:
143  k[0] = 0;
144  k[1] = 1;
145  k[2] = 2;
146  k[3] = -1;
147  k[4] = 0;
148  k[5] = 1;
149  k[6] = -2;
150  k[7] = -1;
151  k[8] = 0;
152  break;
153  default: throw fawkes::Exception("Cannot generate Sobel kernel for the given orientation"); break;
154  }
155 }
156 
157 void
159 {
160  shrink_region(src_roi[0], 3);
162 
163 #if defined(HAVE_IPP)
164  IppiSize size;
165  size.width = src_roi[0]->width;
166  size.height = src_roi[0]->height;
167 
168  IppStatus status;
169 
170  if (ori[0] == ORI_HORIZONTAL) {
171  // base + number of bytes to line y + pixel bytes
172  status = ippiFilterSobelHoriz_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
173  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
174  src_roi[0]->line_step,
176  + (dst_roi->start.x * dst_roi->pixel_step),
178  size);
179  } else if (ori[0] == ORI_VERTICAL) {
180  status = ippiFilterSobelHoriz_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
181  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
182  src_roi[0]->line_step,
184  + (dst_roi->start.x * dst_roi->pixel_step),
186  size);
187 
188  } else if ((ori[0] == ORI_DEG_0) || (ori[0] == ORI_DEG_45) || (ori[0] == ORI_DEG_90)
189  || (ori[0] == ORI_DEG_135) || (ori[0] == ORI_DEG_180) || (ori[0] == ORI_DEG_225)
190  || (ori[0] == ORI_DEG_270) || (ori[0] == ORI_DEG_315) || (ori[0] == ORI_DEG_360)) {
191  Ipp32s kernel[9];
192  generate_kernel(kernel, ori[0]);
193 
194  IppiSize kernel_size;
195  kernel_size.width = kernel_size.height = 3;
196 
197  IppiPoint anchor;
198  anchor.x = anchor.y = 1;
199 
200  status = ippiFilter_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
201  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
202  src_roi[0]->line_step,
204  + (dst_roi->start.x * dst_roi->pixel_step),
206  size,
207  kernel,
208  kernel_size,
209  anchor,
210  /* divisor */ 1);
211 
212  } else {
213  // cout << "FilterSobel: Unsupported direction" << endl;
214  status = ippStsNullPtrErr;
215  }
216 
217  if (status != ippStsNoErr) {
218  throw fawkes::Exception("Sobel filter failed with %i", status);
219  }
220 #elif defined(HAVE_OPENCV)
221  cv::Mat srcm(src_roi[0]->height,
222  src_roi[0]->width,
223  CV_8UC1,
224  src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
225  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
226  src_roi[0]->line_step);
227 
228  if (dst == NULL) {
229  dst = src[0];
230  dst_roi = src_roi[0];
231  }
232 
233  cv::Mat dstm(dst_roi->height,
234  dst_roi->width,
235  CV_8UC1,
237  + (dst_roi->start.x * dst_roi->pixel_step),
238  dst_roi->line_step);
239 
240  if (ori[0] == ORI_HORIZONTAL) {
241  if ((dst == NULL) || (dst == src[0])) {
242  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
243  }
244 
245  cv::Sobel(srcm,
246  dstm,
247  /* ddepth */ -1,
248  /* xorder */ 1,
249  /* yorder */ 0,
250  /* ksize */ 3,
251  /* scale */ 1);
252  } else if (ori[0] == ORI_VERTICAL) {
253  if ((dst == NULL) || (dst == src[0])) {
254  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
255  }
256 
257  cv::Sobel(srcm,
258  dstm,
259  /* ddepth */ -1,
260  /* xorder */ 0,
261  /* yorder */ 1,
262  /* ksize */ 3,
263  /* scale */ 1);
264  } else if ((ori[0] == ORI_DEG_0) || (ori[0] == ORI_DEG_45) || (ori[0] == ORI_DEG_90)
265  || (ori[0] == ORI_DEG_135) || (ori[0] == ORI_DEG_180) || (ori[0] == ORI_DEG_225)
266  || (ori[0] == ORI_DEG_270) || (ori[0] == ORI_DEG_315) || (ori[0] == ORI_DEG_360)) {
267  cv::Mat kernel(3, 3, CV_32F);
268  generate_kernel((float *)kernel.ptr(), ori[0]);
269 
270  cv::filter2D(srcm, dstm, /* ddepth */ -1, kernel, cv::Point(1, 1));
271  } else {
272  throw fawkes::Exception("Unknown filter sobel orientation");
273  }
274 #endif
275 }
276 
277 } // end namespace firevision
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void apply()
Apply the filter.
Definition: sobel.cpp:158
FilterSobel(orientation_t ori=ORI_HORIZONTAL)
Constructor.
Definition: sobel.cpp:44
Filter interface.
Definition: filter.h:33
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:66
void shrink_region(ROI *r, unsigned int n)
This shrinks the regions as needed for a N x N matrix.
Definition: filter.cpp:158
unsigned char ** src
Source buffers, dynamically allocated by Filter ctor.
Definition: filter.h:61
unsigned char * dst
Destination buffer.
Definition: filter.h:63
ROI * dst_roi
Destination ROI.
Definition: filter.h:68
orientation_t * ori
Orientations, one for each source image.
Definition: filter.h:71
unsigned int height
ROI height.
Definition: roi.h:119
fawkes::upoint_t start
ROI start.
Definition: roi.h:115
unsigned int line_step
line step
Definition: roi.h:125
unsigned int width
ROI width.
Definition: roi.h:117
unsigned int pixel_step
pixel step
Definition: roi.h:127
unsigned int x
x coordinate
Definition: types.h:36
unsigned int y
y coordinate
Definition: types.h:37