前回に引き続き、cv::Matクラスについて。
今回は行列演算に関する機能を使います。
上記のシンプルな連立一次方程式を cv::Mat クラスの機能を使って解いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 係数行列 A float dataA[][3] = { {1.0, -2.0, 3.0}, {3.0, 1.0, -5.0}, {-2.0, 6.0, -9.0} }; // 行列 B float dataB[] = {1.0, -4.0, -2.0}; Mat matA(3, 3, CV_32FC1, dataA); Mat matB(3, 1, CV_32FC1, dataB); Mat matX(3, 1, CV_32FC1); // AX = B を解く. 両辺にAの逆行列を前掛けする matX = matA.inv()*matB; MatConstIterator_<float> iter = matX.begin<float>(); while(iter != matX.end<float>()) printf("%.1f\n", *iter++); |
? 出力結果
1 2 3 |
1.0 // x 3.0 // y 2.0 // z |
CvMatでは cvmInvert -> cvmMul と関数を順番に呼び出さないといけないところを、
cv::Matなら matX = matA.inv()*matB のように直感的に行列演算を行うことができます。
また、今回のような線形な問題であれば solve(matA, matB, matX) で解くこともできます。
基本的な行列演算
CvMat | cv::Mat | |
---|---|---|
X = A + B | cvmAdd(A, B, X) | X = A + B |
X = A – B | cvmSub(A, B, X) | X = A – B |
X = AB | cvmMul(A, B, X) | X = A * B |
X = A-1 (逆行列) | cvmInvert(A, X) | X = A.inv() |
X = AT (転置行列) | cvmTranspose(A, X) | X = A.t() |
X = A・B (内積) | cvmDotProduct(A, B) | X = A.dot(B) |
X = A × B (外積) | cvmCrossProduct(A, B, X) | X = A.cross(B) |
|A| (行列式) | cvmDet(A) | determinant(A) |
以下のような細かい操作もできます。
1 2 3 |
matA*5.0; // 行列の各要素に5を掛ける (スケーリング) matA.row(0) = matA.row(2)*2.0; // 3行目をスケーリングして1行目に (添字に注意) |
また、Matlabスタイルの行列初期化関数も用意されています。
1 2 3 |
Mat zero = Mat::zeros(3, 3, CV_32FC1); // 零行列を生成 Mat eye = Mat::eye(3, 3, CV_32FC1); // 単位行列を生成 Mat one = Mat::ones(3, 3, CV_32FC1); // 全要素が 1 の行列を生成 |
これ以外にもまだまだたくさんの機能があります。
今まで面倒だった行列演算がかなり楽になるのでうれしいですね。
関連記事:
OpenCV 2.0 – cv::Mat
OpenCV 2.0 – cv::Ptr
OpenCV 2.0を試してみた