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