LinearAlgebraCV.cpp
Go to the documentation of this file.
00001 // ****************************************************************************
00002 // This file is part of the Integrating Vision Toolkit (IVT).
00003 //
00004 // The IVT is maintained by the Karlsruhe Institute of Technology (KIT)
00005 // (www.kit.edu) in cooperation with the company Keyetech (www.keyetech.de).
00006 //
00007 // Copyright (C) 2014 Karlsruhe Institute of Technology (KIT).
00008 // All rights reserved.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are met:
00012 //
00013 // 1. Redistributions of source code must retain the above copyright
00014 //    notice, this list of conditions and the following disclaimer.
00015 //
00016 // 2. Redistributions in binary form must reproduce the above copyright
00017 //    notice, this list of conditions and the following disclaimer in the
00018 //    documentation and/or other materials provided with the distribution.
00019 //
00020 // 3. Neither the name of the KIT nor the names of its contributors may be
00021 //    used to endorse or promote products derived from this software
00022 //    without specific prior written permission.
00023 //
00024 // THIS SOFTWARE IS PROVIDED BY THE KIT AND CONTRIBUTORS “AS IS” AND ANY
00025 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00026 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 // DISCLAIMED. IN NO EVENT SHALL THE KIT OR CONTRIBUTORS BE LIABLE FOR ANY
00028 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00031 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00033 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034 // ****************************************************************************
00035 
00036 
00037 
00038 // ****************************************************************************
00039 // Includes
00040 // ****************************************************************************
00041 
00042 #include <new> // for explicitly using correct new/delete operators on VC DSPs
00043 
00044 #include "LinearAlgebraCV.h"
00045 #include "LinearAlgebra.h"
00046 #include "Math/FloatMatrix.h"
00047 #include "Math/FloatVector.h"
00048 #include "Math/DoubleMatrix.h"
00049 #include "Math/DoubleVector.h"
00050 #include "Math/Math2d.h"
00051 #include "Math/Math3d.h"
00052 #include "Helpers/helpers.h"
00053 
00054 #include <float.h>
00055 #include <math.h>
00056 #include <stdio.h>
00057 
00058 
00059 
00060 // ****************************************************************************
00061 // Functions
00062 // ****************************************************************************
00063 
00064 void LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD(const CFloatMatrix *A, CFloatVector *x)
00065 {
00066         if (A->columns != x->dimension)
00067         {
00068                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD");
00069                 return;
00070         }
00071         
00072         if (A->rows < A->columns)
00073         {
00074                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD\n");
00075                 return;
00076         }
00077         
00078         const int m = A->rows;
00079         const int n = A->columns;
00080 
00081         CFloatMatrix W(n, m), V(n, n);
00082         
00083         SVD(A, &W, 0, &V, false, false, false);
00084         
00085         for (int i = 0, offset = n - 1; i < n; i++, offset += n)
00086                 x->data[i] = V.data[offset];
00087 }
00088 
00089 void LinearAlgebraCV::SolveLinearLeastSquaresSVD(const CFloatMatrix *A, const CFloatVector *b, CFloatVector *x)
00090 {
00091         if (A->columns != x->dimension || A->rows != b->dimension)
00092         {
00093                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresSVD");
00094                 return;
00095         }
00096         
00097         if (A->rows < A->columns)
00098         {
00099                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresSVD\n");
00100                 return;
00101         }
00102 
00103         CFloatMatrix A_(A->rows, A->columns);
00104         CalculatePseudoInverseSVD(A, &A_);
00105         LinearAlgebra::MulMatVec(&A_, b, x);
00106 }
00107 
00108 void LinearAlgebraCV::SolveLinearLeastSquaresSimple(const CFloatMatrix *A, const CFloatVector *b, CFloatVector *x)
00109 {
00110         if (A->columns != x->dimension || A->rows != b->dimension)
00111         {
00112                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresSimple");
00113                 return;
00114         }
00115         
00116         if (A->rows < A->columns)
00117         {
00118                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresSimple\n");
00119                 return;
00120         }
00121 
00122         CFloatMatrix A_(A->rows, A->columns);
00123         CalculatePseudoInverseSimple(A, &A_);
00124         LinearAlgebra::MulMatVec(&A_, b, x);
00125 }
00126 
00127 void LinearAlgebraCV::CalculatePseudoInverseSVD(const CFloatMatrix *pInputMatrix, CFloatMatrix *pResultMatrix)
00128 {
00129         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00130         {
00131                 printf("error: input and output matrix do not match LinearAlgebraCV::CalculatePseudoInverseSVD");
00132                 return;
00133         }
00134         
00135         // algorithm:
00136         // 1: compute U * W * V^T = A
00137         // 2: compute W' = W^T with all non-zero values inverted
00138         // 3: compute V * W' * U^T (=pseudoinverse of A)
00139         
00140         const CFloatMatrix *A = pInputMatrix;
00141         const int m = pInputMatrix->rows;
00142         const int n = pInputMatrix->columns;
00143         
00144         CFloatMatrix W(n, m), WT(m, n), UT(m, m), V(n, n);
00145         
00146         // calculate SVD
00147         SVD(A, &W, &UT, &V, false, true, false);
00148         
00149         // transpose middle diagonal matrix
00150         Transpose(&W, &WT);
00151         
00152         const int min = MY_MIN(m, n);
00153 
00154         int i;
00155         float fThreshold = 0.0f;
00156 
00157         for (i = 0; i < min; i++)
00158                 fThreshold += WT(i, i);
00159         
00160         fThreshold *= 2 * FLT_EPSILON;
00161         
00162         // invert non-zero values (along diagonal)
00163         for (i = 0; i < min; i++)
00164                 if (WT(i, i) < fThreshold)
00165                         WT(i, i) = 0.0f;
00166                 else
00167                         WT(i, i) = 1.0f / WT(i, i);
00168 
00169         // calculate pseudoinverse
00170         CFloatMatrix temp(m, n);
00171         Multiply(&V, &WT, &temp);
00172         Multiply(&temp, &UT, pResultMatrix);
00173 }
00174 
00175 void LinearAlgebraCV::CalculatePseudoInverseSimple(const CFloatMatrix *pInputMatrix, CFloatMatrix *pResultMatrix)
00176 {
00177         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00178         {
00179                 printf("error: input and output matrix do not match LinearAlgebraCV::CalculatePseudoInverseSimple");
00180                 return;
00181         }
00182         
00183         // algorithm:
00184         // compute (A * A^T)^-1 * A^T
00185         
00186         const CFloatMatrix *A = pInputMatrix;
00187         const int m = pInputMatrix->rows;
00188         const int n = pInputMatrix->columns;
00189         
00190         CFloatMatrix AT(m, n), ATA(n, n), ATA_inverted(n, n);
00191         
00192         Transpose(A, &AT);
00193         Multiply(&AT, A, &ATA);
00194         Invert(&ATA, &ATA_inverted);
00195         Multiply(&ATA_inverted, &AT, pResultMatrix);
00196 }
00197 
00198 void LinearAlgebraCV::Invert(const CFloatMatrix *pInputMatrix, const CFloatMatrix *pResultMatrix)
00199 {
00200         if (pInputMatrix->columns != pInputMatrix->rows)
00201         {
00202                 printf("error: input is not square matrix in LinearAlgebraCV::Invert");
00203                 return;
00204         }
00205         
00206         if (pInputMatrix->columns != pResultMatrix->columns || pInputMatrix->rows != pResultMatrix->rows)
00207         {
00208                 printf("error: input and output matrix are not the same in LinearAlgebraCV::Invert");
00209                 return;
00210         }
00211         
00212         CvMat inputMatrix = cvMat(pInputMatrix->rows, pInputMatrix->columns, CV_32FC1, pInputMatrix->data);
00213         CvMat resultMatrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_32FC1, pResultMatrix->data);
00214         
00215         cvInvert(&inputMatrix, &resultMatrix);
00216 }
00217 
00218 void LinearAlgebraCV::Transpose(const CFloatMatrix *pInputMatrix, const CFloatMatrix *pResultMatrix)
00219 {
00220         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00221         {
00222                 printf("error: input and output matrix do not match LinearAlgebraCV::Transpose");
00223                 return;
00224         }
00225         
00226         CvMat inputMatrix = cvMat(pInputMatrix->rows, pInputMatrix->columns, CV_32FC1, pInputMatrix->data);
00227         CvMat resultMatrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_32FC1, pResultMatrix->data);
00228         
00229         cvTranspose(&inputMatrix, &resultMatrix);
00230 }
00231 
00232 void LinearAlgebraCV::CalculateCovarianceMatrix(const CFloatMatrix *pMatrix, CFloatMatrix *pCovarianceMatrix)
00233 {
00234         if (pCovarianceMatrix->columns != pMatrix->columns || pCovarianceMatrix->rows != pMatrix->columns)
00235                 return;
00236 
00237         const int columns = pMatrix->columns;
00238         const int rows = pMatrix->rows;
00239         
00240         CvMat covarianceMatrix = cvMat(columns, columns, CV_32FC1, pCovarianceMatrix->data);
00241         
00242         CvMat **ppInput = new CvMat*[rows];
00243         for (int i = 0; i < rows; i++)
00244         {
00245                 CvMat *vector = cvCreateMatHeader(1, columns, CV_32FC1);
00246                 cvInitMatHeader(vector, 1, columns, CV_32FC1, pMatrix->data + i * columns);
00247                 ppInput[i] = vector;
00248         }
00249 
00250         CvMat *avg = cvCreateMat(1, columns, CV_32FC1);
00251 
00252         #ifdef CV_COVAR_NORMAL
00253         cvCalcCovarMatrix((const CvArr **) ppInput, rows, &covarianceMatrix, avg, CV_COVAR_NORMAL);
00254         #else
00255         cvCalcCovarMatrix((const CvArr **) ppInput, &covarianceMatrix, avg);
00256         #endif
00257 
00258         cvReleaseMat(&avg);
00259 }
00260 
00261 void LinearAlgebraCV::Multiply(const CFloatMatrix *A, const CFloatMatrix *B, CFloatMatrix *pResultMatrix, bool bTransposeB)
00262 {
00263         if (!bTransposeB && (A->columns != B->rows || pResultMatrix->columns != B->columns || pResultMatrix->rows != A->rows))
00264         {
00265                 printf("error: matrices A, B, and pResultMatrix do not satisfy requirements for LinearAlgebraCV::Multiply\n");
00266                 return;
00267         }
00268 
00269         if (bTransposeB && (A->columns != B->columns || pResultMatrix->columns != B->rows || pResultMatrix->rows != A->rows))
00270         {
00271                 printf("error: matrices A, B, and pResultMatrix do not satisfy requirements for LinearAlgebraCV::Multiply\n");
00272                 return;
00273         }
00274 
00275         int flags = 0;
00276 
00277         if (bTransposeB)
00278                 flags =  CV_GEMM_B_T;
00279 
00280         CvMat matrixA = cvMat(A->rows, A->columns, CV_32FC1, A->data);
00281         CvMat matrixB = cvMat(B->rows, B->columns, CV_32FC1, B->data);
00282         CvMat result_matrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_32FC1, pResultMatrix->data);
00283 
00284         cvGEMM(&matrixA, &matrixB, 1, 0, 1, &result_matrix, flags);
00285 }
00286 
00287 void LinearAlgebraCV::SelfProduct(const CFloatMatrix *pMatrix, CFloatMatrix *pResultMatrix, bool bTransposeSecond)
00288 {
00289         if (pResultMatrix->columns != pMatrix->columns || pResultMatrix->rows != pMatrix->columns)
00290                 return;
00291 
00292         CvMat matrix = cvMat(pMatrix->rows, pMatrix->columns, CV_32FC1, pMatrix->data);
00293         CvMat result_matrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_32FC1, pResultMatrix->data);
00294 
00295         if (bTransposeSecond)
00296         cvGEMM(&matrix, &matrix, 1, 0, 1, &result_matrix, CV_GEMM_B_T);
00297         else
00298                 cvGEMM(&matrix, &matrix, 1, 0, 1, &result_matrix, CV_GEMM_A_T);
00299 }
00300 
00301 void LinearAlgebraCV::SVD(const CFloatMatrix *A, CFloatMatrix *W, CFloatMatrix *U, CFloatMatrix *V, bool bAllowModifyA, bool bReturnUTransposed, bool bReturnVTransposed)
00302 {
00303         const int columns = A->columns;
00304         const int rows = A->rows;
00305 
00306         if (W->columns != columns || W->rows != rows)
00307         {
00308                 printf("error: W should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, rows);
00309                 return;
00310         }
00311 
00312         if (U && (U->columns != rows || U->rows != rows))
00313         {
00314                 printf("error: U should have %i columns and %i rows for LinearAlgebra::SVD\n", rows, rows);
00315                 return;
00316         }
00317 
00318         if (V && (V->columns != columns || V->rows != columns))
00319         {
00320                 printf("error: V should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, columns);
00321                 return;
00322         }
00323 
00324         int flags = 0;
00325 
00326         if (bAllowModifyA)
00327                 flags |= CV_SVD_MODIFY_A;
00328 
00329         if (bReturnUTransposed)
00330                 flags |= CV_SVD_U_T;
00331 
00332         if (bReturnVTransposed)
00333                 flags |= CV_SVD_V_T;
00334 
00335         CvMat matrixA = cvMat(rows, columns, CV_32FC1, A->data);
00336         CvMat matrixW = cvMat(rows, columns, CV_32FC1, W->data);
00337 
00338         if (U && V)
00339         {
00340                 CvMat matrixU = cvMat(rows, rows, CV_32FC1, U->data);
00341                 CvMat matrixV = cvMat(columns, columns, CV_32FC1, V->data);
00342 
00343                 cvSVD(&matrixA, &matrixW, &matrixU, &matrixV, flags);
00344         }
00345         else if (U)
00346         {
00347                 CvMat matrixU = cvMat(rows, rows, CV_32FC1, U->data);
00348 
00349                 cvSVD(&matrixA, &matrixW, &matrixU, 0, flags);
00350         }
00351         else if (V)
00352         {
00353                 CvMat matrixV = cvMat(columns, columns, CV_32FC1, V->data);
00354 
00355                 cvSVD(&matrixA, &matrixW, 0, &matrixV, flags);
00356         }
00357         else
00358         {
00359                 cvSVD(&matrixA, &matrixW, 0, 0, flags);
00360         }
00361 }
00362 
00363 void LinearAlgebraCV::PCA(const CFloatMatrix *pData, CFloatMatrix *pTransformationMatrix, CFloatMatrix *pTransformedData, int nTargetDimension)
00364 {
00365         if (nTargetDimension > pData->columns)
00366         {
00367                 printf("error: target dimension is greater than number of columns in training data matrix in LinearAlgebraCV::PCA\n");
00368                 return;
00369         }
00370 
00371         const int samples = pData->rows;
00372         const int dimension = pData->columns;
00373 
00374         if (pTransformationMatrix->columns != dimension || pTransformationMatrix->rows != nTargetDimension ||
00375                 pTransformedData->columns != samples || pTransformedData->rows != nTargetDimension)
00376         {
00377                 printf("error: input to LinearAlgebraCV::PCA does not match\n");
00378                 return;
00379         }
00380 
00381         CFloatMatrix adjustedData(pData);
00382         CFloatMatrix covarianceMatrix(dimension, dimension);
00383         CFloatMatrix eigenValues(dimension, dimension);
00384         CFloatMatrix eigenVectors(dimension, dimension);
00385         
00386         printf("subtracting mean from columns...\n");
00387         LinearAlgebra::SubtractMeanFromColumns(pData, &adjustedData);
00388         
00389         printf("calculating covariance matrix...\n");
00390         LinearAlgebraCV::SelfProduct(&adjustedData, &covarianceMatrix);
00391         
00392         printf("calculating SVD on %ix%i matrix...\n", dimension, dimension);
00393         LinearAlgebraCV::SVD(&covarianceMatrix, &eigenValues, &eigenVectors, 0, true, true);
00394         
00395         printf("SVD calculated\n");
00396 
00397         for (int i = 0, offset = 0; i < nTargetDimension; i++)
00398         {
00399                 for (int j = 0; j < dimension; j++)
00400                 {
00401                         pTransformationMatrix->data[offset] = eigenVectors.data[i * dimension + j];
00402                         offset++;
00403                 }
00404         }
00405 
00406         LinearAlgebraCV::Multiply(pTransformationMatrix, pData, pTransformedData, true);
00407 }
00408 
00409 void LinearAlgebraCV::PCA(const CFloatMatrix *pData, CFloatMatrix *pTransformationMatrix, CFloatMatrix *pEigenValues)
00410 {
00411         const int samples = pData->rows;
00412         const int dimension = pData->columns;
00413 
00414         if (pTransformationMatrix->columns != dimension || pTransformationMatrix->rows != dimension || pEigenValues->columns != 1 || pEigenValues->rows != dimension)
00415                 return;
00416 
00417         CFloatMatrix adjustedData(pData);
00418         CFloatMatrix covarianceMatrix(dimension, dimension);
00419         CFloatMatrix eigenValues(dimension, dimension);
00420         CFloatMatrix eigenVectors(dimension, dimension);
00421         
00422         printf("subtracting mean from columns...\n");
00423         LinearAlgebra::SubtractMeanFromColumns(pData, &adjustedData);
00424         
00425         printf("calculating covariance matrix...\n");
00426         LinearAlgebraCV::SelfProduct(&adjustedData, &covarianceMatrix);
00427         
00428         printf("calculating SVD on %ix%i matrix...\n", dimension, dimension);
00429         LinearAlgebraCV::SVD(&covarianceMatrix, &eigenValues, pTransformationMatrix, 0, true, true);
00430         
00431         printf("SVD calculated\n");
00432         
00433         for (int i = 0; i < dimension; i++)
00434                 pEigenValues->data[i] = eigenValues.data[i * dimension + i];
00435 }
00436 
00437 bool LinearAlgebraCV::DetermineAffineTransformation(const Vec2d *pSourcePoints, const Vec2d *pTargetPoints, int nPoints, Mat3d &A, bool bUseSVD)
00438 {
00439         if (nPoints < 3)
00440         {
00441                 printf("error: not enough input point pairs for LinearAlgebraCV::DetermineAffineTransformation (must be at least 3)\n");
00442                 return false;
00443         }
00444         
00445         CFloatMatrix M(6, 2 * nPoints);
00446         CFloatVector b(2 * nPoints);
00447         
00448         float *data = M.data;
00449         
00450         for (int i = 0, offset = 0; i < nPoints; i++, offset += 12)
00451         {
00452                 data[offset] = pSourcePoints[i].x;
00453                 data[offset + 1] = pSourcePoints[i].y;
00454                 data[offset + 2] = 1;
00455                 data[offset + 3] = 0;
00456                 data[offset + 4] = 0;
00457                 data[offset + 5] = 0;
00458                 
00459                 data[offset + 6] = 0;
00460                 data[offset + 7] = 0;
00461                 data[offset + 8] = 0;
00462                 data[offset + 9] = pSourcePoints[i].x;
00463                 data[offset + 10] = pSourcePoints[i].y;
00464                 data[offset + 11] = 1;
00465 
00466                 const int index = 2 * i;
00467                 b.data[index] = pTargetPoints[i].x;
00468                 b.data[index + 1] = pTargetPoints[i].y;
00469         }
00470         
00471         CFloatVector x(6);
00472         
00473         if (bUseSVD)
00474                 LinearAlgebraCV::SolveLinearLeastSquaresSVD(&M, &b, &x);
00475         else
00476                 LinearAlgebraCV::SolveLinearLeastSquaresSimple(&M, &b, &x);
00477         
00478         Math3d::SetMat(A, x.data[0], x.data[1], x.data[2], x.data[3], x.data[4], x.data[5], 0, 0, 1);
00479         
00480         return true;
00481 }
00482 
00483 bool LinearAlgebraCV::DetermineHomography(const Vec2d *pSourcePoints, const Vec2d *pTargetPoints, int nPoints, Mat3d &A, bool bUseSVD)
00484 {
00485         if (nPoints < 4)
00486         {
00487                 printf("error: not enough input point pairs for LinearAlgebraCV::DetermineHomography (must be at least 4)\n");
00488                 return false;
00489         }
00490 
00491         // this least squares problem becomes numerically instable when
00492         // using float instead of double!!
00493         CDoubleMatrix M(8, 2 * nPoints);
00494         CDoubleVector b(2 * nPoints);
00495         
00496         double *data = M.data;
00497         
00498         for (int i = 0, offset = 0; i < nPoints; i++, offset += 16)
00499         {
00500                 data[offset] = pSourcePoints[i].x;
00501                 data[offset + 1] = pSourcePoints[i].y;
00502                 data[offset + 2] = 1;
00503                 data[offset + 3] = 0;
00504                 data[offset + 4] = 0;
00505                 data[offset + 5] = 0;
00506                 data[offset + 6] = -pSourcePoints[i].x * pTargetPoints[i].x;
00507                 data[offset + 7] = -pSourcePoints[i].y * pTargetPoints[i].x;
00508                 
00509                 data[offset + 8] = 0;
00510                 data[offset + 9] = 0;
00511                 data[offset + 10] = 0;
00512                 data[offset + 11] = pSourcePoints[i].x;
00513                 data[offset + 12] = pSourcePoints[i].y;
00514                 data[offset + 13] = 1;
00515                 data[offset + 14] = -pSourcePoints[i].x * pTargetPoints[i].y;
00516                 data[offset + 15] = -pSourcePoints[i].y * pTargetPoints[i].y;
00517 
00518                 const int index = 2 * i;
00519                 b.data[index] = pTargetPoints[i].x;
00520                 b.data[index + 1] = pTargetPoints[i].y;
00521         }
00522         
00523         CDoubleVector x(8);
00524         
00525         if (bUseSVD)
00526                 LinearAlgebraCV::SolveLinearLeastSquaresSVD(&M, &b, &x);
00527         else
00528                 LinearAlgebraCV::SolveLinearLeastSquaresSimple(&M, &b, &x);
00529         
00530         Math3d::SetMat(A, float(x.data[0]), float(x.data[1]), float(x.data[2]), float(x.data[3]), float(x.data[4]), float(x.data[5]), float(x.data[6]), float(x.data[7]), 1);
00531         
00532         return true;
00533 }
00534 
00535 
00536 
00537 
00538 
00539 // copy & paste implementation for CDoubleMatrix and CDoubleVector
00540 // not nice, but i don't like templates.
00541 
00542 void LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD(const CDoubleMatrix *A, CDoubleVector *x)
00543 {
00544         if (A->columns != x->dimension)
00545         {
00546                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD");
00547                 return;
00548         }
00549         
00550         if (A->rows < A->columns)
00551         {
00552                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresHomogeneousSVD\n");
00553                 return;
00554         }
00555         
00556         const int m = A->rows;
00557         const int n = A->columns;
00558 
00559         CDoubleMatrix W(n, m), V(n, n);
00560         
00561         SVD(A, &W, 0, &V, false, false, false);
00562         
00563         for (int i = 0, offset = n - 1; i < n; i++, offset += n)
00564                 x->data[i] = V.data[offset];
00565 }
00566 
00567 void LinearAlgebraCV::SolveLinearLeastSquaresSVD(const CDoubleMatrix *A, const CDoubleVector *b, CDoubleVector *x)
00568 {
00569         if (A->columns != x->dimension || A->rows != b->dimension)
00570         {
00571                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresSVD");
00572                 return;
00573         }
00574         
00575         if (A->rows < A->columns)
00576         {
00577                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresSVD\n");
00578                 return;
00579         }
00580 
00581 #if 0
00582         CvMat *AA = cvCreateMat(A->rows, A->columns, CV_64FC1);
00583     CvMat *BB = cvCreateMat(b->dimension, 1, CV_64FC1);
00584     CvMat *XX = cvCreateMat(x->dimension, 1, CV_64FC1);
00585 
00586         int i;
00587 
00588         for (i = 0; i < A->rows * A->columns; i++)
00589                 AA->data.db[i] = A->data[i];
00590 
00591         for (i = 0; i < b->dimension; i++)
00592                 BB->data.db[i] = b->data[i];
00593 
00594         cvSolve(AA, BB, XX, CV_SVD);
00595         
00596         for (int k = 0; k < 8; k++)
00597                 x->data[k] = XX->data.db[k];
00598         
00599         cvReleaseMat(&AA);
00600         cvReleaseMat(&BB);
00601         cvReleaseMat(&XX);
00602 #else
00603         CDoubleMatrix A_(A->rows, A->columns);
00604         CalculatePseudoInverseSVD(A, &A_);
00605         LinearAlgebra::MulMatVec(&A_, b, x);
00606 #endif
00607 }
00608 
00609 void LinearAlgebraCV::SolveLinearLeastSquaresSimple(const CDoubleMatrix *A, const CDoubleVector *b, CDoubleVector *x)
00610 {
00611         if (A->columns != x->dimension || A->rows != b->dimension)
00612         {
00613                 printf("error: A, b, x do not match LinearAlgebraCV::SolveLinearLeastSquaresSimple");
00614                 return;
00615         }
00616         
00617         if (A->rows < A->columns)
00618         {
00619                 printf("error: equation system is underdetermined in LinearAlgebraCV::SolveLinearLeastSquaresSimple\n");
00620                 return;
00621         }
00622 
00623         CDoubleMatrix A_(A->rows, A->columns);
00624         CalculatePseudoInverseSimple(A, &A_);
00625         LinearAlgebra::MulMatVec(&A_, b, x);
00626 }
00627 
00628 void LinearAlgebraCV::CalculatePseudoInverseSVD(const CDoubleMatrix *pInputMatrix, CDoubleMatrix *pResultMatrix)
00629 {
00630         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00631         {
00632                 printf("error: input and output matrix do not match LinearAlgebraCV::CalculatePseudoInverseSVD");
00633                 return;
00634         }
00635         
00636         // algorithm:
00637         // 1: compute U * W * V^T = A
00638         // 2: compute W' = W^T with all non-zero values inverted
00639         // 3: compute V * W' * U^T (=pseudoinverse of A)
00640         
00641         const CDoubleMatrix *A = pInputMatrix;
00642         const int m = pInputMatrix->rows;
00643         const int n = pInputMatrix->columns;
00644         
00645         CDoubleMatrix W(n, m), WT(m, n), UT(m, m), V(n, n);
00646         
00647         // calculate SVD
00648         SVD(A, &W, &UT, &V, false, true, false);
00649         
00650         // transpose middle diagonal matrix
00651         Transpose(&W, &WT);
00652         
00653         const int min = MY_MIN(m, n);
00654 
00655         int i;
00656         double dThreshold = 0.0;
00657 
00658         for(i = 0; i < min; i++)
00659         dThreshold += WT(i, i);
00660     
00661         dThreshold *= 2 * DBL_EPSILON;
00662         
00663         // invert non-zero values (along diagonal)
00664         for (i = 0; i < min; i++)
00665                 if (WT(i, i) < dThreshold)
00666                         WT(i, i) = 0;
00667                 else
00668                         WT(i, i) = 1.0 / WT(i, i);
00669 
00670         // calculate pseudoinverse
00671         CDoubleMatrix temp(m, n);
00672         Multiply(&V, &WT, &temp);
00673         Multiply(&temp, &UT, pResultMatrix);
00674 }
00675 
00676 void LinearAlgebraCV::CalculatePseudoInverseSimple(const CDoubleMatrix *pInputMatrix, CDoubleMatrix *pResultMatrix)
00677 {
00678         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00679         {
00680                 printf("error: input and output matrix do not match LinearAlgebraCV::CalculatePseudoInverseSimple");
00681                 return;
00682         }
00683         
00684         // algorithm:
00685         // compute (A * A^T)^-1 * A^T
00686         
00687         const CDoubleMatrix *A = pInputMatrix;
00688         const int m = pInputMatrix->rows;
00689         const int n = pInputMatrix->columns;
00690         
00691         CDoubleMatrix AT(m, n), ATA(n, n), ATA_inverted(n, n);
00692         
00693         Transpose(A, &AT);
00694         Multiply(&AT, A, &ATA);
00695         Invert(&ATA, &ATA_inverted);
00696         Multiply(&ATA_inverted, &AT, pResultMatrix);
00697 }
00698 
00699 void LinearAlgebraCV::Invert(const CDoubleMatrix *pInputMatrix, const CDoubleMatrix *pResultMatrix)
00700 {
00701         if (pInputMatrix->columns != pInputMatrix->rows)
00702         {
00703                 printf("error: input is not square matrix in LinearAlgebraCV::Invert");
00704                 return;
00705         }
00706         
00707         if (pInputMatrix->columns != pResultMatrix->columns || pInputMatrix->rows != pResultMatrix->rows)
00708         {
00709                 printf("error: input and output matrix are not the same in LinearAlgebraCV::Invert");
00710                 return;
00711         }
00712         
00713         CvMat inputMatrix = cvMat(pInputMatrix->rows, pInputMatrix->columns, CV_64FC1, pInputMatrix->data);
00714         CvMat resultMatrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_64FC1, pResultMatrix->data);
00715         
00716         cvInvert(&inputMatrix, &resultMatrix);
00717 }
00718 
00719 void LinearAlgebraCV::Transpose(const CDoubleMatrix *pInputMatrix, const CDoubleMatrix *pResultMatrix)
00720 {
00721         if (pInputMatrix->columns != pResultMatrix->rows || pInputMatrix->rows != pResultMatrix->columns)
00722         {
00723                 printf("error: input and output matrix do not match LinearAlgebraCV::Transpose");
00724                 return;
00725         }
00726         
00727         CvMat inputMatrix = cvMat(pInputMatrix->rows, pInputMatrix->columns, CV_64FC1, pInputMatrix->data);
00728         CvMat resultMatrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_64FC1, pResultMatrix->data);
00729         
00730         cvTranspose(&inputMatrix, &resultMatrix);
00731 }
00732 
00733 void LinearAlgebraCV::Multiply(const CDoubleMatrix *A, const CDoubleMatrix *B, CDoubleMatrix *pResultMatrix, bool bTransposeB)
00734 {
00735         if (!bTransposeB && (A->columns != B->rows || pResultMatrix->columns != B->columns || pResultMatrix->rows != A->rows))
00736         {
00737                 printf("error: matrices A, B, and pResultMatrix do not satisfy requirements for LinearAlgebraCV::Multiply\n");
00738                 return;
00739         }
00740 
00741         if (bTransposeB && (A->columns != B->columns || pResultMatrix->columns != B->rows || pResultMatrix->rows != A->rows))
00742         {
00743                 printf("error: matrices A, B, and pResultMatrix do not satisfy requirements for LinearAlgebraCV::Multiply\n");
00744                 return;
00745         }
00746 
00747         int flags = 0;
00748 
00749         if (bTransposeB)
00750                 flags =  CV_GEMM_B_T;
00751 
00752         CvMat matrixA = cvMat(A->rows, A->columns, CV_64FC1, A->data);
00753         CvMat matrixB = cvMat(B->rows, B->columns, CV_64FC1, B->data);
00754         CvMat result_matrix = cvMat(pResultMatrix->rows, pResultMatrix->columns, CV_64FC1, pResultMatrix->data);
00755 
00756         cvGEMM(&matrixA, &matrixB, 1, 0, 1, &result_matrix, flags);
00757 }
00758 
00759 void LinearAlgebraCV::SVD(const CDoubleMatrix *A, CDoubleMatrix *W, CDoubleMatrix *U, CDoubleMatrix *V, bool bAllowModifyA, bool bReturnUTransposed, bool bReturnVTransposed)
00760 {
00761         const int columns = A->columns;
00762         const int rows = A->rows;
00763 
00764         if (W->columns != columns || W->rows != rows)
00765         {
00766                 printf("error: W should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, rows);
00767                 return;
00768         }
00769 
00770         if (U && (U->columns != rows || U->rows != rows))
00771         {
00772                 printf("error: U should have %i columns and %i rows for LinearAlgebra::SVD\n", rows, rows);
00773                 return;
00774         }
00775 
00776         if (V && (V->columns != columns || V->rows != columns))
00777         {
00778                 printf("error: V should have %i columns and %i rows for LinearAlgebra::SVD\n", columns, columns);
00779                 return;
00780         }
00781 
00782         int flags = 0;
00783 
00784         if (bAllowModifyA)
00785                 flags |= CV_SVD_MODIFY_A;
00786 
00787         if (bReturnUTransposed)
00788                 flags |= CV_SVD_U_T;
00789 
00790         if (bReturnVTransposed)
00791                 flags |= CV_SVD_V_T;
00792 
00793         CvMat matrixA = cvMat(rows, columns, CV_64FC1, A->data);
00794         CvMat matrixW = cvMat(rows, columns, CV_64FC1, W->data);
00795 
00796         if (U && V)
00797         {
00798                 CvMat matrixU = cvMat(rows, rows, CV_64FC1, U->data);
00799                 CvMat matrixV = cvMat(columns, columns, CV_64FC1, V->data);
00800 
00801                 cvSVD(&matrixA, &matrixW, &matrixU, &matrixV, flags);
00802         }
00803         else if (U)
00804         {
00805                 CvMat matrixU = cvMat(rows, rows, CV_64FC1, U->data);
00806 
00807                 cvSVD(&matrixA, &matrixW, &matrixU, 0, flags);
00808         }
00809         else if (V)
00810         {
00811                 CvMat matrixV = cvMat(columns, columns, CV_64FC1, V->data);
00812 
00813                 cvSVD(&matrixA, &matrixW, 0, &matrixV, flags);
00814         }
00815         else
00816         {
00817                 cvSVD(&matrixA, &matrixW, 0, 0, flags);
00818         }
00819 }


asr_ivt
Author(s): Allgeyer Tobias, Hutmacher Robin, Kleinert Daniel, Meißner Pascal, Scholz Jonas, Stöckle Patrick
autogenerated on Thu Jun 6 2019 21:46:57