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 # if CV_MAJOR_VERSION < 2 || (CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION < 4)
30 # include <opencv/cv.h>
31 # endif
32 # include <opencv/cv.hpp>
33 #else
34 # error "Neither IPP nor OpenCV available"
35 #endif
36 
37 namespace firevision {
38 
39 /** @class FilterSobel <fvfilters/sobel.h>
40  * Sobel filter.
41  * @author Tim Niemueller
42  */
43 
44 /** Constructor.
45  * @param ori edge orientation
46  */
47 FilterSobel::FilterSobel(orientation_t ori) : Filter("FilterSobel")
48 {
49 }
50 
51 /** Generate a sobel kernel for the given orientation.
52  * @param k matrix for the kernel of size 3x3, contains three
53  * lines concatenated into an one dimensional array.
54  * @param ori requested orientation of the filter
55  */
56 static inline void
57 generate_kernel(
58 #ifdef HAVE_IPP
59  int *k,
60 #else
61  float *k,
62 #endif
63  orientation_t ori)
64 {
65  // k is the kernel
66  switch (ori) {
67  case ORI_DEG_0:
68  case ORI_DEG_360:
69  k[0] = 1;
70  k[1] = 2;
71  k[2] = 1;
72  k[3] = 0;
73  k[4] = 0;
74  k[5] = 0;
75  k[6] = -1;
76  k[7] = -2;
77  k[8] = -1;
78  break;
79  case ORI_DEG_45:
80  k[0] = 2;
81  k[1] = 1;
82  k[2] = 0;
83  k[3] = 1;
84  k[4] = 0;
85  k[5] = -1;
86  k[6] = 0;
87  k[7] = -1;
88  k[8] = -2;
89  break;
90  case ORI_DEG_90:
91  k[0] = 1;
92  k[1] = 0;
93  k[2] = -1;
94  k[3] = 2;
95  k[4] = 0;
96  k[5] = -2;
97  k[6] = 1;
98  k[7] = 0;
99  k[8] = -1;
100  break;
101  case ORI_DEG_135:
102  k[0] = 0;
103  k[1] = -1;
104  k[2] = -2;
105  k[3] = 1;
106  k[4] = 0;
107  k[5] = -1;
108  k[6] = 2;
109  k[7] = 1;
110  k[8] = 0;
111  break;
112  case ORI_DEG_180:
113  k[0] = -1;
114  k[1] = -2;
115  k[2] = -1;
116  k[3] = 0;
117  k[4] = 0;
118  k[5] = 0;
119  k[6] = 1;
120  k[7] = 2;
121  k[8] = 1;
122  break;
123  case ORI_DEG_225:
124  k[0] = -2;
125  k[1] = -1;
126  k[2] = 0;
127  k[3] = -1;
128  k[4] = 0;
129  k[5] = 1;
130  k[6] = 0;
131  k[7] = 1;
132  k[8] = 2;
133  break;
134  case ORI_DEG_270:
135  k[0] = -1;
136  k[1] = 0;
137  k[2] = 1;
138  k[3] = -2;
139  k[4] = 0;
140  k[5] = 2;
141  k[6] = -1;
142  k[7] = 0;
143  k[8] = 1;
144  break;
145  case ORI_DEG_315:
146  k[0] = 0;
147  k[1] = 1;
148  k[2] = 2;
149  k[3] = -1;
150  k[4] = 0;
151  k[5] = 1;
152  k[6] = -2;
153  k[7] = -1;
154  k[8] = 0;
155  break;
156  default: throw fawkes::Exception("Cannot generate Sobel kernel for the given orientation"); break;
157  }
158 }
159 
160 void
162 {
163  shrink_region(src_roi[0], 3);
165 
166 #if defined(HAVE_IPP)
167  IppiSize size;
168  size.width = src_roi[0]->width;
169  size.height = src_roi[0]->height;
170 
171  IppStatus status;
172 
173  if (ori[0] == ORI_HORIZONTAL) {
174  // base + number of bytes to line y + pixel bytes
175  status = ippiFilterSobelHoriz_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
176  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
177  src_roi[0]->line_step,
179  + (dst_roi->start.x * dst_roi->pixel_step),
181  size);
182  } else if (ori[0] == ORI_VERTICAL) {
183  status = ippiFilterSobelHoriz_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
184  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
185  src_roi[0]->line_step,
187  + (dst_roi->start.x * dst_roi->pixel_step),
189  size);
190 
191  } else if ((ori[0] == ORI_DEG_0) || (ori[0] == ORI_DEG_45) || (ori[0] == ORI_DEG_90)
192  || (ori[0] == ORI_DEG_135) || (ori[0] == ORI_DEG_180) || (ori[0] == ORI_DEG_225)
193  || (ori[0] == ORI_DEG_270) || (ori[0] == ORI_DEG_315) || (ori[0] == ORI_DEG_360)) {
194  Ipp32s kernel[9];
195  generate_kernel(kernel, ori[0]);
196 
197  IppiSize kernel_size;
198  kernel_size.width = kernel_size.height = 3;
199 
200  IppiPoint anchor;
201  anchor.x = anchor.y = 1;
202 
203  status = ippiFilter_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
204  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
205  src_roi[0]->line_step,
207  + (dst_roi->start.x * dst_roi->pixel_step),
209  size,
210  kernel,
211  kernel_size,
212  anchor,
213  /* divisor */ 1);
214 
215  } else {
216  // cout << "FilterSobel: Unsupported direction" << endl;
217  status = ippStsNullPtrErr;
218  }
219 
220  if (status != ippStsNoErr) {
221  throw fawkes::Exception("Sobel filter failed with %i", status);
222  }
223 #elif defined(HAVE_OPENCV)
224  cv::Mat srcm(src_roi[0]->height,
225  src_roi[0]->width,
226  CV_8UC1,
227  src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
228  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
229  src_roi[0]->line_step);
230 
231  if (dst == NULL) {
232  dst = src[0];
233  dst_roi = src_roi[0];
234  }
235 
236  cv::Mat dstm(dst_roi->height,
237  dst_roi->width,
238  CV_8UC1,
240  + (dst_roi->start.x * dst_roi->pixel_step),
241  dst_roi->line_step);
242 
243  if (ori[0] == ORI_HORIZONTAL) {
244  if ((dst == NULL) || (dst == src[0])) {
245  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
246  }
247 
248  cv::Sobel(srcm,
249  dstm,
250  /* ddepth */ -1,
251  /* xorder */ 1,
252  /* yorder */ 0,
253  /* ksize */ 3,
254  /* scale */ 1);
255  } else if (ori[0] == ORI_VERTICAL) {
256  if ((dst == NULL) || (dst == src[0])) {
257  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
258  }
259 
260  cv::Sobel(srcm,
261  dstm,
262  /* ddepth */ -1,
263  /* xorder */ 0,
264  /* yorder */ 1,
265  /* ksize */ 3,
266  /* scale */ 1);
267  } else if ((ori[0] == ORI_DEG_0) || (ori[0] == ORI_DEG_45) || (ori[0] == ORI_DEG_90)
268  || (ori[0] == ORI_DEG_135) || (ori[0] == ORI_DEG_180) || (ori[0] == ORI_DEG_225)
269  || (ori[0] == ORI_DEG_270) || (ori[0] == ORI_DEG_315) || (ori[0] == ORI_DEG_360)) {
270  cv::Mat kernel(3, 3, CV_32F);
271  generate_kernel((float *)kernel.ptr(), ori[0]);
272 
273  cv::filter2D(srcm, dstm, /* ddepth */ -1, kernel, cv::Point(1, 1));
274  } else {
275  throw fawkes::Exception("Unknown filter sobel orientation");
276  }
277 #endif
278 }
279 
280 } // end namespace firevision
firevision::ROI::width
unsigned int width
ROI width.
Definition: roi.h:121
firevision::Filter::src
unsigned char ** src
Source buffers, dynamically allocated by Filter ctor.
Definition: filter.h:70
firevision::FilterSobel::FilterSobel
FilterSobel(orientation_t ori=ORI_HORIZONTAL)
Constructor.
Definition: sobel.cpp:50
firevision::Filter::ori
orientation_t * ori
Orientations, one for each source image.
Definition: filter.h:80
firevision::ROI::height
unsigned int height
ROI height.
Definition: roi.h:123
firevision::Filter::src_roi
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:75
firevision::Filter::shrink_region
void shrink_region(ROI *r, unsigned int n)
This shrinks the regions as needed for a N x N matrix.
Definition: filter.cpp:157
fawkes::upoint_t::y
unsigned int y
y coordinate
Definition: types.h:36
firevision::ROI::pixel_step
unsigned int pixel_step
pixel step
Definition: roi.h:131
firevision::Filter::dst_roi
ROI * dst_roi
Destination ROI.
Definition: filter.h:77
firevision::FilterSobel::apply
virtual void apply()
Definition: sobel.cpp:164
firevision::ROI::start
fawkes::upoint_t start
ROI start.
Definition: roi.h:119
firevision::ROI::line_step
unsigned int line_step
line step
Definition: roi.h:129
fawkes::upoint_t::x
unsigned int x
x coordinate
Definition: types.h:35
firevision::Filter::dst
unsigned char * dst
Destination buffer.
Definition: filter.h:72
fawkes::Exception
Definition: exception.h:39