2008年9月3日 星期三

OpenCV線性代數-cvNorm向量長度,距離計算

cvNorm()這個函數,可以用來做為特徵值比對的公式,也就是在資訊檢索這個領域內,將兩張圖形的特徵值擷取出來,利用紋理值擷取,統計直方圖,小波轉換,或是輪廓資訊等方法,在用裡面cvNorm()內建的CV_L1,CV_L2,CV_C參數來做圖形特徵值比對,cvNorm()的參數定義如下

#define CV_C 1
#define CV_L1 2
#define CV_L2 4
#define CV_DIFF_C (CV_DIFF CV_C)
#define CV_DIFF_L1 (CV_DIFF CV_L1)
#define CV_DIFF_L2 (CV_DIFF CV_L2)
#define CV_RELATIVE_C (CV_RELATIVE | CV_C)
#define CV_RELATIVE_L1 (CV_RELATIVE | CV_L1)
#define CV_RELATIVE_L2 (CV_RELATIVE | CV_L2)

CV_L1是一般的長度計算,CV_L2則是論文常用的歐幾里德距離,CV_C則是拿絕對值後的最大值,在圖形檢索比對這方面cvNorm()還算是不錯用的函式,cvNorm()還提供了遮罩的功能,可以將不必要的特徵資訊做掩蓋的功能,遮罩的部份就要參考前面"圖形的Mask遮罩實作"這地方,與前面圖形Mask使用原理相同.

在線性代數的部分Norm,為向量長度的意思,最常見的長度計算方式為1-Norm將所有向量數據取絕對值的總和,2-Norm為歐機里德距離,將所有數據平方在開根號,∞-Norm為將所有向量數據絕對值後取對大的那個,當然,這分別代表著CV_L1,CV_L2,CV_C的使用,在下面則用簡單的方式做cvNorm()的長度計算.

cvNorm()長度的計算
#include <cv.h>
#include <stdio.h>


float Array2[]={6,-1,2};

