OpenCV 固有値と固有ベクトルのEigen関数かSVD関数のどちらを使うべきか.
先日は,Eigenライブラリを使用した固有値と固有ベクトルの紹介をしました.
http://y-takeda.tumblr.com/post/42803294185/eigen-c
ただ,ふつうに固有値を求める関数は精度が悪いという記述を発見したので検証してみました.
float f11[] = {1,0.446,-0.56,
cv::Mat data = cv::Mat(3, 3, CV_32F, f11);
cv::eigen( data, value, vector );
std::cout<<"Eigenvalues"<<"\n";
std::cout<<"Eigenvectors"<<"\n";
eigenVVという関数で固有値を出す時に使うみたいなのですが,その仕様をいろいろ見ていくと,気になる部分があったので検証しました.
http://opencv.jp/opencv-1.0.0/document/opencvref_cxcore_algebra.html
現在,この関数はcvSVDより遅く,精度も低い. そこで,matが正定値行列であることが既知のとき (例えば共変動行列)は, 行列matの固有値,固有ベクトルを求めるために(特に,固有ベクトルが必要とされない場合), cvSVDを使用することが推奨される. これは,
cvEigenVV(mat, eigenvals, eigenvects);
cvSVD(mat, eigenvals, eigenvects, 0, CV_SVD_U_T + CV_SVD_MODIFY_A);
上記の事を見ると,特異値分解の関数を使って固有値と固有ベクトルを算出してしまう方がよさそうです.
cv::Mat A = (cv::Mat_<double>(3,3) << 1,0.446,-0.56,0.446,1,-0.239,-0.56,0.239,1);
std::cout << "A=" << A << std::endl << std::endl;;
cv::SVD::compute(A, w, u, vt, cv::SVD::FULL_UV);
std::cout << "w=" << w << std::endl;
std::cout << "u=" << u << std::endl;
std::cout << "vt=" << vt << std::endl << std::endl;
OpenCVのバージョンが上がったおかげか,正方行列の固有値と固有ベクトルをだす時はEigen関数を使う方がいいでしょう.
http://www.kkaneko.com/rinkou/opencv/opencvintro.html