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