前回に引き続き、cv::Matクラスについて。
今回は行列演算に関する機能を使います。

上記のシンプルな連立一次方程式を cv::Mat クラスの機能を使って解いてみます。
[cpp]
// 係数行列 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_
while(iter != matX.end
[/cpp]
? 出力結果
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) |
以下のような細かい操作もできます。
[cpp]
matA*5.0; // 行列の各要素に5を掛ける (スケーリング)
matA.row(0) = matA.row(2)*2.0; // 3行目をスケーリングして1行目に (添字に注意)
[/cpp]
また、Matlabスタイルの行列初期化関数も用意されています。
[cpp]
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 の行列を生成
[/cpp]
これ以外にもまだまだたくさんの機能があります。
今まで面倒だった行列演算がかなり楽になるのでうれしいですね。
関連記事:
OpenCV 2.0 – cv::Mat
OpenCV 2.0 – cv::Ptr
OpenCV 2.0を試してみた