Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * laplace.cpp - Implementation of a laplace filter 00004 * 00005 * Created: Thu Jun 16 16:30:23 2005 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <filters/laplace.h> 00025 00026 #include <core/exception.h> 00027 00028 #include <ippi.h> 00029 #include <cmath> 00030 #include <cstdlib> 00031 00032 namespace firevision { 00033 #if 0 /* just to make Emacs auto-indent happy */ 00034 } 00035 #endif 00036 00037 /** @class FilterLaplace <filters/laplace.h> 00038 * Laplacian filter. 00039 * Laplacian of Gaussian filter. 00040 * @author Tim Niemueller 00041 */ 00042 00043 /** Constructor. */ 00044 FilterLaplace::FilterLaplace() 00045 : Filter("FilterLaplace") 00046 { 00047 kernel = NULL; 00048 } 00049 00050 00051 /** Constructor. 00052 * @param sigma sigma for Laplacian 00053 * @param size size of kernel 00054 * @param scale scale factor 00055 */ 00056 FilterLaplace::FilterLaplace(float sigma, unsigned int size, float scale) 00057 : Filter("FilterLaplace") 00058 { 00059 kernel_size = size; 00060 kernel = (int *)malloc( size * size * sizeof(int) ); 00061 calculate_kernel( kernel, sigma, size, scale ); 00062 } 00063 00064 00065 /** Destructor. */ 00066 FilterLaplace::~FilterLaplace() 00067 { 00068 if ( kernel != NULL ) { 00069 free( kernel ); 00070 } 00071 } 00072 00073 00074 void 00075 FilterLaplace::apply() 00076 { 00077 IppiSize size; 00078 size.width = src_roi[0]->width - kernel_size; 00079 size.height = src_roi[0]->height - kernel_size; 00080 00081 IppStatus status; 00082 00083 if ( kernel == NULL ) { 00084 // base + number of bytes to line y + pixel bytes 00085 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, 00086 dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step, 00087 size, ippMskSize5x5 ); 00088 } else { 00089 IppiSize ksize = { kernel_size, kernel_size }; 00090 IppiPoint kanchor = { (kernel_size + 1) / 2, (kernel_size + 1) / 2 }; 00091 00092 /* 00093 std::cout << "steps: " << src_roi[0]->line_step << " " << dst_roi->line_step << std::endl 00094 << "ksize: " << ksize.width << " x " << ksize.height << std::endl 00095 << "kanchor: " << kanchor.x << "," << kanchor.y << std::endl; 00096 */ 00097 00098 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, 00099 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, 00100 size, kernel, ksize, kanchor, 1 ); 00101 00102 } 00103 00104 if ( status != ippStsNoErr ) { 00105 throw fawkes::Exception("Laplace filter failed with %i\n", status); 00106 } 00107 00108 /* 00109 std::cout << "FilterLaplace: ippiFilterLaplace exit code: " << std::flush; 00110 switch (status) { 00111 case ippStsNoErr: 00112 std::cout << "ippStsNoErr"; 00113 break; 00114 case ippStsNullPtrErr: 00115 std::cout << "ippStsNullPtrErr"; 00116 break; 00117 case ippStsSizeErr: 00118 std::cout << "ippStsSizeErr"; 00119 break; 00120 case ippStsStepErr: 00121 std::cout << "ippStsStepErr"; 00122 break; 00123 case ippStsMaskSizeErr: 00124 std::cout << "ippStsMaskSizeErr"; 00125 break; 00126 default: 00127 std::cout << "Unknown status " << status; 00128 } 00129 std::cout << std::endl; 00130 */ 00131 } 00132 00133 00134 /** Calculate a Laplacian of Gaussian kernel. 00135 * The kernel is calculated with the formula 00136 * \f[ 00137 * roundf( \frac{-1}{\pi * \sigma^4} * 00138 * ( 1 - \frac{w^2 + h^2}{2 * \sigma^2} ) 00139 * * e^{-\frac{w^2 + h^2}{2 * \sigma^2}} * \mathtt{scale} ) 00140 * \f] 00141 * 00142 * @param kernel buffer contains kernel upon return 00143 * @param sigma sigma for formula 00144 * @param size kernel is of quadratic size \f$\mathtt{size} \times \mathtt{size}\f$ 00145 * @param scale scale parameter in formula 00146 */ 00147 void 00148 FilterLaplace::calculate_kernel(int *kernel, float sigma, unsigned int size, float scale) 00149 { 00150 // title "LoGFUNC__________________________________________" 00151 00152 /* 00153 std::cout.precision( 5 ); 00154 std::cout.width( 10 ); 00155 00156 std::cout << "Discrete Laplacian kernel for sigma=" << sigma 00157 << " quadratic size of " << size 00158 << " scaled by " << scale << std::endl; 00159 */ 00160 for (int h = (-(int)(size / 2)); h <= (int)((size - 1) / 2); ++h) { 00161 for (int w = (-(int)(size / 2)); w <= (int)((size - 1) / 2); ++w) { 00162 //float v = ( (w*w + h*h - 2 * sigma * sigma) / sigma * sigma * sigma * sigma ) 00163 //* exp( -( (w*w + h*h) / (2 * sigma * sigma) )); 00164 int v = (int)roundf( - 1/( M_PI * sigma * sigma * sigma * sigma ) * 00165 ( 1 - ( (w*w + h*h) / (2 * sigma * sigma) ) ) 00166 * exp( -( (w*w + h*h) / (2 * sigma * sigma) )) * scale ); 00167 // std::cout << " " << v << std::flush; 00168 kernel[ (h + (size / 2)) * size + (w + (size / 2)) ] = v; 00169 } 00170 //std::cout << std::endl; 00171 } 00172 00173 /* 00174 for (int h = 0; h < size; ++h) { 00175 for (int w = 0; w < size; ++w) { 00176 std::cout << " " << kernel[ h * size + w ] << std::flush; 00177 } 00178 std::cout << std::endl; 00179 } 00180 */ 00181 00182 } 00183 00184 } // end namespace firevision