00001 /*!@file Image/LinearAlgebra.H */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Rob Peters <rjpeters@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Image/LinearAlgebra.H $ 00035 // $Id: LinearAlgebra.H 5744 2005-10-18 23:30:18Z rjpeters $ 00036 // 00037 00038 #ifndef IMAGE_LINEARALGEBRA_H_DEFINED 00039 #define IMAGE_LINEARALGEBRA_H_DEFINED 00040 00041 #include "Image/LinearAlgebraFlags.H" 00042 #include "Util/Promotions.H" 00043 00044 template <class T> class Image; 00045 00046 //! Compute the singular decomposition of M: M = U * S * V^T 00047 /*! The U, S, V matrices have special properties: 00048 00049 - U is column-orthogonal, such that (U^T * U) = I 00050 - S is square, diagonal, so that S is easily invertible 00051 - V is square and orthogonal, so (V^T * V) = (V * V^T) = I 00052 00053 Note that these properties mean that the svd can be used to 00054 compute the pseudo-inverse of a general matrix M: 00055 00056 - M = U*S*V^T 00057 - U^T*M = S*V^T (since U is column-orthogonal) 00058 - S^-1*U^T*M = V^T (since S is diagonal and invertible) 00059 - V*S^-1*U^T*M = I (since V is square and orthogonal) 00060 00061 by definition, pinv(M)*M = I, therefore 00062 00063 - V*S^-1*U^T = pinv(M) 00064 00065 (Note ^T is used to designate the matrix transpose, and ^-1 is 00066 used to designate the matrix inverse). 00067 00068 You can use the routine svdPseudoInv to compute the pseudo-inverse 00069 using just this method. 00070 */ 00071 void svd(const Image<double>& M, 00072 Image<double>& U, Image<double>& S, Image<double>& V, 00073 SvdAlgo algo, const SvdFlag flags = 0); 00074 00075 //! Single-precision counterpart of svd() 00076 void svdf(const Image<float>& M, 00077 Image<float>& U, Image<float>& S, Image<float>& V, 00078 SvdAlgo algo, const SvdFlag flags = 0); 00079 00080 //! Compute the pseudo-inverse using the method described in svd() 00081 /*! Optionally throw out small values from the diagonal S matrix -- 00082 this helps numerical stability. 00083 00084 The number of eigenvalues retained is controlled by tolfactor. If 00085 tolfactor is less than 1.0, then it serves as a multiplier of the 00086 largest eigenvalue, below which any smaller eigenvalues are thrown 00087 out. If tolfactor is greater than 1.0, then the integer portion of 00088 tolfactor specifies the number of eigenvalues to be retained. 00089 00090 If rank is a non-null pointer, then the rank of the diagonal 00091 matrix (after setting small values to zero) will be returned 00092 through that pointer. */ 00093 Image<double> svdPseudoInv(const Image<double>& x, 00094 const SvdAlgo algo, 00095 int* const rank = 0, 00096 const double tolfactor = 1.0e-8); 00097 00098 //! Single-precision counterpart of svdPseudoInv() 00099 Image<float> svdPseudoInvf(const Image<float>& x, 00100 const SvdAlgo algo, 00101 int* const rank = 0, 00102 const float tolfactor = 1.0e-8f); 00103 00104 //! NOTE that this procedure is called "naive, unstable" for a reason! 00105 /*! This procedure computes the pseudo-inverse using the direct 00106 formula pinv(M) = (M^T * M)^-1 * M^T. The formula is analytically 00107 correct, but in practice it can be numerically unstable. Indeed it 00108 might work just fine for your matrix, but to be safe you'll need 00109 to check the identity pinv(M)*M ~= I -- for example, do 00110 RMSerr(matrixMult(M,pinv(M)), eye<float>(M.getHeight())) and make 00111 sure that it's small (say, less than 0.01 or so). If you do get a 00112 large RMS error, then you can consider using svdPseudoInv() 00113 instead, which offers more numerical stability. */ 00114 template <class T> 00115 Image<typename promote_trait<T, float>::TP> 00116 naiveUnstablePseudoInv(const Image<T>& M); 00117 00118 // ###################################################################### 00119 /* So things look consistent in everyone's emacs... */ 00120 /* Local Variables: */ 00121 /* indent-tabs-mode: nil */ 00122 /* End: */ 00123 00124 #endif // IMAGE_LINEARALGEBRA_H_DEFINED