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