About BBS

曲線と形状

作成者: 怡土順一, 最終変更者: 怡土順一, 最終変更リビジョン: 309, 最終変更日時: 2007-09-26 01:28:01 +0900 (水, 26 9月 2007)

■ 曲線と形状の描画

OpenCVでは,数種類のプリミティブ形状を描画する関数が用意されている. 用意されている形状は,線分,矩形,円,楕円(扇形),凸多角形,任意の多角形である. なんらかの検出結果や探索範囲などを実際の画像上に重畳表示する際や, ヒストグラムなどのグラフ作成(可視化)の際などに利用される.

サンプル


図形の描画 cvLine, cvRectangle, cvCircle, cvEllipse

線分,矩形,円,楕円(扇形を含む)をランダムに描画する

サンプルコード

#include <cv.h> #include <highgui.h> #include <time.h> int main (int argc, char **argv) { int i; IplImage *img = 0; CvRNG rng = cvRNG (time (NULL)); CvPoint pt1, pt2; CvScalar rcolor; int irandom; // (1)画像領域を確保し初期化する img = cvCreateImage (cvSize (800, 800), IPL_DEPTH_8U, 3); cvZero (img); // (2)ランダムな線分を描画する for (i = 0; i < 5; i++) { pt1.x = cvRandInt (&rng) % (img->width); pt1.y = cvRandInt (&rng) % (img->height); pt2.x = cvRandInt (&rng) % (img->width); pt2.y = cvRandInt (&rng) % (img->height); irandom = cvRandInt (&rng); rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255); cvLine (img, pt1, pt2, rcolor, cvRandInt (&rng) % 4, CV_AA, 0); } // (3)ランダムな矩形を描画する for (i = 0; i < 5; i++) { pt1.x = cvRandInt (&rng) % (img->width); pt1.y = cvRandInt (&rng) % (img->height); pt2.x = cvRandInt (&rng) % (img->width); pt2.y = cvRandInt (&rng) % (img->height); irandom = cvRandInt (&rng); rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255); cvRectangle (img, pt1, pt2, rcolor, cvRandInt (&rng) % 5 - 1, CV_AA, 0); } // (4)ランダムな円を描画する for (i = 0; i < 5; i++) { pt1.x = cvRandInt (&rng) % (img->width); pt1.y = cvRandInt (&rng) % (img->height); irandom = cvRandInt (&rng); rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255); cvCircle (img, pt1, cvRandInt (&rng) % (img->width / 4) + img->width / 4, rcolor, cvRandInt (&rng) % 5 - 1, CV_AA, 0); } // (5)ランダムな楕円を描画する for (i = 0; i < 5; i++) { pt1.x = cvRandInt (&rng) % (img->width); pt1.y = cvRandInt (&rng) % (img->height); irandom = cvRandInt (&rng); rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255); cvEllipse (img, pt1, cvSize (img->width / 2, img->height / 2), irandom % 180, irandom % 90, irandom % 90 + 90, rcolor, cvRandInt (&rng) % 5 - 1, 0); } // (6)画像の表示,キーが押されたときに終了 cvNamedWindow ("Drawing", CV_WINDOW_AUTOSIZE); cvShowImage ("Drawing", img); cvWaitKey (0); cvDestroyWindow ("Drawing"); cvReleaseImage (&img); return 0; }

// (1)画像領域を確保し初期化する
このサンプルでは,外部画像を読み込まずに,プログラム内部で画像を用意する. また,作成されたカラー画像を,黒(0)で塗りつぶして初期化する.

// (2)ランダムな線分を描画する
画像内に収まるように,ランダムなサイズと色を持つ線分を5本作成し,描画する.

// (3)ランダムな矩形を描画する
画像内に収まるように,ランダムなサイズと色を持つ矩形を5つ作成し,描画する.

// (4)ランダムな円を描画する
画像内に収まるように,ランダムなサイズと色を持つ円を5つ作成し,描画する.

// (5)ランダムな楕円を描画する
画像内に収まるように,ランダムなサイズと色を持つ楕円を5つ作成し,描画する.

