2008年7月26日 星期六

OpenCV線性代數-跡數,轉置,反矩陣

跡數(trace),也就是對角線數據的總和,轉置矩陣(Transpose Matrix),則是將矩陣數據列跟欄對調將橫的數據變成直的,反矩陣(Inverse Matrix)它的定義為與目標矩陣相乘可以得到單位矩陣,為一個可逆矩陣.

跡數,轉置,反矩陣實作
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


void PrintMatrix(CvMat *Matrix,int Rows,int Cols);

CvScalar Trace;
float Array[]={2,3,1,4,1,4,3,4,6};

int main()
{
    CvMat *Matrix1=cvCreateMat(3,3,CV_32FC1);
    CvMat *TransposeMatrix=cvCreateMat(3,3,CV_32FC1);
    CvMat *InverseMatrix=cvCreateMat(3,3,CV_32FC1);
    cvSetData(Matrix1,Array,Matrix1->step);

    printf("The Trace is:\n");
    Trace=cvTrace(Matrix1);
    printf("%.f",Trace.val[0]);

    printf("\nThe Transpose Matrix is:\n");
    cvTranspose(Matrix1,TransposeMatrix);
    PrintMatrix(TransposeMatrix,TransposeMatrix->rows,TransposeMatrix->cols);

    printf("\nThe Invert Matrix is:\n");
    cvInvert(Matrix1,InverseMatrix,CV_LU);
    PrintMatrix(InverseMatrix,InverseMatrix->rows,InverseMatrix->cols);

    system("pause");
}

void PrintMatrix(CvMat *Matrix,int Rows,int Cols)
{
    for(int i=0;i<Rows;i++)
    {
        for(int j=0;j<Cols;j++)
        {
            printf("%.1f ",cvGet2D(Matrix,i,j).val[0]);
        }
        printf("\n");
    }
}

執行結果:


由上面的程式可以看出來cvTrace()就是對角線的數據總和2+1+6=9為跡數的數據,必須放在CvScalar資料結構內,而轉置矩陣函式cvTranspose()則是將內部欄跟列對調,至於反矩陣,cvInvert()第三個引數是計算方法的參數,CV_LU則是用LU分解的方式去實作,LU分解對於用程式求反矩陣來講為較快的方法.

Matrix1做LU分解


Matrix1用LU分解求反矩陣


而反矩陣的另一個參數CV_SVD,為奇異值分解法(Singular Value Decomposition,SVD)求反矩陣,奇異值分解法可以將一個不存在反矩陣的方陣求出它的虛反矩陣(Pseudoinverse Matrix),又稱為廣義反矩陣(Generalized Inverse Matrix),而對於一個具有反矩陣的方陣,CV_SVD則直接求出反矩陣的值.

CV_SVD求虛反矩陣
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


void PrintMatrix(CvMat *Matrix,int Rows,int Cols);

float Array[]={0,1,2,3,4,5,6,7,8};
int main()
{
    CvMat *Matrix1=cvCreateMat(3,3,CV_32FC1);
    CvMat *InverseMatrix=cvCreateMat(3,3,CV_32FC1);
    CvMat *PseudoInverseMatrix=cvCreateMat(3,3,CV_32FC1);
    cvSetData(Matrix1,Array,Matrix1->step);

    printf("\nThe Invert Matrix is:\n");
    cvInvert(Matrix1,InverseMatrix,CV_LU);
    PrintMatrix(InverseMatrix,InverseMatrix->rows,InverseMatrix->cols);

    printf("\nThe Invert Matrix is:\n");
    cvInvert(Matrix1,PseudoInverseMatrix,CV_SVD);
    PrintMatrix(PseudoInverseMatrix,PseudoInverseMatrix->rows,PseudoInverseMatrix->cols);

    system("pause");

}

void PrintMatrix(CvMat *Matrix,int Rows,int Cols)
{
    for(int i=0;i<Rows;i++)
    {
        for(int j=0;j<Cols;j++)
        {
            printf("%.2f ",cvGet2D(Matrix,i,j).val[0]);
        }
        printf("\n");
    }
}

