Fawkes API  Fawkes Development Version
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
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 <fvfilters/sobel.h>
24 
25 #include <core/exception.h>
26 
27 #ifdef HAVE_IPP
28 # include <ippi.h>
29 #elif defined(HAVE_OPENCV)
30 # include <cv.h>
31 #else
32 # error "Neither IPP nor OpenCV available"
33 #endif
34 
35 
36 namespace firevision {
37 #if 0 /* just to make Emacs auto-indent happy */
38 }
39 #endif
40 
41 /** @class FilterSobel <fvfilters/sobel.h>
42  * Sobel filter.
43  * @author Tim Niemueller
44  */
45 
46 /** Constructor.
47  * @param ori edge orientation
48  */
49 FilterSobel::FilterSobel(orientation_t ori)
50  : Filter("FilterSobel")
51 {
52 }
53 
54 
55 /** Generate a sobel kernel for the given orientation.
56  * @param k matrix for the kernel of size 3x3, contains three
57  * lines concatenated into an one dimensional array.
58  * @param ori requested orientation of the filter
59  */
60 static inline void
61 generate_kernel(
62 #ifdef HAVE_IPP
63  int *k,
64 #else
65  float *k,
66 #endif
67  orientation_t ori)
68 {
69  // k is the kernel
70  switch (ori) {
71  case ORI_DEG_0:
72  case ORI_DEG_360:
73  k[0] = 1; k[1] = 2; k[2] = 1;
74  k[3] = 0; k[4] = 0; k[5] = 0;
75  k[6] = -1; k[7] = -2; k[8] = -1;
76  break;
77  case ORI_DEG_45:
78  k[0] = 2; k[1] = 1; k[2] = 0;
79  k[3] = 1; k[4] = 0; k[5] = -1;
80  k[6] = 0; k[7] = -1; k[8] = -2;
81  break;
82  case ORI_DEG_90:
83  k[0] = 1; k[1] = 0; k[2] = -1;
84  k[3] = 2; k[4] = 0; k[5] = -2;
85  k[6] = 1; k[7] = 0; k[8] = -1;
86  break;
87  case ORI_DEG_135:
88  k[0] = 0; k[1] = -1; k[2] = -2;
89  k[3] = 1; k[4] = 0; k[5] = -1;
90  k[6] = 2; k[7] = 1; k[8] = 0;
91  break;
92  case ORI_DEG_180:
93  k[0] = -1; k[1] = -2; k[2] = -1;
94  k[3] = 0; k[4] = 0; k[5] = 0;
95  k[6] = 1; k[7] = 2; k[8] = 1;
96  break;
97  case ORI_DEG_225:
98  k[0] = -2; k[1] = -1; k[2] = 0;
99  k[3] = -1; k[4] = 0; k[5] = 1;
100  k[6] = 0; k[7] = 1; k[8] = 2;
101  break;
102  case ORI_DEG_270:
103  k[0] = -1; k[1] = 0; k[2] = 1;
104  k[3] = -2; k[4] = 0; k[5] = 2;
105  k[6] = -1; k[7] = 0; k[8] = 1;
106  break;
107  case ORI_DEG_315:
108  k[0] = 0; k[1] = 1; k[2] = 2;
109  k[3] = -1; k[4] = 0; k[5] = 1;
110  k[6] = -2; k[7] = -1; k[8] = 0;
111  break;
112  default:
113  throw fawkes::Exception("Cannot generate Sobel kernel for the given orientation");
114  break;
115  }
116 }
117 
118 void
120 {
121  shrink_region(src_roi[0], 3);
123 
124 #if defined(HAVE_IPP)
125  IppiSize size;
126  size.width = src_roi[0]->width;
127  size.height = src_roi[0]->height;
128 
129  IppStatus status;
130 
131  if (ori[0] == ORI_HORIZONTAL) {
132  // base + number of bytes to line y + pixel bytes
133  status = ippiFilterSobelHoriz_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step,
135  size );
136  } else if (ori[0] == ORI_VERTICAL) {
137  status = ippiFilterSobelHoriz_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step,
139  size );
140 
141  } else if ( (ori[0] == ORI_DEG_0) ||
142  (ori[0] == ORI_DEG_45) ||
143  (ori[0] == ORI_DEG_90) ||
144  (ori[0] == ORI_DEG_135) ||
145  (ori[0] == ORI_DEG_180) ||
146  (ori[0] == ORI_DEG_225) ||
147  (ori[0] == ORI_DEG_270) ||
148  (ori[0] == ORI_DEG_315) ||
149  (ori[0] == ORI_DEG_360)
150  ) {
151 
152  Ipp32s kernel[9];
153  generate_kernel(kernel, ori[0]);
154 
155  IppiSize kernel_size;
156  kernel_size.width = kernel_size.height = 3;
157 
158  IppiPoint anchor;
159  anchor.x = anchor.y = 1;
160 
161  status = ippiFilter_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step,
163  size,
164  kernel, kernel_size,
165  anchor,
166  /* divisor */ 1 );
167 
168  } else {
169  // cout << "FilterSobel: Unsupported direction" << endl;
170  status = ippStsNullPtrErr;
171  }
172 
173  if ( status != ippStsNoErr ) {
174  throw fawkes::Exception("Sobel filter failed with %i", status);
175  }
176 #elif defined(HAVE_OPENCV)
177  cv::Mat srcm(src_roi[0]->height, src_roi[0]->width, CV_8UC1,
178  src[0] +
179  (src_roi[0]->start.y * src_roi[0]->line_step) +
180  (src_roi[0]->start.x * src_roi[0]->pixel_step),
181  src_roi[0]->line_step);
182 
183  if (dst == NULL) { dst = src[0]; dst_roi = src_roi[0]; }
184 
185  cv::Mat dstm(dst_roi->height, dst_roi->width, CV_8UC1,
186  dst +
189  dst_roi->line_step);
190 
191  if (ori[0] == ORI_HORIZONTAL) {
192  if ((dst == NULL) || (dst == src[0])) {
193  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
194  }
195 
196  cv::Sobel(srcm, dstm, /* ddepth */ -1, /* xorder */ 1, /* yorder */ 0,
197  /* ksize */ 3, /* scale */ 1);
198  } else if (ori[0] == ORI_VERTICAL) {
199  if ((dst == NULL) || (dst == src[0])) {
200  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
201  }
202 
203  cv::Sobel(srcm, dstm, /* ddepth */ -1, /* xorder */ 0, /* yorder */ 1,
204  /* ksize */ 3, /* scale */ 1);
205  } else if ( (ori[0] == ORI_DEG_0) ||
206  (ori[0] == ORI_DEG_45) ||
207  (ori[0] == ORI_DEG_90) ||
208  (ori[0] == ORI_DEG_135) ||
209  (ori[0] == ORI_DEG_180) ||
210  (ori[0] == ORI_DEG_225) ||
211  (ori[0] == ORI_DEG_270) ||
212  (ori[0] == ORI_DEG_315) ||
213  (ori[0] == ORI_DEG_360)
214  )
215  {
216  cv::Mat kernel(3, 3, CV_32F);
217  generate_kernel((float *)kernel.ptr(), ori[0]);
218 
219  cv::filter2D(srcm, dstm, /* ddepth */ -1, kernel, cv::Point(1, 1));
220  } else {
221  throw fawkes::Exception("Unknown filter sobel orientation");
222 
223  }
224 #endif
225 
226 }
227 
228 } // end namespace firevision
fawkes::point_t start
ROI start.
Definition: roi.h:118
unsigned int x
x coordinate
Definition: types.h:35
unsigned int width
ROI width.
Definition: roi.h:120
virtual void apply()
Apply the filter.
Definition: sobel.cpp:119
void shrink_region(ROI *r, unsigned int n)
This shrinks the regions as needed for a N x N matrix.
Definition: filter.cpp:172
unsigned char ** src
Source buffers, dynamically allocated by Filter ctor.
Definition: filter.h:65
Base class for exceptions in Fawkes.
Definition: exception.h:36
Filter interface.
Definition: filter.h:35
unsigned int y
y coordinate
Definition: types.h:36
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:70
unsigned int height
ROI height.
Definition: roi.h:122
unsigned int line_step
line step
Definition: roi.h:128
unsigned char * dst
Destination buffer.
Definition: filter.h:67
unsigned int pixel_step
pixel step
Definition: roi.h:130
ROI * dst_roi
Destination ROI.
Definition: filter.h:72