// (6)画像の表示,キーが押されたときに終了
結果の画像を表示し,何かキーが押されるまで待つ.

実行結果例


ポリゴンの描画 cvFillpoly

1つのあるいは複数のポリゴンによって区切られた領域を塗りつぶす

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { IplImage *img1, *img2, *img3; int npts[3] = { 3, 3, 4 }; CvPoint **pts; // (1)画像を確保し初期化する img1 = cvCreateImage (cvSize (500, 500), IPL_DEPTH_8U, 3); img2 = cvCloneImage (img1); img3 = cvCloneImage (img1); cvZero (img1); // (2)ポリゴンの頂点を配列に代入 pts = (CvPoint **) cvAlloc (sizeof (CvPoint *) * 3); pts[0] = (CvPoint *) cvAlloc (sizeof (CvPoint) * 3); pts[1] = (CvPoint *) cvAlloc (sizeof (CvPoint) * 3); pts[2] = (CvPoint *) cvAlloc (sizeof (CvPoint) * 4); pts[0][0].x = 0 + 50; pts[0][0].y = int (200 * 1.73) + 50; pts[0][1].x = 200 + 50; pts[0][1].y = 0 + 50; pts[0][2].x = 400 + 50; pts[0][2].y = int (200 * 1.73) + 50; pts[1][0].x = 0 + 50; pts[1][0].y = 0 + 50; pts[1][1].x = 200 + 50; pts[1][1].y = int (200 * 1.73) + 50; pts[1][2].x = 400 + 50; pts[1][2].y = 0 + 50; pts[2][0].x = 200; pts[2][0].y = int (200 * 1.73 / 2.0) + 50; pts[2][1].x = 200 + 50; pts[2][1].y = int (200 * 1.73 * 1 / 4.0) + 50; pts[2][2].x = 200 + 100; pts[2][2].y = int (200 * 1.73 / 2.0) + 50; pts[2][3].x = 200 + 50; pts[2][3].y = int (200 * 1.73 * 3 / 4.0) + 50; // (3)ポリゴンを描画する cvFillPoly (img1, pts, npts, 1, CV_RGB (255, 0, 0)); cvFillPoly (img2, pts, npts, 2, CV_RGB (255, 0, 0)); cvFillPoly (img3, pts, npts, 3, CV_RGB (255, 0, 0)); // (4)画像の表示,キーが押されたときに終了 cvNamedWindow ("Fillpoly1", CV_WINDOW_AUTOSIZE); cvShowImage ("Fillpoly1", img1); cvNamedWindow ("Fillpoly2", CV_WINDOW_AUTOSIZE); cvShowImage ("Fillpoly2", img2); cvNamedWindow ("Fillpoly3", CV_WINDOW_AUTOSIZE); cvShowImage ("Fillpoly3", img3); cvWaitKey (0); cvDestroyWindow ("Fillpoly1"); cvDestroyWindow ("Fillpoly2"); cvDestroyWindow ("Fillpoly3"); cvReleaseImage (&img1); cvReleaseImage (&img2); cvReleaseImage (&img3); cvFree (&pts[0]); cvFree (&pts[1]); cvFree (&pts[2]); cvFree (pts); return 0; }

// (1)画像を確保し初期化する
このサンプルでは,外部画像を読み込まずに,プログラム内部で画像を用意する. また,作成されたカラー画像を,黒(0)で塗りつぶして初期化する.

// (2)ポリゴンの頂点を配列に代入
描画するためのポリゴンを定義する. 3頂点のポリゴン(三角形)を二つ,4頂点のポリゴン(四角形)を一つ,分の頂点を, CvPointの二次元配列ptsに代入する.

// (3)ポリゴンを描画する
関数cvFillPoly()の4番目の引数は,与えられた配列のうち,実際に描画されるポリゴンの個数を表しており, 今回は,三つのポリゴン(を表す頂点座標)が与えれているので,この引数が取りうる範囲は1〜3になる. これは,内部的に配列のインデックスとして利用されるので,0や,用意されたポリゴン数を越えるような値を指定することはできない.

// (4)画像の表示,キーが押されたときに終了
結果の画像を表示し,何かキーが押されるまで待つ. 1番目の画像は,単に三角形のポリゴンを表示するだけであるが,2番目の画像では, 二つの三角形ポリゴン(1番目の画像のポリゴンとそれを上下反転したポリゴン)の重ね合わせが表示されている.重なった場所は,ポリゴンの塗りつぶしが行われない. 3番目の画像では,さらに四角形(菱形)のポリゴンが追加されており,三つのポリゴンが重なった場所では, 通常どおりに塗りつぶしが行われている事が分かる.

実行結果例


凸ポリゴンの描画 cvFillConvexpoly

1つの凸ポリゴンを塗りつぶす

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { int i; IplImage *img1, *img2; CvPoint *pts; // (1)画像領域を確保し初期化する img1 = cvCreateImage (cvSize (400, 400), IPL_DEPTH_8U, 3); cvZero (img1); img2 = cvCloneImage (img1); // (2)ポリゴンの頂点を配列に代入 pts = (CvPoint *) cvAlloc (sizeof (CvPoint) * 4); pts[0].x = 100; pts[0].y = 100; pts[1].x = 200; pts[1].y = 150; pts[2].x = 140; pts[2].y = 300; pts[3].x = 30; pts[3].y = 200; // (3)凸ポリゴンを描画する cvFillConvexPoly (img1, pts, 4, CV_RGB (255, 0, 0), CV_AA, 0); cvFillConvexPoly (img1, pts, 4, CV_RGB (0, 255, 0), CV_AA, 1); // (4)ポリゴンの座標を1ビット右シフトさせて,描画する for (i = 0; i < 4; i++) { pts[i].x >>= 1; pts[i].y >>= 1; } cvFillConvexPoly (img2, pts, 4, CV_RGB (0, 0, 255), CV_AA, 0); // (5)画像の表示,キーが押されたときに終了 cvNamedWindow ("Fillconvexpoly1", CV_WINDOW_AUTOSIZE); cvShowImage ("Fillconvexpoly1", img1); cvNamedWindow ("Fillconvexpoly2", CV_WINDOW_AUTOSIZE); cvShowImage ("Fillconvexpoly2", img2); cvWaitKey (0); cvDestroyWindow ("Fillconvexpoly1"); cvDestroyWindow ("Fillconvexpoly2"); cvReleaseImage (&img1); cvReleaseImage (&img2); cvFree (&pts); return 0; }

// (1)画像領域を確保し初期化する
このサンプルでは,外部画像を読み込まずに,プログラム内部で画像を用意する. また,作成されたカラー画像を,黒(0)で塗りつぶして初期化する.

// (2)ポリゴンの頂点を配列に代入
4頂点の凸ポリゴン(四角形)を一つ描画するために,そのポリゴンの頂点座標を定義する.

// (3)凸ポリゴンを描画する
上で定義した凸ポリゴンを描画する. 関数cvFillConvexPoly()の最後の引数は,頂点座標のShift量を表しており, 例えば,ここに"1"を指定すると,座標値の下位1ビットは小数点以下を表すビットであると見なされる. つまり,各頂点座標が1ビット右シフトされた(座標値が1/2になった)ポリゴンとほぼ同じものが表示される. ここでは,赤色で指定座標そのままのポリゴンを,緑色で最後に引数に"1"を指定した場合のポリゴンを描画する. また,その輪郭が水平なスキャンラインと2回以下しか交差しないような単純なポリゴンを仮定しているため, この関数cvFillConvexPoly()は,関数cvFillPoly()よりも高速に動作する.

// (4)ポリゴンの座標を1ビット右シフトさせて,描画する
比較のために,各座標値を右に1ビットシフトさせたポリゴンを,別画像に青色で描画する.

// (5)画像の表示,キーが押されたときに終了
結果の画像それぞれを表示し,何かキーが押されるまで待つ.

実行結果例

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


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