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