線形代数
■ 逆行列(擬似逆行列)の計算
サンプル
逆行列の計算 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の要素を以下の様にセットする.
// (5) mat, sftに従ってsrc_imgをdst_imgに変換
関数cvTransform()により,色空間の写像を以下の式に従って求め,結果をdst_imgに格納する.
// (6) 結果をファイル出力
関数cvSaveImage()により,dst_imgをcolorbar_dst.pngとして保存する.
// (7) 結果を画面に表示
// (8) キー入力待ち
// (9) 後処理
実行結果例
入力画像(左),出力画像(右)