シンプルGUI
■ ウィジェット(コントロール)
OpenCV-1.0.0で利用できるウィジェット(コントロール)は,画像を表示するためのウィンドウ,およびトラックバーのみである. 複雑なGUIデザインやイベントを適切に読み飛ばすといった処理が難しく, カメラキャプチャにおいても解像度の変更やフレームレートの設定などに難点 があるので,簡単なテストプログラム以外では,別のライブラリを利用するほうが無難である.サンプル
トラックバーの利用 cvCreateTrackbar, cvGetTrackbarPos, cvSetTrackbarPos
トラックバーの作成,その位置の取得と設定
サンプルコード
#include <cv.h> #include <highgui.h> #include <stdio.h> /* グローバル変数 */ CvFont font; IplImage *img = 0; /* プロトタイプ宣言 */ void on_trackbar1 (int val); void on_trackbar2 (int val); int main (int argc, char *argv[]) { // (1)画像領域を確保し,初期化する img = cvCreateImage (cvSize (400, 200), IPL_DEPTH_8U, 3); cvZero (img); cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0); // (2)ウィンドウ,およびトラックバーを作成する cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvCreateTrackbar ("Trackbar1", "Image", 0, 100, on_trackbar1); cvCreateTrackbar ("Trackbar2", "Image", 0, 100, on_trackbar2); cvShowImage ("Image", img); cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&img); return 0; } /* コールバック関数 */ void on_trackbar1 (int val) { char str[64]; // (3)トラックバー2を,トラックバー1に同期させる cvSetTrackbarPos ("Trackbar2", "Image", val); // (4)トラックバー1の値を描画する cvRectangle (img, cvPoint (0, 0), cvPoint (400, 50), cvScalar (0), CV_FILLED); snprintf (str, 64, "%d", val); cvPutText (img, str, cvPoint (15, 30), &font, CV_RGB (0, 200, 100)); cvShowImage ("Image", img); } void on_trackbar2 (int val) { char str[64]; int pos1, pos2; // (5)トラックバー2の移動範囲を,トラックバー1の値±20に限定する pos1 = cvGetTrackbarPos ("Trackbar1", "Image"); if (pos1 > val) pos2 = pos1 - 20 < val ? val : pos1 - 20; else pos2 = pos1 + 20 > val ? val : pos1 + 20; cvSetTrackbarPos ("Trackbar2", "Image", pos2); // (6)トラックバー2の値を描画する cvRectangle (img, cvPoint (0, 50), cvPoint (400, 100), cvScalar (0), CV_FILLED); snprintf (str, 64, "%d", val); cvPutText (img, str, cvPoint (15, 80), &font, CV_RGB (200, 200, 0)); cvShowImage ("Image", img); }
// (1)画像領域を確保し,初期化する
画像領域を確保し,初期化する.
また,後に結果の文字列を描画するためのフォント構造体を初期化する.
// (2)ウィンドウ,およびトラックバーを作成する
ウィンドウを作成後,関数cvCreateTrackbar()により,ウィンドウ上にトラックバーを追加する.
トラックバー作成時に,トラックバーイベントに対するコールバック関数(on_trackbar1,on_trackbar2)を設定する.
// (3)トラックバー2を,トラックバー1に同期させる
関数cvSetTrackbarPos()を用いて,トラックバー2の値を,トラックバー1の現在の値と同期させる.
// (4)トラックバー1の値を描画する
トラックバー1の現在の値を,画像領域上部に描画する.
// (5)トラックバー2の移動範囲を,トラックバー1の値±20に限定する
関数cvGetTrackbarPos()を用いて,トラックバー1の現在の値を取得し,
その値の±20の範囲内でトラックバー2が動くように設定する.
// (6)トラックバー2の値を描画する
トラックバー2の現在の値を,画像領域下部に描画する.
実行結果例
■ イベント
OpenCVでは,ウィンドウ上で発生したマウスイベント,およびウィンドウがアクティブな状態で押されたキーコードを取得できる.サンプル
マウスイベントの取得 cvSetMouseCallback
マウスイベントを取得して,ウィンドウに表示する
サンプルコード
#include <cv.h> #include <highgui.h> #include <stdio.h> /* グローバル変数 */ CvFont font; IplImage *img = 0; /* プロトタイプ宣言 */ void on_mouse (int event, int x, int y, int flags, void *param); int main (int argc, char *argv[]) { int c; // (1)画像領域を確保し,初期化する img = cvCreateImage (cvSize (640, 480), IPL_DEPTH_8U, 3); cvZero (img); cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 0.4, 0.4); // (2)ウィンドウを作成し,マウスイベントに対するコールバック関数を登録する cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvSetMouseCallback ("Image", on_mouse); cvShowImage ("Image", img); // (3)'Esc'キーが押された場合に終了する while (1) { c = cvWaitKey (0); if (c == '\x1b') return 1; } cvDestroyWindow ("Image"); cvReleaseImage (&img); return 0; } /* コールバック関数 */ void on_mouse (int event, int x, int y, int flags, void *param = NULL) { char str[64]; static int line = 0; const int max_line = 15, w = 15, h = 30; // (4)マウスイベントを取得 switch (event) { case CV_EVENT_MOUSEMOVE: snprintf (str, 64, "(%d,%d) %s", x, y, "MOUSE_MOVE"); break; case CV_EVENT_LBUTTONDOWN: snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_DOWN"); break; case CV_EVENT_RBUTTONDOWN: snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_DOWN"); break; case CV_EVENT_MBUTTONDOWN: snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_DOWN"); break; case CV_EVENT_LBUTTONUP: snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_UP"); break; case CV_EVENT_RBUTTONUP: snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_UP"); break; case CV_EVENT_MBUTTONUP: snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_UP"); break; case CV_EVENT_LBUTTONDBLCLK: snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_DOUBLE_CLICK"); break; case CV_EVENT_RBUTTONDBLCLK: snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_DOUBLE_CLICK"); break; case CV_EVENT_MBUTTONDBLCLK: snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_DOUBLE_CLICK"); break; } // (5)マウスボタン,修飾キーを取得 if (flags & CV_EVENT_FLAG_LBUTTON) strncat (str, " + LBUTTON", 64); if (flags & CV_EVENT_FLAG_RBUTTON) strncat (str, " + RBUTTON", 64); if (flags & CV_EVENT_FLAG_MBUTTON) strncat (str, " + MBUTTON", 64); if (flags & CV_EVENT_FLAG_CTRLKEY) strncat (str, " + CTRL", 64); if (flags & CV_EVENT_FLAG_SHIFTKEY) strncat (str, " + SHIFT", 64); if (flags & CV_EVENT_FLAG_ALTKEY) strncat (str, " + ALT", 64); // (6)マウス座標,イベント,修飾キーなどを画像に描画,表示 if (line > max_line) { cvGetRectSubPix (img, img, cvPoint2D32f (320 - 0.5, 240 - 0.5 + h)); cvPutText (img, str, cvPoint (w, 20 + h * max_line), &font, CV_RGB (0, 200, 100)); } else { cvPutText (img, str, cvPoint (w, 20 + h * line), &font, CV_RGB (0, 200, 100)); } line++; cvShowImage ("Image", img); }
// (1)画像領域を確保し,初期化する
画像領域を確保し,初期化する.
また,後に結果の文字列を描画するためのフォント構造体を初期化する.
// (2)ウィンドウを作成し,マウスイベントに対するコールバック関数を登録する
初期化した画像を表示し,関数 cvSetMouseCallback()を用いて,
マウスイベントに対するコールバック関数(on_mouse)を登録する.
// (3)'Esc'キーが押された場合に終了する
"Esc"キーが押された場合に終了する.'\x1b'は,"Esc"キーを表すが,この文字コードは"27"なので,
if( c == 27 )としても良い. また,その他のキーの場合は,以下のように指定すれば良い.
if( c == 'q' )
// (4)マウスイベントを取得
マウスイベントを取得する.取得できるマウスイベントは,マウスの移動と,
左,右,中央ボタンのDOWN,UP,ダブルクリックである.
ちなみに,ダブルクリックを行った際のマウスイベントは,
ボタンDOWN,ボタンUP,ボタンDOWN,ボタンダブルクリック,ボタンUPの順序で発生する.
// (5)マウスボタン,修飾キーを取得
イベント時に押されているマウスボタン,修飾キー(CTRL,ALT,SHIFT)を取得する.
これらのフラグは,各イベントフラグの論理和で表現される.
また,マウスボタンフラグは,ボタンDOWN時には発生しないが,ボタンUP時には発生する.
// (6)マウス座標,イベント,修飾キーなどを画像に描画,表示
現在のマウス座標,マウスイベント,修飾キー全てを画像に描画し,表示する.
また,関数cvGetRectSubPix() を利用して,画面をスクロールさせる.
実行結果例
■ カメラ
OpenCVでは,実際のカメラや動画像ファイルからキャプチャを行ったり,逆に画像列を動画像ファイルとして書き出したりすることが可能である.カメラからの画像キャプチャ cvCaptureFromCAM, cvQueryFrame
指定された番号のカメラから画像をキャプチャして表示する
サンプルコード
#include <cv.h> #include <highgui.h> #include <ctype.h> int main (int argc, char **argv) { CvCapture *capture = 0; IplImage *frame = 0; double w = 320, h = 240; int c; // (1)コマンド引数によって指定された番号のカメラに対するキャプチャ構造体を作成する if (argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit (argv[1][0]))) capture = cvCreateCameraCapture (argc == 2 ? argv[1][0] - '0' : 0); /* この設定は,利用するカメラに依存する */ // (2)キャプチャサイズを設定する. cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, w); cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h); cvNamedWindow ("Capture", CV_WINDOW_AUTOSIZE); // (3)カメラから画像をキャプチャする while (1) { frame = cvQueryFrame (capture); cvShowImage ("Capture", frame); c = cvWaitKey (2); if (c == '\x1b') break; } cvReleaseCapture (&capture); cvDestroyWindow ("Capture"); return 0; }
// (1)コマンド引数によって指定された番号のカメラに対するキャプチャ構造体を作成する
コマンド引数として与えられた番号のカメラに対する,キャプチャ構造体 CvCaptureを作成する.
引数が指定されない場合は,デフォルトの値である"0"が利用される.
// (2)キャプチャサイズを設定する
関数cvSetCaptureProperty()により,キャプチャをおこなう際の画面サイズ(幅と高さ)を指定する.
ただし,実際のカメラがサポートしていないキャプチャサイズは指定できない.
// (3)カメラから画像をキャプチャする
ループブロック中に関数 cvQueryFrame() を呼び出すことで,実際にキャプチャを行い,
それを表示する.
キャプチャ中に"Esc"キーが押された場合は,終了する.