int main()
{
    CvMat *Matrix2=cvCreateMat(1,3,CV_32FC1);
    cvSetData(Matrix2,Array2,Matrix2->step);

    printf("1-norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_L1));
    printf("2-norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_L2));
    printf("Infininte norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_C));

    system("pause");
}

執行結果:


cvNorm()的輸出為一個double型別的數據,上面的程式可以簡單的看出來cvNorm()對長度的計算,要計算Matrix2的長度,則是要把第二個引數設置為空,而第二個引數的輸入則是代表著距離,在下面的程式碼範例會介紹到,對於長度的計算公式則是如下所示.


再來是長度計算Mask使用的範例,利用一個遮罩將不想被計算的數據給取消掉,0代表不想使用的數據,1代表要被計算的數據.

cvNorm()遮罩與長度的計算
#include <cv.h>
#include <stdio.h>


float Array2[]={6,-1,2};
uchar MaskArray[]={1,1,0};

int main()
{
    CvMat *Matrix2=cvCreateMat(1,3,CV_32FC1);
    CvMat *MaskMatrix=cvCreateMat(1,3,CV_8UC1);

    cvSetData(Matrix2,Array2,Matrix2->step);
    cvSetData(MaskMatrix,MaskArray,MaskMatrix->step);

    printf("1-norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_L1,MaskMatrix));
    printf("2-norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_L2,MaskMatrix));
    printf("Infininte norm is : %.1f\n",cvNorm(Matrix2,NULL,CV_C,MaskMatrix));

    system("pause");
}

執行結果:


因此,實際上做長度計算的只有6跟-1這兩個數據,在這邊,遮罩的使用CvMat資料結構必須要用單通道非浮點數的數據型別,如CV_32FC1及CV_64FC1都是不可用來作遮罩矩陣的參數宣告.而矩陣也不可以用float及double的型別.遮罩長度的計算方式如下


再來,就是距離的計算了,它可以比較兩個向量的距離大小,也可以用許多向量的距離來做分數(Score)的參考目標,也就是說,在做圖形比對的時候,特徵值距離越小的兩張圖片某些特殊的特徵就越接近(看是用什麼方法擷取特徵值),因此,在一個龐大的圖形特徵資料庫中,將目標圖形的特徵值對每一筆資料做比對,可以藉由取得最小距離來找出最相似的圖形,距離的簡單例子就如下

cvNorm()距離的計算
#include <cv.h>
#include <stdio.h>


float Array1[]={6,-1,2};
float Array2[]={5,3,1};
int main()
{
    CvMat *Matrix1=cvCreateMat(1,3,CV_32FC1);
    CvMat *Matrix2=cvCreateMat(1,3,CV_32FC1);
    cvSetData(Matrix1,Array1,Matrix1->step);
    cvSetData(Matrix2,Array2,Matrix2->step);

    printf("1-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_DIFF_L1));
    printf("2-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_DIFF_L2));
    printf("Infininte norm distance is : %.1f\n\n",cvNorm(Matrix1,Matrix2,CV_DIFF_C));

    printf("Relative 1-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_L1));
    printf("Relative 2-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_L2));
    printf("Relative infininte norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_C));

    system("pause");
}

執行結果:


同樣的,它跟長度的計算有點像,比較不同的地方是將兩個向量個別值做相減在對它做1-Norm,2-Norm或是Infininte-Norm的處理,而2-Norm則是論文常用的歐幾里德距離,CV_RELATIVE_L1,CV_RELATIVE_L2,CV_RELATIVE_C則是取它們相對差異的距離.以下則是它們的計算方式.



再來就是遮罩的部份了,實作方式也跟長度的做法差不多.

cvNorm()遮罩與距離的計算
#include <cv.h>
#include <stdio.h>


float Array1[]={5,3,1};
float Array2[]={6,-1,2};
uchar MaskArray[]={1,1,0};

int main()
{
    CvMat *Matrix1=cvCreateMat(1,3,CV_32FC1);
    CvMat *Matrix2=cvCreateMat(1,3,CV_32FC1);
    CvMat *MaskMatrix=cvCreateMat(1,3,CV_8UC1);

    cvSetData(Matrix1,Array1,Matrix1->step);
    cvSetData(Matrix2,Array2,Matrix2->step);
    cvSetData(MaskMatrix,MaskArray,MaskMatrix->step);

    printf("1-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_DIFF_L1,MaskMatrix));
    printf("2-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_DIFF_L2,MaskMatrix));
    printf("Infininte norm distance is : %.1f\n\n",cvNorm(Matrix1,Matrix2,CV_DIFF_C,MaskMatrix));

    printf("Relative 1-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_L1,MaskMatrix));
    printf("Relative 2-norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_L2,MaskMatrix));
    printf("Relative infininte norm distance is : %.1f\n",cvNorm(Matrix1,Matrix2,CV_RELATIVE_C,MaskMatrix));

    system("pause");
}

執行結果:


由上面看,有用到的Matrix1向量為<5,3>,Matrix2的向量為<6,-1>,因此Mask為0的向量數據都被忽略了,而Mask為1的被保留,計算的方式如下所示.



cvNorm()
計算向量的長度或距離,分為1-Norm(CV_L1),2-Norm(CV_L2),∞-Norm(CV_C)等三種方法,也可以計算相對距離,分別為CV_RELATIVE_C,CV_RELATIVE_L1,CV_RELATIVE_L2,在做資訊檢索比對上有很大的用處.第一個跟第二個引數為輸入向量的CvMat資料結構,如果要計算長度的話第二個引數要為空,第三個引數為cvNorm()的參數,第四個引數為單通道CvMat資料結構的CV_8UC1參數(非浮點數型別)的遮罩矩陣,cvNorm()的輸出為一個double型別的數據,代表著向量的長度或距離.
cvNorm(輸入CvMat資料結構,輸入CvMat資料結構或為空,參數或代號,輸入CvMat遮罩)



0 意見:

Copyright 2008-2009,yester