laplace.cpp

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

Generated on Tue Feb 22 13:32:15 2011 for Fawkes API by  doxygen 1.4.7