線形代数
■ 逆行列(擬似逆行列)の計算
サンプル
逆行列の計算 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) 後処理
実行結果例
入力画像(左),出力画像(右)