2009年1月23日 星期五

OpenCV統計應用-共變數矩陣

共變數(Covariance),為兩個隨機變數的離均差除以母體個數,可以判斷兩個事件隨機變數的相依性,而單一變數的共變數,那就是變異數(Variance)了,共變數以及變異數簡單的定義如下

變異數


共變數


而當兩隨機變數為獨立事件的時候


再來提到的是共變數矩陣(Covariance matrix),代表著隨機變數所有共變數的種類,以兩組隨機變數來說所產生的共變數矩陣如下


而三組,四組以上隨機變數的共變數矩陣又是不同情形了,在這邊,隨機變數的個數代表著向量的維度,而他的數對則是同時發生的情形,下面就以座標的簡單例子來示範


這是個維度為2的座標數組,代表的是一個座標平面的點集合,而下面就是給它跑cvCalcCovarMatrix()共變數矩陣的計算方法

共變數矩陣1
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <stdlib.h>

float Coordinates[20]={1.5,2.3,
                                 3.0,1.7,
                                 1.2,2.9,
                                 2.1,2.2,
                                 3.1,3.1,
                                 1.3,2.7,
                                 2.0,1.7,
                                 1.0,2.0,
                                 0.5,0.6,
                                 1.0,0.9};

int main()
{
    CvMat *Vector[10];
    CvMat *CovarMatrix;
    CvMat *AvgMatrix;
    IplImage *Image1=cvCreateImage(cvSize(450,450),IPL_DEPTH_8U,3);
    Image1->origin=1;
    for(int i=0;i<10;i++)
    {
        Vector[i]=cvCreateMat(1,2,CV_32FC1);
        cvSetReal1D(Vector[i],0,Coordinates[i*2]);
        cvSetReal1D(Vector[i],1,Coordinates[i*2+1]);
        cvCircle(Image1,cvPoint((int)(Coordinates[i*2]*100),(int)(Coordinates[i*2+1]*100)),0,CV_RGB(0,0,255),10,CV_AA,0);
    }

    CovarMatrix=cvCreateMat(2,2,CV_32FC1);
    AvgMatrix=cvCreateMat(1,2,CV_32FC1);
    cvCalcCovarMatrix((const CvArr **)Vector,10,CovarMatrix,AvgMatrix,CV_COVAR_SCALE+CV_COVAR_NORMAL);

    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            printf("%f ",cvGetReal2D(CovarMatrix,i,j));
        }
        printf("\n");
    }
    cvNamedWindow("Coordinates",1);
    cvShowImage("Coordinates",Image1);
    cvWaitKey(0);
}

執行結果:


計算方法:


上面的方法是用個別的向量來實作,向量的維度為2,而圖片顯示的結果為它們二維座標的分佈情況,cvCalcCovarMatrix()必須給它空的平均值向量矩陣來計算,而cvCalcCovarMatrix()它的參數被定義如下

#define CV_COVAR_SCRAMBLED 0
#define CV_COVAR_NORMAL 1
#define CV_COVAR_USE_AVG 2
#define CV_COVAR_SCALE 4
#define CV_COVAR_ROWS 8
#define CV_COVAR_COLS 16

由上面可以知道,它是由2的N次方所表達的,所以可以用合成參數的方式來表達cvCalcCovarMatrix()的共變數矩陣函式,也就是說,可以用CV_COVAR_SCRAMBLED+CV_COVAR_ROWS的組合,也可以用CV_COVAR_NORMAL+CV_COVAR_USE_AVG+CV_COVAR_ROWS之類的組合,而它所代表的含意分別是

CV_COVAR_SCRAMBLED
一種共變數矩陣的計算方式,不可以與CV_COVAR_NORMAL合用,表達方式如下

這計算方式在OpenCV說明文件提到為Eigenface的計算方式

CV_COVAR_NORMAL
共變數矩陣計算方式,不可與CV_COVAR_SCRAMBLED合用,表達方式如下

這個則是為一般共變數矩陣的計算方式

CV_COVAR_USE_AVG
不用共變數矩陣內建計算平均數的函式,而是自己給予平均數值,可與任何參數共用

CV_COVAR_SCALE
對共變數矩陣的數據做向量個數總和的純量積,用的是除法計算如下的共變數矩陣

