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