奇異值分解的理論參見下面的鏈接
http://www.cnblogs.com/pinard/p/6251584.html
https://blog.csdn.net/shenziheng1/article/details/52916278
https://blog.csdn.net/billbliss/article/details/78579308
https://blog.csdn.net/zhongkejingwang/article/details/43053513
https://blog.csdn.net/u010099080/article/details/68060274
在Matlab中的eig()函數,和Opencv中的eigen()函數,都是用來獲得矩陣的特征值和特征矢量。並且,這兩個函數的輸入矩陣必須是對稱矩陣。
Matlab中的eig()函數,常見的寫法如下:
[V D]=eig(A);
D是矩陣A的特征值組成的對角矩陣,與A是同數據類型,同尺度。V是與特征值對應的特征矢量組成的矩陣。
在Opencv中的eigen()函數,常見的寫法如下:
myEigen(A,D,V);
函數中的A是輸入矩陣,D和V是輸出的特征值矢量和特征矢量組成的矩陣。eig()函數與eigen()函數的不同之處是:
1、在eigen()中的D是一個一維特征值組成的列矢量,並且特征值是按照降序排序;而在eig()中的D則是一個以特征值為對角的對角矩陣,特征值是按照升序排序。
2、在eigen()中的V是特征矢量組成的矩陣,矩陣中的每一行就是一個特征矢量;而在eig()中的V則是以特征矢量組成的矩陣,矩陣中的每一列即是一個特征矢量。
下面是同一個實例,在Matlab中和Opencv中的比較:
首先是Matlab中的eig函數的實例代碼:
clear; clc; A=[1,2,3; 2,5,6; 3,6,9]; [V D]=eig(A); A_r=V*D*V';
輸入結果如下:
下面是Opencv中eigen函數的實例代碼:
//為方便與Matlab中的eig()函數比較,我把eigen封裝在一個函數里,並將特征值矢量轉換成對角矩陣,與Matlab中類似
void myEigen(Mat&A,Mat&D,Mat&V) { eigen(A,D,V); Mat E=Mat::eye(A.size(),A.type()); for(int i=0;i<A.rows;i++) { E.at<double>(i,i)=D.at<double>(0,i); } D=E.clone(); } const double eps=2.224e-16; int main() { Mat A=(Mat_<double>(3,3)<< 1,2,3, 2,5,6, 3,6,9); Mat D,V; myEigen(A,D,V); Mat A_r=V.t()*D*V; cout<<"原矩陣 A ="<<endl<<A<<endl; cout<<"重構矩陣A_r="<<endl<<A_r<<endl<<endl; cout<<"D="<<endl<<D<<endl; cout<<"V="<<endl<<V<<endl; return 0; }
輸出結果如下:
比較Matlab和Opencv中的D、V值:
Opencv中V的第一列,與Matlab中V的第一行數值一直,但排序相反,其它行列對比也基本一致。