執行結果:


上面的結果用單純的CV_LU是無解的,因為該矩陣具0列,因此無法求得反矩陣,這種矩陣又叫做奇異矩陣(Singular Matirx),奇異矩陣的定義就是不可逆矩陣,不具有反矩陣的矩陣,而他可以藉由奇異值分解(SVD)的方法求得虛反矩陣

Matrix1做SVD分解


Matrix1用SVD分解求反矩陣



再來,下面是另一個參數利用奇異值分解快速求解的方法,但是它限定輸入的數據必須是對稱矩陣(Symmetric Matrix),對稱矩陣的定義為它的轉置與原來的矩陣相同,而CV_SVD_SYM這個對稱矩陣的參數,可以比一般反矩陣運算還快速.

對稱矩陣求反矩陣
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


void PrintMatrix(CvMat *Matrix,int Rows,int Cols);

float Array[]={2,2,-2,2,5,-4,-2,-4,5};
int main()
{
    CvMat *Matrix1=cvCreateMat(3,3,CV_32FC1);
    CvMat *TransposeMatrix=cvCreateMat(3,3,CV_32FC1);
    CvMat *InverseMatrix=cvCreateMat(3,3,CV_32FC1);
    cvSetData(Matrix1,Array,Matrix1->step);

    printf("\nThe Transpose Matrix is:\n");
    cvTranspose(Matrix1,TransposeMatrix);
    PrintMatrix(TransposeMatrix,TransposeMatrix->rows,TransposeMatrix->cols);

    printf("\nThe Inverse Matrix is:\n");
    cvInvert(Matrix1,InverseMatrix,CV_LU);
    PrintMatrix(InverseMatrix,InverseMatrix->rows,InverseMatrix->cols);

    printf("\nThe Invese Matrix is:\n");
    cvInvert(Matrix1,InverseMatrix,CV_SVD);
    PrintMatrix(InverseMatrix,InverseMatrix->rows,InverseMatrix->cols);

    printf("\nThe Invese Matrix is:\n");
    cvInvert(Matrix1,InverseMatrix,CV_SVD_SYM);
    PrintMatrix(InverseMatrix,InverseMatrix->rows,InverseMatrix->cols);

    system("pause");

}

void PrintMatrix(CvMat *Matrix,int Rows,int Cols)
{
    for(int i=0;i<Rows;i++)
    {
        for(int j=0;j<Cols;j++)
        {
            printf("%.2f ",cvGet2D(Matrix,i,j).val[0]);
        }
        printf("\n");
    }
}

執行結果:


由上面的cvTranspose()轉置結果,輸入矩陣跟輸出矩陣是相同的,而它也可以做CV_LU的反矩陣運算,也可以做CV_SVD的反矩陣運算,CV_SVD_SYM則是對稱矩陣的快速算法.

Matrix1對稱矩陣做SVD分解


Matrix1對稱矩陣用SVD分解求反矩陣



cvTrace()
計算CvMat資料結構的跡數,也就是對角線數據的總和,回傳CvScalar資料結構.
cvTrace(CvMat資料結構)

cvTranspose()
將目標矩陣轉置,第一個引數為輸入CvMat資料結構,第二個引數為CvMat輸出資料結構
cvTranspose(輸入CvMat資料結構,輸出CvMat資料結構)

cvInvert()
計算反矩陣,有三種計算方式,它的參數被定義為

#define CV_LU 0
#define CV_SVD 1
#define CV_SVD_SYM 2

分別代表上三角,下三角矩陣的LU分解,奇異值分解(Singular Value Decomposition)及奇異值對稱分解
,第一個引數為輸入CvMat資料結構,第二個引數為輸出CvMat資料結構,第三個引數為反矩陣參數
cvInvert(輸入CvMat資料結構,輸出CvMat資料結構,反矩陣參數或代號)



1 意見:

Quanto 提到...

請問要怎麼才能知道某個矩陣有沒有反矩陣?
有特殊函式可以幫忙嗎??

Copyright 2008-2009,yester