可與任何參數共用,而如果沒這參數則是無除以N的計算

CV_COVAR_ROWS
將共變數矩陣的輸入值用矩陣的方式表達,而不是用向量的方式,矩陣表達方式以列(Rows)為主,並且參數不可與CV_COVAR_COLS合用

CV_COVAR_COLS
將共變數矩陣的輸入值用矩陣的方式表達,而不是用向量的方式,矩陣表達方式以欄(Columns)為主,並且參數不可與CV_COVAR_ROWS共用

共變數矩陣有幾個規則,也就是,輸入一定要是方陣,平均數的長度要是向量的維度,而平均數的長度也一定要是向量的大小,然後一定要是用單通道CV_32FC1或是CV_64FC1做為輸入,cvCalcCovarMatrix()函式,第一個引數則必須要用(const CvArr **)強制型別轉換,第二個引數為輸入向量的數目,第三個引數為空的或是非空平均數向量,第四個引數為cvCalcCovarMatrix()這函式要輸入的參數,而下面,則是使用矩陣方式表達共變數矩陣的範例

共變數矩陣2
#include <cv.h>
#include <stdio.h>
#include <stdlib.h>


float Coordinates[20]={1.5,2.3,
                                 3.0,1.7,
                                 1.2,2.9,
                                 2.1,2.2,
                                 3.1,3.1,
                                 1.3,2.7,
                                 2.0,1.7,
                                 1.0,2.0,
                                 0.5,0.6,
                                 1.0,0.9};

int main()
{
    CvMat *Vector[1];
    CvMat *Vector1;
    CvMat *CovarMatrix;
    CvMat *avg;

    Vector1=cvCreateMat(10,2,CV_32FC1);
    cvSetData(Vector1,Coordinates,Vector1->step);
    Vector[0]=Vector1;
    CovarMatrix=cvCreateMat(2,2,CV_32FC1);
    avg=cvCreateMat(1,2,CV_32FC1);

    cvCalcCovarMatrix((const CvArr **)Vector,10,CovarMatrix,avg,CV_COVAR_SCALE+CV_COVAR_NORMAL+CV_COVAR_ROWS);

    for(int i=0;i<2;i++)
    {
        for(int j=0;j<2;j++)
        {
            printf("%f ",cvGetReal2D(CovarMatrix,i,j));
        }
        printf("\n");
    }
    system("pause");
}

執行結果:


上面的程式碼,如果想用矩陣來表達向量的方式計算共變數矩陣,就必須要將第一個引數設為二維陣列當做輸入,輸入的方式就如上面程式的寫法,而其他地方則是沒什麼差異.

共變數矩陣在OpenCV內,不但可以做到計算主成分分析(Principal Cmponents Analysis,PCA),以及另一個Mahalanobis距離的計算

cvCalcCovarMatrix()
計算共變數矩陣,輸入可為多個IplImage或CvMat資料結構,可輸入高維度資料的向量,有多種輸入方式,在資料輸入方面,可以用單一CvMat資料結構,以列(Rows)為主或以行(Columns)為主,使用CV_COVAR_ROWS以及CV_COVAR_COLS的參數輸入,而要做多個IplImage或CvMat資料結構輸入則不需提供CV_COVAR_ROWS,CV_COVAR_COLS的參數,在計算方面,又分為以維度為主的共變數矩陣參數輸入CV_COVAR_NORMAL以及以個數為主的共變數矩陣CV_COVAR_SCRAMBLED,而他也可一自行定義平均值CV_COVAR_USE_AVG,以及除以是否除以共變數矩陣的共變數個數CV_COVAR_SCALE,而這些參數可以自行組合運算,第一個引數為輸入目標向量,第二個引數為輸出目標共變數矩陣,第三個引數為輸入或輸出平均數向量,第四個引數為cvCalcCovarMatrix()共變數計算函式的參數輸入
cvCalcCovarMatrix(輸入多個IplImage或CvMat資料結構,輸出目標共變數矩陣,輸入/出平均數向量,共變數矩陣參數或代號)



1 意見:

匿名 提到...

這BLOG真的很棒耶
而且都還有想到可能的其他問題
提供另外一種解決方法
真是感謝有這個BLOG的存在啊!!!
希望yester能發表些更多內容
感謝^^

Copyright 2008-2009,yester