About BBS

データの読み込み

作成者: 怡土順一, 最終変更者: 怡土順一, 最終変更リビジョン: 345, 最終変更日時: 2007-10-20 07:42:30 +0900 (土, 20 10月 2007)

■ データの読み込み

OpenCVでは,cvWriteなどの関数によって出力されたデータを読み込む関数が複数用意されている. 単純なマップの場合は,関数cvGetFileNodeByName()でノードを取得し,関数cvRead()で読み込みを行う. シーケンスの場合は,CvSeqReaderを利用してデータを走査する. その場合は,関数cvReadIntByName()によって直接値を得る,あるいは関数cvGetHashedNode()によって得られるユニークな値のポインタを利用して値を得る,などの方法を利用する.

サンプル


IplImage構造体情報の読み込み cvRead, cvGetFileNodeByName

IplImage構造体の情報をファイルから読み込む

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char *argv[]) { IplImage *color_img, *gray_img; CvRect roi_color, roi_gray; CvFileStorage *fs; CvFileNode *node; // (1)ファイルを読み込む if (argc != 2 || (fs = cvOpenFileStorage (argv[1], 0, CV_STORAGE_READ)) == 0) return -1; node = cvGetFileNodeByName (fs, NULL, "color_img"); color_img = (IplImage *) cvRead (fs, node); node = cvGetFileNodeByName (fs, NULL, "gray_img"); gray_img = (IplImage *) cvRead (fs, node); cvReleaseFileStorage (&fs); // (2)ROI情報を取得し矩形を描いた後,解放 roi_color = cvGetImageROI (color_img); roi_gray = cvGetImageROI (gray_img); cvResetImageROI (color_img); cvResetImageROI (gray_img); cvRectangle (color_img, cvPoint (roi_color.x, roi_color.y), cvPoint (roi_color.x + roi_color.width, roi_color.y + roi_color.height), CV_RGB (255, 0, 0)); cvRectangle (gray_img, cvPoint (roi_gray.x, roi_gray.y), cvPoint (roi_gray.x + roi_gray.width, roi_gray.y + roi_gray.height), cvScalar (0)); // (3)画像を描画 cvNamedWindow ("Color Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Color Image", color_img); cvNamedWindow ("Grayscale Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Grayscale Image", gray_img); cvWaitKey (0); cvDestroyWindow ("Color Image"); cvDestroyWindow ("Grayscale Image"); cvReleaseImage (&color_img); cvReleaseImage (&gray_img); return 0; }

// (1)ファイルを読み込む
コマンド引数で指定されたファイルをオープンし,関数cvOpenFileStorage()によりファイルストレージポインタを得る. 関数cvGetFileNodeByName()により,"color_img"と,"gray_img"という名前からノードを取得し, 関数cvRead()によりデータを読み込む.

// (2)ROI情報を取得し矩形を描いた後,解放
関数cvGetImageROI()により,読み込んだIplImage構造体からROIの情報を抽出し,その矩形を描く. また,そのために画像のROIを解放しておく.

// (3)画像を描画
実際に,ファイルから読み込まれた画像を表示し,何かキーが押されるまで待つ.

実行結果例

ここで読み込まれているファイルは,IplImage構造体情報の保存で保存されたxmlファイルである.


マップのシーケンスを読み込む cvGetHashedKey, cvGetFileNode

二つのエントリを持つマップのシーケンスをファイルから読み込む.これは,リファレンスマニュアル内のサンプルとほぼ同一である.

サンプルコード

#include <cv.h> #include <stdio.h> int main (int argc, char **argv) { // (1)ファイルストレージのオープン,ハッシュドキーの計算,シーケンスノードの取得 CvFileStorage *fs = cvOpenFileStorage ("sequence.yml", 0, CV_STORAGE_READ); CvStringHashNode *x_key = cvGetHashedKey (fs, "x", -1, 1); CvStringHashNode *y_key = cvGetHashedKey (fs, "y", -1, 1); CvFileNode *points = cvGetFileNodeByName (fs, 0, "points"); // (2)シーケンスリーダを初期化,各ノードを順次取得 if (CV_NODE_IS_SEQ (points->tag)) { CvSeq *seq = points->data.seq; int i, total = seq->total; CvSeqReader reader; cvStartReadSeq (seq, &reader, 0); for (i = 0; i < total; i++) { CvFileNode *pt = (CvFileNode *) reader.ptr; #if 1 // (3)高速バージョン CvFileNode *xnode = cvGetFileNode (fs, pt, x_key, 0); CvFileNode *ynode = cvGetFileNode (fs, pt, y_key, 0); assert (xnode && CV_NODE_IS_INT (xnode->tag) && ynode && CV_NODE_IS_INT (ynode->tag)); int x = xnode->data.i; /* あるいは x = cvReadInt( xnode, 0 ); */ int y = ynode->data.i; /* あるいは y = cvReadInt( ynode, 0 ); */ #elif 1 // (4)低速バージョン.x_keyとy_keyを使わない CvFileNode *xnode = cvGetFileNodeByName (fs, pt, "x"); CvFileNode *ynode = cvGetFileNodeByName (fs, pt, "y"); assert (xnode && CV_NODE_IS_INT (xnode->tag) && ynode && CV_NODE_IS_INT (ynode->tag)); int x = xnode->data.i; /* あるいは x = cvReadInt( xnode, 0 ); */ int y = ynode->data.i; /* あるいは y = cvReadInt( ynode, 0 ); */ #else // (5)さらに低速だが,使いやすいバージョン int x = cvReadIntByName (fs, pt, "x", 0); int y = cvReadIntByName (fs, pt, "y", 0); #endif // (6)データを表示し,次のシーケンスノードを取得 CV_NEXT_SEQ_ELEM (seq->elem_size, reader); printf ("%d: (%d, %d)\n", i, x, y); } } cvReleaseFileStorage (&fs); return 0; }

// (1)ファイルストレージのオープン,ハッシュドキーの計算,シーケンスノードの取得
最初に,ファイル名を指定してファイルストレージをオープンする. また,各シーケンスの二つのエントリのキーである"x","y"に対するユニークな値を 関数cvGetHashedKey()により計算して,CvStringHashNode型のポインタを取得する. ここで,関数cvGetHashedKey()の第3引数は,キーの名前の長さであるので, ここでは,"1"を指定しても良いが,0以下の値を指定することで自動的に文字列の長さが計算される.
オープンされたファイルノードから,"points"という名前を持つシーケンスノードのポインタを取得する.

// (2)シーケンスリーダを初期化,各ノードを順次取得
関数cvStartReadSeq()を用いて,シーケンスリーダによる連続読み出し処理を初期化し,順次ノードを読み込む. ノードの取得は,初期化されたシーケンスリーダが指すノード(ptrメンバ)をキャストすることで行われる. また,これらの処理の前に,あらかじめ取得したファイルノードの種類がシーケンスであることを確認するために, マクロCV_NODE_IS_SEQ()を利用している. ノードのメンバtagを利用して,そのノードの種類を知るマクロは,CV_NODE_IS_*という形で,cxtypes.h内で定義されている.

// (3)高速バージョン
あらかじめ計算されたCvStringHashNode型のポインタを利用して,"x","y"の名前を持つノードを取得する. これは,キーの文字列の内容を比較するのではなく,ユニークなポインタを比較することによりノードを求めるため, 後述の関数cvGetFieleNodeByName()と比べると若干高速に動作する. また,取得したノードの値を直接参照する方が,関数cvReadInt()を利用して値を読み出すよりも若干高速である.

// (4)低速バージョン.x_keyとy_keyを使わない
関数cvGetFieleNodeByName()によりノードを取得する事以外は,前述の例と同様.

// (5)さらに低速だが,使いやすいバージョン
関数cvReadIntByName()は,その内部で関数cvGetFileNodeByNameと,関数cvReadInt()を呼び出している. 関数cvReadInt()の呼び出し分のオーバヘッドがかかるため,上述の例よりもさらに少しだけ低速になる.

// (6)データを表示し,次のシーケンスノードを取得
上述のいずれかの方法で取得された値を表示する. また, マクロCV_NEXT_SEQ_ELEM()により,シーケンスリーダの指すノードを要素のサイズ分だけ進めて(あるいはブロックを切替えて), 次のノードを取得する.

実行結果例

ここで読み込まれているファイルは,マップのシーケンスを保存で保存されたYAMLファイルである.

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


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