About BBS

線形代数

作成者: 小枝正直, 最終変更者: 怡土順一, 最終変更リビジョン: 474, 最終変更日時: 2009-07-02 02:47:38 +0900 (木, 02 7月 2009)
This is a local copy taken at 2010/09/20. CLICK HERE to the original page at opencv.jp.

■ 逆行列(擬似逆行列)の計算

サンプル


逆行列の計算 cvInvert

逆行列の計算を行う

サンプルコード

#include <stdio.h> #include <highgui.h> #include <time.h> int main (int argc, char **argv) { int i, j; int nrow = 3; int ncol = 3; CvMat *src, *dst, *mul; double det; CvRNG rng = cvRNG (time (NULL)); /* 乱数の初期化 */ // (1) 行列のメモリ確保 src = cvCreateMat (nrow, ncol, CV_32FC1); dst = cvCreateMat (ncol, nrow, CV_32FC1); mul = cvCreateMat (nrow, nrow, CV_32FC1); // (2) 行列srcに乱数を代入 printf ("src\n"); cvmSet (src, 0, 0, 1); for (i = 0; i < src->rows; i++) { for (j = 0; j < src->cols; j++) { cvmSet (src, i, j, cvRandReal (&rng)); printf ("% lf\t", cvmGet (src, i, j)); } printf ("\n"); } // (3) 行列srcの逆行列を求めて,行列dstに代入 det = cvInvert (src, dst, CV_SVD); // (4) 行列srcの行列式を表示 printf ("det(src)=%lf\n", det); // (5) 行列dstの表示 printf ("dst\n"); for (i = 0; i < dst->rows; i++) { for (j = 0; j < dst->cols; j++) { printf ("% lf\t", cvmGet (dst, i, j)); } printf ("\n"); } // (6) 行列srcとdstの積を計算して確認 cvMatMul (src, dst, mul); printf ("mul\n"); for (i = 0; i < mul->rows; i++) { for (j = 0; j < mul->cols; j++) { printf ("% lf\t", cvmGet (mul, i, j)); } printf ("\n"); } // (7) 行列のメモリを開放 cvReleaseMat (&src); cvReleaseMat (&dst); cvReleaseMat (&mul); return 0; }

// (1) 行列のメモリ確保
関数cvCreateMat()により 32ビット浮動小数点数型1チャンネルの nrow行ncol列の行列src,ncol行nrow列の行列dst,nrow行nrow列の行列mutをそれぞれ用意する.

// (2) 行列srcに乱数を代入
関数cvRandReal()により行列srcに0以上1未満の浮動小数点数の適当な乱数を代入し, 行列の要素を表示する.

// (3) 行列srcの逆行列を求めて,行列dstに代入
関数cvInvert()により行列srcの逆行列を求め,行列dstに代入する. ここでは第3引数にCV_SVDを指定し,特異値分解により逆行列求めている.

// (4) 行列srcの行列式を表示
関数cvInvert()が返す行列srcの行列式を表示する. この値が小さすぎる場合,逆行列が求まらない場合があるので注意する.

// (5) 行列dstの表示
求められた行列dstを表示する.

// (6) 行列srcとdstの積を計算して確認
関数cvMatMul()により行列srcとdstの積を求め,単位行列になることを確認する.

実行結果例

■ 写像

サンプル


色空間の写像 cvTransform

行列とベクトルにより色空間を一度に写像する

サンプルコード

#include <cv.h> #include <highgui.h> #include <stdio.h> #include <ctype.h> int main (int argc, char **argv) { IplImage *src_img = 0, *dst_img = 0; CvMat *mat; CvMat *sft; // (1)画像読み込み src_img = cvLoadImage ("colorbar_src.png", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); if (src_img == 0) return -1; dst_img = cvCloneImage (src_img); if (dst_img == 0) return -1; // (2)変換行列とシフトベクトルのメモリ確保 mat = cvCreateMat (src_img->nChannels, src_img->nChannels, CV_32FC1); sft = cvCreateMat (src_img->nChannels, 1, CV_32FC1); // (3)変換行列の要素をセット // Bチャネルを破棄 cvmSet (mat, 0, 0, 0.0); // src_imgのBチャネル→dst_imgのBチャネル cvmSet (mat, 1, 0, 0.0); // src_imgのBチャネル→dst_imgのGチャネル cvmSet (mat, 2, 0, 0.0); // src_imgのBチャネル→dst_imgのRチャネル // GチャネルをRチャネルに変換 cvmSet (mat, 0, 1, 0.0); // src_imgのGチャネル→dst_imgのBチャネル cvmSet (mat, 1, 1, 0.0); // src_imgのGチャネル→dst_imgのGチャネル cvmSet (mat, 2, 1, 1.0); // src_imgのGチャネル→dst_imgのRチャネル // RチャネルをBチャネルに変換 cvmSet (mat, 0, 2, 1.0); // src_imgのRチャネル→dst_imgのBチャネル cvmSet (mat, 1, 2, 0.0); // src_imgのRチャネル→dst_imgのGチャネル cvmSet (mat, 2, 2, 0.0); // src_imgのRチャネル→dst_imgのRチャネル // (4)シフトベクトルの要素をセット cvmSet (sft, 0, 0, -128.0); // Bチャネルを-128 cvmSet (sft, 1, 0, 0.0); // Gチャネルはそのまま cvmSet (sft, 2, 0, 0.0); // Rチャネルはそのまま // (5)mat, sftに従ってsrc_imgをdst_imgに変換 cvTransform (src_img, dst_img, mat, sft); // (6)結果をファイル出力 cvSaveImage ("colorbar_dst.png", dst_img); // (7)結果を画面に表示 cvNamedWindow ("src", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst", CV_WINDOW_AUTOSIZE); cvShowImage ("src", src_img); cvShowImage ("dst", dst_img); // (8)キー入力待ち cvWaitKey (0); // (9)後処理 cvDestroyWindow ("src"); cvDestroyWindow ("dst"); cvReleaseImage (&src_img); return 0; }

