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
37namespace 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 */
57FilterLaplace::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
81void
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),
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,
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 */
194void
195FilterLaplace::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