About BBS

木構造(Trees)

作成者: 怡土順一, 最終変更者: 怡土順一, 最終変更リビジョン: 356, 最終変更日時: 2007-12-04 16:54:53 +0900 (火, 04 12月 2007)

■ 木構造

OpenCVでは,代表的ないくつかのデータ構造があらかじめ定義されている.木構造は,その一つである. ここでは,木構造を持つデータをどのように扱うかの例を示す.

サンプル


輪郭座標の取得 cvInitTreeNodeIterator, cvNextTreeNode

輪郭の検出を行い,木構造を持つ輪郭データから座標を取り出す

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char *argv[]) { int i; IplImage *src_img = 0; IplImage *src_img_gray = 0; IplImage *tmp_img; CvMemStorage *storage = cvCreateMemStorage (0); CvSeq *contours = 0; CvPoint *point, *tmp; CvSeq *contour; CvTreeNodeIterator it; CvFileStorage *fs; if (argc >= 2) src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); if (src_img == 0) return -1; src_img_gray = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); cvCvtColor (src_img, src_img_gray, CV_BGR2GRAY); tmp_img = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); // (1)画像の二値化と輪郭の検出 cvThreshold (src_img_gray, tmp_img, 120, 255, CV_THRESH_BINARY); cvFindContours (tmp_img, storage, &contours, sizeof (CvContour), CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); /* 輪郭シーケンスから座標を取得 */ fs = cvOpenFileStorage ("contours.yaml", 0, CV_STORAGE_WRITE); // (2)ツリーノードイテレータの初期化 cvInitTreeNodeIterator (&it, contours, 1); // (3)各ノード(輪郭)を走査 while ((contour = (CvSeq *) cvNextTreeNode (&it)) != NULL) { cvStartWriteStruct (fs, "contour", CV_NODE_SEQ); // (4)輪郭を構成する頂点座標を取得 tmp = CV_GET_SEQ_ELEM (CvPoint, contour, -1); for (i = 0; i < contour->total; i++) { point = CV_GET_SEQ_ELEM (CvPoint, contour, i); cvLine (src_img, *tmp, *point, CV_RGB (0, 0, 255), 2); cvStartWriteStruct (fs, NULL, CV_NODE_MAP | CV_NODE_FLOW); cvWriteInt (fs, "x", point->x); cvWriteInt (fs, "y", point->y); cvEndWriteStruct (fs); tmp = point; } cvEndWriteStruct (fs); } cvReleaseFileStorage (&fs); cvNamedWindow ("Contours", CV_WINDOW_AUTOSIZE); cvShowImage ("Contours", src_img); cvWaitKey (0); cvDestroyWindow ("Contours"); cvReleaseImage (&src_img); cvReleaseImage (&src_img_gray); cvReleaseImage (&tmp_img); cvReleaseMemStorage (&storage); return 0; }

// (1)画像の二値化と輪郭の検出
ここまでの処理は, 輪郭の検出と描画でのサンプルと同一なので,そちらを参照のこと.

// (2)ツリーノードイテレータの初期化
検出された輪郭のシーケンスから座標を取得する. まず,関数cvInitTreeNodeIterator()により,ツリーノードイテレータを初期化する (必ず一つの輪郭しか持たないような単純な場合は,ツリーノードイテレータを利用せずとも構わない). ここで,最後の引数は,検出する輪郭の最大レベルを表している(ここではレベル2を指定している). つまりここでは,関数cvFindContours()で輪郭を検出する際に,第5引数にCV_RETR_TREEが指定される場合を想定している. 関数cvFindContours()の引数が,CV_RETR_EXTERNALの場合(最も外側の輪郭しか検出されない)と,CV_RETR_LISTの場合(リスト構造)は,検出された輪郭シーケンスが階層構造を持たないので,レベル指定は意味をなさない. CV_RETR_CCOMPの場合は,輪郭シーケンスが2階層の構造しかもたないので,2レベルまでですべての輪郭が取得できる. また,関数cvFindContours()の第6引数で,CV_CHAIN_CODE以外が指定されていなければならない. なぜなら,CV_CHAIN_CODEを指定した場合は,輪郭データが頂点のシーケンスではなくチェーンコードで表現されてしまうからである(もちろん,そこから座標を再計算することは可能である).

// (3)各ノード(輪郭)を走査
次に,関数cvNextTreeNode()により,順次ツリーノード(各輪郭シーケンス)へのポインタを得る. 返すのツリーノードが存在しなくなる,つまり最後のノードまでたどり着くと,この関数はNULLを返す.

// (4)輪郭を構成する頂点座標を取得
得られたノードの要素である座標データ(CvPoint)へのポインタを,マクロCV_GET_SEQ_ELEMにより取得する. そして取得された座標同士を直線で結ぶ(cvLine)ことで輪郭を描画し,さらに,各座標をファイルにYAML形式で保存する.
また,この方法で保存されたファイルは,木構造を保持せず,すべての枝(輪郭)が並列に並べられる.

実行結果例

[左]各座標を直線(青)で結んで表示された輪郭.[右]保存された輪郭データ(contours.yml).

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


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