// (1) 画像読み込み
関数cvLoadImage()により元画像colorbar_src.pngを読み込み,src_imgに格納する. また関数cvCloneImage()によりsrc_imgのコピーを作成し,dst_imgに格納する.

// (2) 変換行列とシフトベクトルのメモリ確保
関数cvCreateMat()により, src_imgのチャンネル数と同じ行数列数を持つ3x3浮動小数点型32ビット1チャンネルの変換行列matを作成する. 同様に3x1要素を持つシフトベクトルsftを作成する.

// (3) 変換行列の要素をセット // (4) シフトベクトルの要素をセット
関数cvmSet()により,matとsftの要素を以下の様にセットする.

mat = \left( {\begin{array}{*{20}r} 0.0 & 0.0 & 1.0 \\ 0.0 & 0.0 & 0.0 \\ 0.0 & 1.0 & 0.0 \\ \end{array}} \right)
sft = \left( {\begin{array}{*{20}r} -128.0 \\ 0.0 \\ 0.0 \\ \end{array}} \right)

// (5) mat, sftに従ってsrc_imgをdst_imgに変換
関数cvTransform()により,色空間の写像を以下の式に従って求め,結果をdst_imgに格納する.

\left( {\begin{array}{*{20}r} dst\_img.B \\ dst\_img.G \\ dst\_img.R \\ \end{array}} \right) = mat* \left( {\begin{array}{*{20}r} src\_img.B \\ src\_img.G \\ src\_img.R \\ \end{array}} \right) + sft

// (6) 結果をファイル出力
関数cvSaveImage()により,dst_imgをcolorbar_dst.pngとして保存する.

// (7) 結果を画面に表示

// (8) キー入力待ち

// (9) 後処理

実行結果例

入力画像(左),出力画像(右)

OpenCV-1.0 リファレンス マニュアル
OpenCV-1.1pre リファレンス マニュアル
OpenCVサンプルコード


画素値の直接操作
部分画像のシャッフル
画像の連結
画像のコピー
画像形状の変形
タイリング
画像の反転
逆行列(擬似逆行列)の計算
色空間の写像
離散フーリエ変換
階層構造を持つ輪郭の座標取得
図形の描画
ポリゴンの描画
凸ポリゴンの描画
テキストの描画
IplImage構造体情報の保存
マップのシーケンスを保存
IplImage構造体情報の読み込み
マップのシーケンスを読み込む
K-means法によるクラスタリング
クラスタリングによる減色処理
エッジの検出
コーナーの検出
並進移動のためのピクセルサンプリング
回転移動のためのピクセルサンプリング
画像のサイズ変更
画像のアフィン変換(1)
画像のアフィン変換(2)
画像の透視投影変換
全方位画像の透視投影変換
モルフォロジー変換
平滑化
ユーザ定義フィルタ
境界線の作成
画像の二値化
画像の二値化(大津の手法)
画像ピラミッドの作成
画像ピラミッドを用いた画像の領域分割
平均値シフト法による画像のセグメント化
Watershedアルゴリズムによる画像の領域分割
輪郭の検出と描画
画像のモーメントを計算
ハフ変換による直線検出
ハフ変換による円検出
距離変換とその可視化
不要オブジェクトの除去
ヒストグラムの描画
ヒストグラム間の距離
二次元のヒストグラム
バックプロジェクションパッチ
ヒストグラムの均一化
テンプレートマッチング
形状のマッチング
点列を包含する矩形
輪郭領域の面積と輪郭の長さ
二つの矩形を包含する矩形
楕円のフィッティング
点列を包含する図形
動的背景更新による物体検出
snakeによる輪郭追跡(静止画)
オプティカルフロー1
オプティカルフロー2
オプティカルフロー3
Condensation
顔の検出
カメラキャリブレーション
歪み補正
マップを利用した歪み補正
サポートベクターマシン
画像の各ピクセル値を特徴ベクトルとしたSVMの学習
画像の各ピクセル値を特徴ベクトルとしたSVMによる物体検出
マウスイベントの取得
トラックバーの利用
カメラからの画像キャプチャ
動画としてファイルへ書き出す
ラベリング