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 .......: ltiLDA.h 00027 * authors ....: Jochen Wickel 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 27.11.2000 00030 * revisions ..: $Id: ltiLDA.h,v 1.7 2006/02/07 18:05:36 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_L_D_A_H_ 00034 #define _LTI_L_D_A_H_ 00035 00036 #include "ltiLapackInterface.h" 00037 00038 #ifdef HAVE_LAPACK 00039 00040 #include "ltiLinearAlgebraFunctor.h" 00041 #include "ltiMatrixInversion.h" 00042 #include "ltiGenEigVectors.h" 00043 #include "ltiMeansFunctor.h" 00044 #include "ltiVarianceFunctor.h" 00045 00046 00047 namespace lti { 00048 /** 00049 * Functor for computing a linear discriminant analysis (LDA). 00050 * 00051 * It uses functors that require the LAPack. 00052 * 00053 * @ingroup lapack 00054 * 00055 * @see \ref lapack 00056 */ 00057 template <class T> 00058 class linearDiscriminantAnalysis : public linearAlgebraFunctor { 00059 public: 00060 /** 00061 * the parameters for the class linearDiscriminantAnalysis 00062 */ 00063 class parameters : public linearAlgebraFunctor::parameters { 00064 public: 00065 /** 00066 * default constructor 00067 */ 00068 parameters(); 00069 00070 /** 00071 * copy constructor 00072 * @param other the parameters object to be copied 00073 */ 00074 parameters(const parameters& other); 00075 00076 /** 00077 * destructor 00078 */ 00079 ~parameters(); 00080 00081 /** 00082 * returns name of this type 00083 */ 00084 const char* getTypeName() const; 00085 00086 /** 00087 * copy the contents of a parameters object 00088 * @param other the parameters object to be copied 00089 * @return a reference to this parameters object 00090 */ 00091 parameters& copy(const parameters& other); 00092 00093 /** 00094 * returns a pointer to a clone of the parameters 00095 */ 00096 virtual functor::parameters* clone() const; 00097 00098 //TODO: comment the parameters of your functor 00099 00100 virtual bool read(ioHandler &handler, const bool complete=true); 00101 virtual bool write(ioHandler &handler, const bool complete=true) const; 00102 00103 /** 00104 * This is the dimension of the reduced vectors. 00105 */ 00106 int resultDim; 00107 00108 /** 00109 * This flag determines, if the functor should determine a 00110 * maximum allowable dimension itself. "Maximum dimension" means 00111 * that the dimension is equal to the number of eigenvalues of 00112 * the covariance matrix which are larger than zero. 00113 * 00114 * Default value: false 00115 */ 00116 bool autoDim; 00117 00118 /** 00119 * If true, singular value decomposition instead of LU 00120 * decomposition is used for inverting the Sw (within-class 00121 * scatter) matrix. This is much safer than the original method, 00122 * since it always computes a meaningful result: for singular 00123 * matrices, it computes the closest approximation. 00124 */ 00125 bool useSVD; 00126 }; 00127 00128 /** 00129 * default constructor 00130 */ 00131 linearDiscriminantAnalysis(); 00132 00133 /** 00134 * copy constructor 00135 * @param other the object to be copied 00136 */ 00137 linearDiscriminantAnalysis(const linearDiscriminantAnalysis& other); 00138 00139 /** 00140 * destructor 00141 */ 00142 virtual ~linearDiscriminantAnalysis(); 00143 00144 /** 00145 * returns the name of this type ("linearDiscriminantAnalysis") 00146 */ 00147 virtual const char* getTypeName() const; 00148 00149 /** 00150 * operates on the given %parameter. 00151 * @param srcdest matrix<T> with the source data. The result 00152 * will be left here too. 00153 * @param labels ivector for each row of the source matrix, this 00154 * vector contains the class label. 00155 * @result true if the LDA could be computed, false otherwise 00156 */ 00157 bool apply(matrix<T>& srcdest, const ivector& labels); 00158 00159 /** 00160 * Computes the linear discriminant analysis for the data given in 00161 * src. It internally stores a transformation matrix which is applied 00162 * to the data. This matrix can be reused by calling one of the 00163 * functions without the label vector. 00164 * 00165 * @param src matrix<T> with the source data. 00166 * @param dest matrix<T> where the result will be left. 00167 * @param labels ivector for each row of the source matrix, this 00168 * vector contains the class label. 00169 * @result true if the LDA could be computed, false otherwise 00170 */ 00171 bool apply(const matrix<T>& src, matrix<T>& dest, 00172 const ivector& labels); 00173 00174 /** 00175 * Computes a linear discriminant analysis for the data given in 00176 * src. This matrix is assumed to contain the data points for 00177 * one class. The computed transformation is stored internally 00178 * and can be used just as a global transformation. The main 00179 * purpose of this method is to be used for LDA classifiers, 00180 * which compute class-wise LDA transforms and classify by 00181 * subsequently applying the LDA's of all classes to the vector, and 00182 * then choosing the class whose mean is closest to the presented 00183 * vector. This method can be used to compute the required LDAs. 00184 * 00185 * @param src matrix<T> with the source data. 00186 * @param dest matrix<T> where the result will be left. 00187 * @param Sb matrix<T> which is the between-class 00188 * scatter matrix of the entire population. 00189 * @result true if the LDA could be computed, false otherwise 00190 */ 00191 bool apply(const matrix<T>& src, matrix<T>& dest, 00192 const matrix<T>& Sb); 00193 00194 00195 /** 00196 * Uses a previously computed transform in order to reduce 00197 * the given data set's dimensionality according to the 00198 * resultDim parameter. 00199 * @param src matrix<T> with the source data. 00200 * @param result matrix<T> with the result data. 00201 * @result true if the LDA could be applied, false otherwise 00202 */ 00203 bool apply(const matrix<T>&src, matrix<T>& result); 00204 00205 /** 00206 * Uses a previously computed transform in order to reduce 00207 * the given data set's dimensionality according to the 00208 * resultDim parameter. 00209 * @param src matrix<T> with the source data. 00210 * @param result matrix<T> with the result data. 00211 * @result true if the LDA could be applied, false otherwise 00212 */ 00213 bool apply(const vector<T>&src, vector<T>& result); 00214 00215 /** 00216 * On-Place version of the transformation. 00217 * @param srcdest matrix<T> with the source data, which will also contain 00218 * the result. 00219 * @result true if the LDA could be applied, false otherwise 00220 */ 00221 bool apply(matrix<T>& srcdest); 00222 00223 /** 00224 * Set the dimension to which the vectors should be reduced. 00225 */ 00226 void setDimension(int k); 00227 00228 /** 00229 * set functor's parameters. 00230 * This member makes a copy of <em>theParam</em>: the functor 00231 * will keep its own copy of the parameters! 00232 * The difference to the standard is that this one passes 00233 * the useSVD flag on to the matrix inverter. 00234 * @return true if successful, false otherwise 00235 */ 00236 virtual bool setParameters(const parameters& theParam); 00237 00238 00239 /** 00240 * Returns the previously computed eigenvalues of the scatter 00241 * matrix. 00242 * @param result the vector which will receive the eigenvalues. 00243 * @return true if the values could be obtained, false otherwise. 00244 */ 00245 bool getEigenValues(vector<T>& result) const; 00246 00247 /** 00248 * Returns the previously computed eigenvalues of the scatter 00249 * matrix. 00250 * @return true if the values could be obtained, false otherwise. 00251 */ 00252 const vector<T>& getEigenValues() const; 00253 00254 /** 00255 * Returns the previously computed eigenvectors of the scatter 00256 * matrix. 00257 * @param result the matrix which will receive the eigenvectors. 00258 * Each column of the matrix contains one eigenvector. 00259 * @return true if the vectors could be obtained, false otherwise 00260 */ 00261 bool getEigenVectors(matrix<T>& result) const; 00262 00263 /** 00264 * Returns the previously computed eigenvectors of the scatter 00265 * matrix. 00266 * 00267 * This method will call the normal getEigenVectors() methods and 00268 * after that will transpose the obtained matrix, i.e. it is faster 00269 * to get the eigenvectors in the columns. 00270 * 00271 * @param result the matrix which will receive the eigenvectors. 00272 * Each row of the matrix contains one eigenvector. 00273 * @return true if the vectors could be obtained, false otherwise 00274 */ 00275 bool getEigenVectorsInRows(matrix<T>& result) const; 00276 00277 /** 00278 * copy data of "other" functor. 00279 * @param other the functor to be copied 00280 * @return a reference to this functor object 00281 */ 00282 linearDiscriminantAnalysis& copy(const linearDiscriminantAnalysis& other); 00283 00284 /** 00285 * returns a pointer to a clone of this functor. 00286 */ 00287 virtual functor* clone() const; 00288 00289 /** 00290 * returns used parameters 00291 */ 00292 const parameters& getParameters() const; 00293 00294 /** 00295 * Computes the between-class scatter matrix Sb. 00296 */ 00297 bool computeSb(const matrix<T>& src, matrix<T>& Sb, 00298 const ivector& labels) const; 00299 00300 virtual bool read(ioHandler &handler, const bool complete=true); 00301 virtual bool write(ioHandler &handler, const bool complete=true) const; 00302 00303 int getUsedDimension() const { 00304 return usedDimensionality; 00305 } 00306 00307 bool getTransformMatrix(matrix<T>& result) const; 00308 const matrix<T>& getTransformMatrix() const; 00309 const matrix<T>& getEigenVectors() const; 00310 00311 protected: 00312 void find(const ivector &data, int value, ivector &result) const; 00313 00314 void submatrix(const matrix<T>& data,const ivector &index, 00315 matrix<T>& result) const; 00316 00317 /** 00318 * Determines the intrinsic dimensionality of the data set if the 00319 * user specify autoDim, otherwise return parameters::resultDim. 00320 * The member usedDimensionality will be set with the returned value 00321 */ 00322 int checkDim(); 00323 00324 bool buildTransform(const matrix<T>& Sw, const matrix<T>& Sb); 00325 00326 private: 00327 matrix<T> orderedEigVec; 00328 matrix<T> transformMatrix; 00329 vector<T> eigValues; 00330 00331 matrixInversion<T> inv; 00332 varianceFunctor<T> var; 00333 varianceFunctor<T> mlvar; 00334 meansFunctor<T> mean; 00335 generalEigenVectors<T> eig; 00336 00337 00338 /** 00339 * dimensionality being used. 00340 */ 00341 int usedDimensionality; 00342 }; 00343 00344 00345 template <class T> 00346 bool read(ioHandler& handler, linearDiscriminantAnalysis<T>& pca, const bool complete=true) { 00347 return pca.read(handler,complete); 00348 } 00349 00350 00351 template <class T> 00352 bool write(ioHandler& handler, const linearDiscriminantAnalysis<T>& pca, const bool complete=true) { 00353 return pca.write(handler,complete); 00354 } 00355 00356 template <class T> 00357 bool read(ioHandler& handler, typename linearDiscriminantAnalysis<T>::parameters& p, const bool complete=true) { 00358 return p.read(handler,complete); 00359 } 00360 00361 template <class T> 00362 bool write(ioHandler& handler, typename linearDiscriminantAnalysis<T>::parameters& p, const bool complete=true) { 00363 return p.write(handler,complete); 00364 } 00365 00366 00367 } 00368 00369 #endif 00370 #endif