latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiSquareConvolution.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 13.10.2000 00030 * revisions ..: $Id: ltiSquareConvolution.h,v 1.8 2006/02/08 11:55:56 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_SQUARE_CONVOLUTION_H_ 00034 #define _LTI_SQUARE_CONVOLUTION_H_ 00035 00036 #include "ltiObject.h" 00037 #include "ltiMatrix.h" 00038 #include "ltiFilter.h" 00039 00040 namespace lti { 00041 /** 00042 * This is an efficient implementation of the convolution with a 00043 * square or rectangular kernel. The template parameter T defines 00044 * the type of the matrix or vector to be filtered, and A represents 00045 * the accumulator class, which allows different modi for the 00046 * convolution. 00047 * 00048 * The class A must implement following members: 00049 * - constructor(int) for initialization with the value 0. 00050 * - operator+=(T x) for accumulation, 00051 * - operator-=(T x) for "deaccumulation", 00052 * - operator=(T x) for assignation of a value of type T 00053 * - operator/(T x,T y) const returns f(x)/y instead of x/y. 00054 * For example for L2 norm f(x) = sqrt(x). 00055 * - operator T() const returns the contents casted to type T 00056 * 00057 * This way, you can use any simple-types (as int, char, double...) 00058 * as accumulator for a linear filter, or a user-defined class for a 00059 * region normalization with any norm! For an example of an accumulator 00060 * class see lti::chrominanzHistogram::l2accumulator<T>. 00061 * 00062 * Note that for convolving a rectangular filter kernel with a channel8, 00063 * you shoud use an instance squareConvolution<ubyte,int>. If you forget 00064 * the "int" parameter, some quite noisy overflowing effects should be 00065 * expected! 00066 * 00067 * @see parameters 00068 */ 00069 template<class T,class A=T> 00070 class squareConvolution : public filter { 00071 public: 00072 00073 /** 00074 * the parameters for the class squareConvolution 00075 */ 00076 class parameters : public filter::parameters { 00077 public: 00078 /** 00079 * default constructor to initialize a kernel of k x k size centered 00080 * at (0,0) 00081 */ 00082 parameters(const int k = 3) : filter::parameters() { 00083 initSquare(k); 00084 } 00085 00086 /** 00087 * copy constructor 00088 * @param other the parameters object to be copied 00089 */ 00090 parameters(const parameters& other) 00091 : filter::parameters() { 00092 copy(other); 00093 }; 00094 00095 /** 00096 * destructor 00097 */ 00098 ~parameters() {}; 00099 00100 /** 00101 * returns name of this type 00102 */ 00103 const char* getTypeName() const { 00104 return "squareConvolution::parameters"; 00105 }; 00106 00107 /** 00108 * copy the contents of a parameters object 00109 * @param other the parameters object to be copied 00110 * @return a reference to this parameters object 00111 */ 00112 parameters& copy(const parameters& other) { 00113 # ifndef _LTI_MSC_6 00114 // MS Visual C++ 6 is not able to compile this... 00115 filter::parameters::copy(other); 00116 # else 00117 // ...so we have to use this workaround. 00118 // Conditional on that, copy may not be virtual. 00119 filter::parameters& (filter::parameters::* p_copy) 00120 (const filter::parameters&) = 00121 filter::parameters::copy; 00122 (this->*p_copy)(other); 00123 # endif 00124 00125 kernelSize = other.kernelSize; 00126 kernelNorm = other.kernelNorm; 00127 00128 return *this; 00129 }; 00130 00131 /** 00132 * returns a pointer to a clone of the parameters 00133 */ 00134 virtual functor::parameters* clone() const { 00135 return new parameters(*this); 00136 }; 00137 00138 /** 00139 * write the parameters in the given ioHandler 00140 * @param handler the ioHandler to be used 00141 * @param complete if true (the default) the enclosing begin/end will 00142 * be also written, otherwise only the data block will be 00143 * written. 00144 * @return true if write was successful 00145 */ 00146 # ifndef _LTI_MSC_6 00147 virtual bool write(ioHandler& handler,const bool complete=true) const 00148 # else 00149 bool writeMS(ioHandler& handler,const bool complete=true) const 00150 # endif 00151 { 00152 bool b = true; 00153 if (complete) { 00154 b = handler.writeBegin(); 00155 } 00156 00157 if (b) { 00158 lti::write(handler,"kernelSize",kernelSize); 00159 lti::write(handler,"kernelNorm",kernelNorm); 00160 } 00161 00162 # ifndef _LTI_MSC_6 00163 // This is the standard C++ code, which MS Visual C++ 6 is not 00164 // able to compile... 00165 b = b && filter::parameters::write(handler,false); 00166 # else 00167 bool (modifier::parameters::* p_writeMS)(ioHandler&, 00168 const bool) const = 00169 modifier::parameters::writeMS; 00170 b = b && (this->*p_writeMS)(handler,false); 00171 # endif 00172 00173 if (complete) { 00174 b = b && handler.writeEnd(); 00175 } 00176 00177 return b; 00178 } 00179 00180 # ifdef _LTI_MSC_6 00181 virtual bool write(ioHandler& handler, 00182 const bool complete = true) const { 00183 // ...we need this workaround to cope with another really 00184 // awful MSVC bug. 00185 return writeMS(handler,complete); 00186 } 00187 # endif 00188 00189 /** 00190 * read the parameters from the given ioHandler 00191 * @param handler the ioHandler to be used 00192 * @param complete if true (the default) the enclosing begin/end will 00193 * be also read, otherwise only the data block will be read. 00194 * @return true if write was successful 00195 */ 00196 # ifndef _LTI_MSC_6 00197 virtual bool read(ioHandler& handler,const bool complete = true) 00198 # else 00199 bool readMS(ioHandler& handler,const bool complete=true) 00200 # endif 00201 { 00202 bool b = true; 00203 if (complete) { 00204 b = handler.readBegin(); 00205 } 00206 00207 if (b) { 00208 lti::read(handler,"kernelSize",kernelSize); 00209 lti::read(handler,"kernelNorm",kernelNorm); 00210 } 00211 00212 # ifndef _LTI_MSC_6 00213 // This is the standard C++ code, which MS Visual C++ 6 is not 00214 // able to compile... 00215 b = b && filter::parameters::read(handler,false); 00216 # else 00217 bool (modifier::parameters::* p_readMS)(ioHandler&,const bool) = 00218 modifier::parameters::readMS; 00219 b = b && (this->*p_readMS)(handler,false); 00220 # endif 00221 00222 if (complete) { 00223 b = b && handler.readEnd(); 00224 } 00225 00226 return b; 00227 } 00228 00229 # ifdef _LTI_MSC_6 00230 virtual bool read(ioHandler& handler,const bool complete=true) { 00231 // ...we need this workaround to cope with another really awful MSVC 00232 // bug. 00233 return readMS(handler,complete); 00234 } 00235 # endif 00236 00237 /** 00238 * The rectangular kernel will have the value "1/kernelNorm" 00239 * between the limits specified by this rectangle. When 00240 * convolving a vector, the "y" coordinates of this kernelSize 00241 * will be ignored. 00242 * Default value: rectangle(-1,-1,1,1), i.e. a 3x3 kernel 00243 */ 00244 rectangle kernelSize; 00245 00246 /** 00247 * The norm is the value which will be considered as "1.0" for the 00248 * elements of the kernel. The default value is 9 (for a 3x3 kernel). 00249 * You can consider the square filter always as a kernel with nxn 00250 * "ones". 00251 * After the convolution, the resulting image will be divide by this 00252 * value. The implementation combines the convolution with this 00253 * normalization! 00254 */ 00255 T kernelNorm; 00256 00257 /** 00258 * Initialize the parameters for a symmetric square kernel sizeXsize, 00259 * where the sum of all elements equals one. 00260 * If the size is even, it will be "fixed" to the next odd number 00261 */ 00262 void initSquare(const int size) { 00263 int realSize(size); 00264 if ((size % 2) == 0) { 00265 realSize++; 00266 } 00267 00268 kernelNorm = static_cast<T>(realSize*realSize); 00269 00270 realSize/=2; 00271 kernelSize.ul.x = -realSize; 00272 kernelSize.ul.y = -realSize; 00273 kernelSize.br.x = +realSize; 00274 kernelSize.br.y = +realSize; 00275 }; 00276 00277 }; 00278 00279 /** 00280 * default constructor 00281 */ 00282 squareConvolution(); 00283 00284 /** 00285 * constructor to initialize the parameters with an square filter 00286 * of k x k size. 00287 */ 00288 squareConvolution(const int k); 00289 00290 /** 00291 * copy constructor 00292 * @param other the object to be copied 00293 */ 00294 squareConvolution(const squareConvolution& other); 00295 00296 /** 00297 * destructor 00298 */ 00299 virtual ~squareConvolution(); 00300 00301 /** 00302 * returns the name of this type ("squareConvolution") 00303 */ 00304 virtual const char* getTypeName() const; 00305 00306 /** 00307 * operates on the given %parameter. 00308 * @param srcdest matrix<T> with the source data. The result 00309 * will be left here too. 00310 * @return true if successful, false otherwise. 00311 */ 00312 bool apply(matrix<T>& srcdest) const; 00313 00314 /** 00315 * operates on the given %parameter. 00316 * @param srcdest vector<T> with the source data. The result 00317 * will be left here too. 00318 * @return true if successful, false otherwise. 00319 */ 00320 bool apply(vector<T>& srcdest) const; 00321 00322 /** 00323 * operates on a copy of the given %parameters. 00324 * @param src matrix<T> with the source data. 00325 * @param dest matrix<T> where the result will be left. 00326 * @return true if successful, false otherwise. 00327 */ 00328 bool apply(const matrix<T>& src,matrix<T>& dest) const; 00329 00330 /** 00331 * operates on a copy of the given %parameters. 00332 * @param src vector<T> with the source data. 00333 * @param dest vector<T> where the result will be left. 00334 * @return true if successful, false otherwise. 00335 */ 00336 bool apply(const vector<T>& src,vector<T>& dest) const; 00337 00338 /** 00339 * copy data of "other" functor. 00340 * @param other the functor to be copied 00341 * @return a reference to this functor object 00342 */ 00343 squareConvolution& copy(const squareConvolution& other); 00344 00345 /** 00346 * returns a pointer to a clone of this functor. 00347 */ 00348 virtual functor* clone() const; 00349 00350 /** 00351 * returns used parameters 00352 */ 00353 const parameters& getParameters() const; 00354 00355 protected: 00356 /** 00357 * applies the vertical part of the kernel to the matrix 00358 * @param src matrix<T> with the source data. 00359 * @param dest matrix<T> where the result will be left. 00360 * @result a reference to the <code>dest</code>. 00361 */ 00362 matrix<T>& applyCol(const matrix<T>& src,matrix<T>& dest) const; 00363 00364 private: 00365 /** 00366 * calculate the real index in an vector of size srcSize for a 00367 * mirrored boundary 00368 */ 00369 inline int getMirrorIndex(const int& x, 00370 const int& srcSize, 00371 bool& mirror) const; 00372 00373 }; 00374 00375 00376 00377 } 00378 00379 #include "ltiSquareConvolution_template.h" 00380 00381 #endif