Fawkes API  Fawkes Development Version
laplace.cpp
1 
2 /***************************************************************************
3  * laplace.cpp - Implementation of a laplace filter
4  *
5  * Created: Thu Jun 16 16:30:23 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/laplace.h>
25 
26 #include <cmath>
27 #include <cstdlib>
28 
29 #ifdef HAVE_IPP
30 # include <ippi.h>
31 #elif defined(HAVE_OPENCV)
32 # include <opencv2/opencv.hpp>
33 #else
34 # error "Neither IPP nor OpenCV available"
35 #endif
36 
37 namespace firevision {
38 
39 /** @class FilterLaplace <fvfilters/laplace.h>
40  * Laplacian filter.
41  * Laplacian of Gaussian filter.
42  * @author Tim Niemueller
43  */
44 
45 /** Constructor. */
47 {
48  kernel = NULL;
49  kernel_float = NULL;
50 }
51 
52 /** Constructor.
53  * @param sigma sigma for Laplacian
54  * @param size size of kernel
55  * @param scale scale factor
56  */
57 FilterLaplace::FilterLaplace(float sigma, unsigned int size, float scale) : Filter("FilterLaplace")
58 {
59  kernel_size = size;
60  kernel = (int *)malloc((size_t)size * (size_t)size * sizeof(int));
61  calculate_kernel(kernel, sigma, size, scale);
62 #ifdef HAVE_OPENCV
63  kernel_float = (float *)malloc((size_t)size * (size_t)size * sizeof(float));
64  for (unsigned int i = 0; i < size * size; ++i) {
65  kernel_float[i] = kernel[i];
66  }
67 #endif
68 }
69 
70 /** Destructor. */
72 {
73  if (kernel != NULL) {
74  free(kernel);
75  }
76  if (kernel_float != NULL) {
77  free(kernel_float);
78  }
79 }
80 
81 void
83 {
84 #if defined(HAVE_IPP)
85  IppiSize size;
86  size.width = src_roi[0]->width - kernel_size;
87  size.height = src_roi[0]->height - kernel_size;
88 
89  IppStatus status;
90 
91  if (kernel == NULL) {
92  // base + number of bytes to line y + pixel bytes
93  status = ippiFilterLaplace_8u_C1R(src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
94  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
95  src_roi[0]->line_step,
99  size,
100  ippMskSize5x5);
101  } else {
102  IppiSize ksize = {kernel_size, kernel_size};
103  IppiPoint kanchor = {(kernel_size + 1) / 2, (kernel_size + 1) / 2};
104 
105  /*
106  std::cout << "steps: " << src_roi[0]->line_step << " " << dst_roi->line_step << std::endl
107  << "ksize: " << ksize.width << " x " << ksize.height << std::endl
108  << "kanchor: " << kanchor.x << "," << kanchor.y << std::endl;
109  */
110 
111  status =
112  ippiFilter_8u_C1R(src[0] + ((src_roi[0]->start.y + kernel_size / 2) * src_roi[0]->line_step)
113  + ((src_roi[0]->start.x + kernel_size / 2) * src_roi[0]->pixel_step),
114  src_roi[0]->line_step,
115  dst + ((dst_roi->start.y + kernel_size / 2) * dst_roi->line_step)
116  + ((dst_roi->start.x + kernel_size / 2) * dst_roi->pixel_step),
118  size,
119  kernel,
120  ksize,
121  kanchor,
122  1);
123  }
124 
125  if (status != ippStsNoErr) {
126  throw fawkes::Exception("Laplace filter failed with %i\n", status);
127  }
128 
129  /*
130  std::cout << "FilterLaplace: ippiFilterLaplace exit code: " << std::flush;
131  switch (status) {
132  case ippStsNoErr:
133  std::cout << "ippStsNoErr";
134  break;
135  case ippStsNullPtrErr:
136  std::cout << "ippStsNullPtrErr";
137  break;
138  case ippStsSizeErr:
139  std::cout << "ippStsSizeErr";
140  break;
141  case ippStsStepErr:
142  std::cout << "ippStsStepErr";
143  break;
144  case ippStsMaskSizeErr:
145  std::cout << "ippStsMaskSizeErr";
146  break;
147  default:
148  std::cout << "Unknown status " << status;
149  }
150  std::cout << std::endl;
151  */
152 #elif defined(HAVE_OPENCV)
153  if ((dst == NULL) || (dst == src[0])) {
154  throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place");
155  }
156 
157  cv::Mat srcm(src_roi[0]->height,
158  src_roi[0]->width,
159  CV_8UC1,
160  src[0] + (src_roi[0]->start.y * src_roi[0]->line_step)
161  + (src_roi[0]->start.x * src_roi[0]->pixel_step),
162  src_roi[0]->line_step);
163 
164  cv::Mat dstm(dst_roi->height,
165  dst_roi->width,
166  CV_8UC1,
168  + (dst_roi->start.x * dst_roi->pixel_step),
169  dst_roi->line_step);
170 
171  if (kernel_float == NULL) {
172  cv::Laplacian(srcm, dstm, /* ddepth */ CV_8UC1, /* ksize */ 5);
173  } else {
174  cv::Mat kernel(kernel_size, kernel_size, CV_32F, kernel_float);
175  cv::Point kanchor((kernel_size + 1) / 2, (kernel_size + 1) / 2);
176  cv::filter2D(srcm, dstm, /* ddepth */ -1, kernel, kanchor);
177  }
178 #endif
179 }
180 
181 /** Calculate a Laplacian of Gaussian kernel.
182  * The kernel is calculated with the formula
183  * \f[
184  * roundf( \frac{-1}{\pi * \sigma^4} *
185  * ( 1 - \frac{w^2 + h^2}{2 * \sigma^2} )
186  * * e^{-\frac{w^2 + h^2}{2 * \sigma^2}} * \mathtt{scale} )
187  * \f]
188  *
189  * @param kernel buffer contains kernel upon return
190  * @param sigma sigma for formula
191  * @param size kernel is of quadratic size \f$\mathtt{size} \times \mathtt{size}\f$
192  * @param scale scale parameter in formula
193  */
194 void
195 FilterLaplace::calculate_kernel(int *kernel, float sigma, unsigned int size, float scale)
196 {
197  // title "LoGFUNC_________________________________________"
198 
199  /*
200  std::cout.precision( 5 );
201  std::cout.width( 10 );
202 
203  std::cout << "Discrete Laplacian kernel for sigma=" << sigma
204  << " quadratic size of " << size
205  << " scaled by " << scale << std::endl;
206  */
207  for (int h = (-(int)(size / 2)); h <= (int)((size - 1) / 2); ++h) {
208  for (int w = (-(int)(size / 2)); w <= (int)((size - 1) / 2); ++w) {
209  //float v = ( (w*w + h*h - 2 * sigma * sigma) / sigma * sigma * sigma * sigma )
210  //* exp( -( (w*w + h*h) / (2 * sigma * sigma) ));
211  int v = (int)roundf(-1 / (M_PI * sigma * sigma * sigma * sigma)
212  * (1 - ((w * w + h * h) / (2 * sigma * sigma)))
213  * exp(-((w * w + h * h) / (2 * sigma * sigma))) * scale);
214  // std::cout << " " << v << std::flush;
215  kernel[(h + (size / 2)) * size + (w + (size / 2))] = v;
216  }
217  //std::cout << std::endl;
218  }
219 
220  /*
221  for (int h = 0; h < size; ++h) {
222  for (int w = 0; w < size; ++w) {
223  std::cout << " " << kernel[ h * size + w ] << std::flush;
224  }
225  std::cout << std::endl;
226  }
227  */
228 }
229 
230 } // end namespace firevision
Base class for exceptions in Fawkes.
Definition: exception.h:36
~FilterLaplace()
Destructor.
Definition: laplace.cpp:71
virtual void apply()
Apply the filter.
Definition: laplace.cpp:82
FilterLaplace()
Constructor.
Definition: laplace.cpp:46
static void calculate_kernel(int *kernel_buffer, float sigma, unsigned int size, float scale)
Calculate a Laplacian of Gaussian kernel.
Definition: laplace.cpp:195
Filter interface.
Definition: filter.h:33
ROI ** src_roi
Source ROIs, dynamically allocated by Filter ctor.
Definition: filter.h:66
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
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