FAST Vision Library シリーズ 画像処理ライブラリ WIL チュートリアル (FVCL) 第 2 版 FAST Vision Library シリーズ WIL Ver1.1 ( 株 ) ファースト
( 株 ) ファーストは 同社が提供していない装置における同社製ソフトウェア ハードウェアの使用または信頼性についてはいかなる責任も負いません ( 株 ) ファーストは本書で記載されているソフトウェア ハードウェアの内容 商品価値 又は特定の使用目的に対する責任に対して明示又は黙示に関わらずいかなる保証も行いません 本書の内容は 予告なしに変更することがあります 内容の変更について ( 株 ) ファーストはいかなる責任も負いません 本書あるいは関連ソフトウェアにおける誤りから生じる損害について ( 株 ) ファーストはいかなる責任も負いません 本書の内容の一部または全部を転載することは固くお断りします 御注意 Microsoft, Windows, Visual Studio, Visual C++, Visual C#, Visual Basic は 米国 Microsoft Corporation の登録商標です.NET は 米国 Microsoft Corporation の商標です Windows XP は 米国 Microsoft Corporation の商品名です Intel, MMX, Pentium は 米国 Intel Corporation の登録商標です その他 文中における会社名 商品名は各社の登録商標または商標です 文中では商標シンボル ((R) (TM) (C) 等 ) の表記は省略致します
目次 1. 開発環境の準備 1 2. プロジェクトの作成 3 3. ライブラリの初期化 5 4. 画像表示の準備 7 5. 画像ファイルの読み込み 11 6. 画像の 2 値化 13 7. カメラからの画像入力 15 8. オーバーレイ表示 19 [1]
[2]
本書では WIL(FVCL) の初期設定 ~ 画像の 2 値化までの流れについて説明します WIL チュートリアル (FVCL) 1. 開発環境の準備 WIL を使用したプログラム開発を始める前に まず VisualStudio のパス設定を行う必要があります 尚 本初期設定は WIL をはじめてお使い頂く際に一度行えば結構です 1.Microsoft Visual Studio 2005 を起動します 2. ツール メニューの オプション を選択します オプションダイアログが表示されます 3. 左側メニューの プロジェクトおよびソリューション の VC++ ディレクトリを選択します 4. 右側のドロップダウンリスト ディレクトリを表示するプロジェクト で インクルードファイル を選択し WIL のインクルードファイルのパスと EVC のインクルードパスを指定します デフォルトでは C:\Program Files\FAST\WIL\Include C:\Program Files\FAST\WIL\EVC となります -1-
5. ライブラリのパスを通します 右側のドロップダウンリスト ライブラリファイル で ライブラリファイル を選択し WIL の lib ファイルのパスを指定します 標準のディレクトリ構成でインストールした場合には C:\Program Files\FAST\WIL\Lib です -2-
2. プロジェクトの作成 開発環境の設定が終わったら 新規プロジェクトを作成します 1. メニューから ファイル (F) -> 新規作成(N) -> プロジェクト(P) を選択し 新しいプロジェクト ダイアログを表示させます 2. プロジェクトの種類を Visual C++ に設定し テンプレート (T) を選択します テンプレートに MFC アプリケーションを選択し プロジェクト名 場所を設定して OK をクリックしてください 今回は プロジェクト名を Sample1 とします アプリケーションの種類は ダイアログベース を指定してください この後に表示されるウィザードでは 変更点が無いので説明を省略します -3-
-4-
3. ライブラリの初期化 準備が完了したら早速コーディングを始めましょう 1. ソリューションエクスプローラより Sample1Dlg.cpp を開き WIL ライブラリの初期化 ( ライセンスチェック ) 関数を記述します WIL のほとんどの機能は この処理を行わなければ使うことができません BOOL CSample1Dlg CSample1Dlg::OnInitDialog() //~~~~~~ 中略 ~~~~~~~ // TODO: 初期化をここに追加します FVCL::InitVisionLibrary(); // WIL 初期化 OnInitDialog() は MFC でダイアログ生成した際必ず呼び出されます 2.EVC ライブラリのリソースを連結します EVC ライブラリを使うには 必ずこの処理が必要です BOOL CSample1Dlg CSample1Dlg::OnInitDialog() //~~~~~~ 中略 ~~~~~~~ // TODO: 初期化をここに追加します FVCL::InitVisionLibrary(); // WIL 初期化 FVCL::EVCbasic::DLLChainResource( NULL ); // EVC リソースの連結 -5-
-6-
4. 画像表示の準備 1. リソースビューより IDD_SAMPLE1_DIALOG をダブルクリックし表示します 2. ツールボックスより Picture Control を選択し IDD_ SAMPLE1_DIALOG に貼り付けます ここが画像表示領域となります -7-
3. 貼り付けた Picture Control のプロパティを表示し ID を任意の名称に変更します 本チュートリアルでは ID を IDC_STATIC_IMAGE_VIEW と変更します -8-
4. コントロールの変数を追加します 貼り付けた Picture Control を右クリックして 変数の追加 (B) を選択し 変数追加ウィザードを表示します 変数の種類を CStatic に 任意の変数名を記入して完了をクリックします 本チュートリアルでは 変数名を m_dummy とします -9-
5. コーディングを行います ソリューションエクスプローラより Sample1Dlg.h を開き コードの上の方に WIL ヘッダファイルのインクルード宣言を行います #pragma once #include "FVCLbasic.h" // 画像処理クラスヘッダ #include "EVCbasic.h" // GUI ライブラリヘッダ 6.Sample1Dlg.h の下の方に 画像メモリ管理クラス 画像ビュークラス オーバーレイクラスの変数を宣言します afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() FVCL::CFvImage m_image; // 画像メモリ管理クラス CEvView m_view; // 画像ビュークラス -10-
5. 画像ファイルの読み込み 1. ツールボックスより ダイアログへボタンコントロールを追加し プロパティより Caption を bmp ファイ ルの読込 ID を IDC_BUTTON_LOAD とします 2. bmp ファイルの読込 ボタンをダブルクリックし BN_CLICKED イベントハンドラ (OnBnClickedButtonLoadImage) を作成します -11-
3. OnBnClickedButtonLoadImage() 内の処理を追加します void CSample1Dlg::OnBnClickedButtonLoadImage() FVCL::CFvImageFileBmp pimagefile;//bmp ファイル読み込みクラスのオブジェクト生成 CFileDialog dlg(true,_t("bmp"),null,ofn_filemustexist OFN_HIDEREADONLY, _T("Imagefile(*.bmp) *.bmp; All files(*.*) *.* "), this); if(idok == dlg.domodal()) if(! pimagefile.load(dlg.getfilename(), &m_image)) // 画像のロード MessageBox(_T(" ファイルロード失敗 ")); else m_view.setimage(&m_image); // 画像をビューに設定します m_view.update(true); // ビューの表示を更新します 4. プログラムを保存し ビルド 実行してみましょう bmp ファイルの読込 をクリックし 任意の Gray 画像をロードします 左図のように画像が表示されれば成功です 画像上で左クリックし Ctrl キー + マウスホイールで画像の倍率が変わることを確認しましょう 補足として 画像表示の操作を行うライブラリをいくつか挙げます 表示倍率の縮小 :CEvView::DoReduce() 表示倍率の拡大 :CEvView::DoExpand() 表示倍率をビューに合わせる :CEvView::FitImageSize() 処理範囲設定 :CEvView::SetCursorType(FVCL::CursorType::PROCAREA) Aスコープ表示 :CEvView::SetCursorType(FVCL::CursorType::ASCOPE) -12-
6. 画像の 2 値化 Sample1 でロードした画像を 2 値化してみましょう 1. 画像の2 値化を行うには 2 値化した画像を保存するメモリを新たに追加する必要があります Sample1Dlg.h 内で 下記のように画像メモリを一枚宣言してください FVCL::CFvImage m_image; CEvView m_view; FVCL::CFvOverlay* m_overlay; FVCL::CFvImage m_imagebin; //2 値画像用メモリ 2. 次に 画像読込ボタンのときと同じ要領で ダイアログにボタンを追加し 名前を 画像の2 値化 ID を IDC_BUTTON_BINARIZE とします 3. 画像の2 値化 ボタンのイベントハンドラを追加し OnBnClickedButtonBinarize() 内の処理を追加します void CSample1Dlg::OnBnClickedButtonLoadImage() FVCL::Conversion::CFvBinarize binarize; //2 値化クラスのオブジェクト生成 binarize.setsrcimage(0,&m_image); // 入力画像の設定 binarize.setdstimage(0,&m_imagebin); // 出力画像の設定 if(binarize.validate()) // 出力画像を入力画像の型に合わせる binarize.setthreshold(100); //2 値化閾値の設定 binarize.execute(); //2 値化実行 m_view.setimage( &m_imagebin ); m_view.update(true); else int error_code = binarize.geterrorcode(); // エラーコードの取得 if(error_code == FVCL_ErrorCode::HAVE_NOT_IMAGE) MessageBox(_T(" 入力画像または出力画像が設定されていません ")); else if(error_code == FVCL_ErrorCode::FAILED_TO_ALLOCATE ) MessageBox(_T(" メモリが不足しています ")); -13-
Validate() を行うと 出力画像の大きさが 強制的に入力画像の大きさに合わせられますので 自分で画像メモリのサイズを合わせる必要がありません 又 Validate() はエラーコードを取得できますので GetErrorCode() によってエラーコードを取得しています Execute() もエラーコード取得できますがこの例では行っていません エラーを取得できるメソッドは WIL リファレンスマニュアルに記述がありますのでご覧下さい すべての画像処理の実行は Execute() メソッドで行います たとえば 2 値計測の場合は FVCL::CFvBlob::Execute() グレイサーチの場合は FVCL::CFvGSearch::Execute() のようになります 本ライブラリの画像処理は 下記の手順を基本とします 基本画像操作 画像解析 備考 入力設定 SetSrcImage SetSrcImage 処理対象画像を設定します 出力設定 SetDstImage SetResult 出力画像または出力データ配列を受け取るオブジェクトを設定します パラメータ調整 クラス毎に異なります 有効性検査 IsValid IsValid 入出力の有効性を検査します 有効化 Validate - 出力画像のサイズや画像種別を調整します 実行 Execute Execute 基本画像操作 階調変換 フィルタ アフィンなどの画像操作ライブラリを指します 画像解析 2 値計測 サーチ エッジ取得などの計測ライブラリを指します 4. プログラムを保存し ビルド 実行してみましょう 画像ロード後 画像の2 値化 ボタンを押し 左図のように画像が表示されれば成功です -14-
7. カメラからの画像入力 Sample1 では BMP ファイルのロードを行って画像処理を行っていましたが カメラからの画像入力を行って 画像処理をできるようにしてみましょう 本チュートリアルでは 画像入力ボード FVC05 を用いて画像入力を行います RICE-001(a/b) や FVC06 を使用する場合も同様の方法で使用することが可能ですが 画像入力ボードごとに機能が異なるため 設定できる関数等が異なります 各画像入力ボードの機能詳細はリファレンスマニュアルをご参照ください 1. カメラから画像入力を行うためには 画像入力ボード制御クラス (FVCL::CFvVideoFVC05) のインスタンスを用意します FVCL::CFvVideoFVC05 を使用するためには インクードファイル FVCLvideo.h をインクルードする必要があります 下記の 1 行を Sample1Dlg.h に追加してください #include FVCLvideo.h FVCL::CFvVideoFVC05 のインスタンスを生成します Sample1Dlg.h 内に下記の一行を追加してください FVCL::CFvImage m_image; CEvView m_view; FVCL::CFvOverlay* m_overlay; FVCL::CFvImage m_imagebin; FVCL::CFvVideoFVC05 m_video; //2 値画像用メモリ // 画像入力ボード制御 2. 画像入力ボードをオープンし カメラ設定ファイルからパラメータを読み込みます 画像入力ボードのオープンとは PC 内にある画像入力ボードを探し 引数で指定したボードを他のソフトウェアから制御できないように占有する処理のことを言います 画像入力ボードのオープンに成功したら 使用するカメラに合わせたパラメータを画像入力ボードに設定します 画像入力ボードの設定は複雑であるため FAST からカメラ設定ファイルが提供されています カメラ設定ファイルは WIL インストール先の \WIL\CameraFiles\ フォルダ配下に入れられています 使用するカメラ設定ファイルを CFvVideoFVC05 に読み込ませることで カメラに合わせたパラメータで画像入力ボードが初期化されます 画像の2 値化ボタンのときと同じ要領で ダイアログにボタンを追加し 名前を ビデオオープン ID を IDC_BUTTON_VIDEO_OPEN とします ビデオオープン ボタンのイベントハンドラを追加し OnBnClickedButtonVideoOpen() 内の処理を追加します -15-
void CSample1Dlg::OnBnClickedButtonVideoOpen() if(true == m_video.open(-1, 0)) //(1) 画像入力ボードのオープン FVCL::CFvString path; path=_t("c:\\program Files\\FAST\\WIL\\CameraFiles\\FVC05\\"); path+=_t("fvc05_xc-hr50_hr57.ini"); // XC-HR50, XC-HR57 用カメラ設定ファイル if( false == m_video.loadinifile(path) ) //(2) カメラ設定ファイル読み込み FVCL::CFvString err_msg; err_msg.format( _T("LoadIniFile Error : code=%d"), m_video.geterrorcode() ); MessageBox( err_msg ); else // (3) カメラの画像サイズと画像メモリのサイズを合わせる m_video.changeimagesize(&m_image); MessageBox( _T(" 画像入力ボードオープン成功 ") ); else switch( m_video.geterrorcode() ) case FVCL_ErrorCode::ALREADY_OPENED: MessageBox(_T(" 既にオープンされています ")); break; case FVCL_ErrorCode::INVALID_PARAMETER: MessageBox(_T(" 引数が間違っています ")); break; case FVCL_ErrorCode::FAILED_TO_ALLOCATE: MessageBox(_T(" メモリの確保が失敗しました ")); break; case FVCL_ErrorCode::FAILED_TO_OPEN: MessageBox(_T(" キャプチャボードのオープンに失敗しました ")); break; -16-
このプログラムでは次のことが行われています (1) 画像入力ボードのオープン画像入力ボードを探し 他のインスタンスから制御できないように占有するのがオープンの処理内容で Open 関数を用いて行います Open 関数は画像入力ボードに応じて 関数が異なります 関数第 1 引数第 2 引数第 3 引数 RICE-001(a/b) FVC05 FVC06 Open(INT,INT) ボード ID 無視 - Open(INT,INT) ボード ID 無視 - Open(INT,INT,INT) ボード ID コンフィグレーションチャネル (2) カメラ設定ファイルの読み込み使用するカメラのカメラ設定ファイルを指定します 本チュートリアルでは XC-HR50,XC-HR57 用カメラ設定ファイルを指定しています (3) カメラから入力される画像サイズと 画像メモリのサイズを一致させる画像入力を行う際に カメラから入力される画像サイズと 画像メモリのサイズが不一致だった場合 エラーとなってしまうため ChangeImageSize 関数を用いて 画像メモリサイズをカメラの画像サイズに合わせます 3. 画像入力ボタンを作り ボタンが押された瞬間にカメラから画像入力を行うようにします ビデオオープ ンボタンのときと同じ要領で ダイアログにボタンを追加し 名前を ビデオ入力 ID を IDC_BUTTON_VIDEO_INPUT とします ビデオオープン ボタンのイベントハンドラを追加し OnBnClickedButtonVideoInput() 内の処理を追加 します 画像入力を開始する関数はいくつか用意されており 用途に応じて使い分けていただく必要があります 関数名 機能 関連関数 GrabImageSync 1 フレーム取り込み ( 取込完了まで関数から抜けてきません ) AbortCapture(*1) GrabImageASync 1 フレーム取り込み ( 取込開始命令を画像入力ボードに行った後 即関数から抜けてきます ) GrabWait GrabStatus AbortCapture(*1) ContinuousGrab(*1) 連続取込 MemoryLock(*1) MemoryUnlock(*1) AbortCapture(*1) StopCapture(*1) NotifyCaptureNo(*1) QueryCaptureNo(*1) (*1)RICE-001(a/b) は未対応 -17-
本チュートリアルでは GrabImageSync 関数を用いて画像入力を行い 取り込みが行われた画像を画面に 表示します void CSample1Dlg::OnBnClickedButtonVideoInput() if( true == m_video.grabimagesync( &m_image )) // 画像入力 // 描画 m_view.setimage(&m_image); m_view.update(true); else FVCL::CFvString err_msg; err_msg.format( _T("GrabImageSync Error : code=%d"), m_video.geterrorcode() ); MessageBox( err_msg ); 4. プログラムを保存し 実行してみましょう ビデオオープン後に ビデオ入力ボタンを押すと画像入力が行われ 画像が表示されれば成功です -18-
8. オーバーレイ表示 1. オーバーレイに対して図形や文字を表示することができます 処理範囲や処理結果を画面上に表示させて視覚的に判りやすくさせることができますソリューションエクスプローラより Sample1Dlg.h を開き コードの上の方に WIL ヘッダファイルのインクルード宣言を行います #pragma once #include "FVCLbasic.h" // 画像処理クラスヘッダ #include "EVCbasic.h" // GUI ライブラリヘッダ 2.Sample1Dlg.h の下の方に 画像メモリ管理クラス 画像ビュークラス オーバーレイクラスの変数を宣言します afx_msg HCURSOR OnQueryDragIcon(); DECLARE_MESSAGE_MAP() FVCL::CFvImage m_image; // 画像メモリ管理クラス CEvView m_view; // 画像ビュークラス FVCL::CFvOverlay* m_overlay; // オーバーレイクラス 3.Picture Control 上に 画像ビューを作成し オーバーレイを生成します BOOL CSample1Dlg::OnInitDialog() //~~~~~~ 中略 ~~~~~~~ // TODO: 初期化をここに追加します FVCL::InitVisionLibrary(); // WIL 初期化 FVCL::EVCbasic::DLLChainResource( NULL ); // EVC リソースの接続 CRect rect; // 四角形データ 3. m_dummy.getwindowrect( &rect ); // ピクチャーコントロールの範囲を取得 ScreenToClient( &rect ); //rect をクライアント座標 ( ダイアログ上の座標 ) に変換 m_view.create( IDC_STATIC_IMAGE_VIEW, rect, this ); // 画像ビューの生成 m_overlay = m_view.m_display.createoverlay(); // オーバーレイの生成 m_view.setfocusoption(fvcl::focusoption::ldown); // ビュー上での左クリック有効 -19-
画像ビュー オーバーレイ : 指定した画像を表示する機能です 画像のスクロール ボタンクリック オーバーレイ 表示機能などを持ちます : 線や文字などの図形を 画像に重ねて表示するための透明のレイヤーです 画像の表示や 図形の表示はオーバーレイ上に書き込みますので オーバーレイは必ず生成する必要があります ここで m_overlay = m_view.m_display.createoverlay() とありますが これは CEvView クラスが内包する FVCL::CFvDisplay クラス内の CreateOverlay メソッドを呼び出す というコードになります CFvDisplay クラスにスクロールバーやオーバレイ描画機能を付加し 使い易くしたのが CEvView となります FVCL::CFvDisplay の操作は CEvView のメンバ変数 m_display から操作します CEvView FVCL::CFvDisplay m_view.setfocusoption(fvcl::focusoption::ldown) は行わなくても動作上問題ありません 1. 今までと同じ要領で ダイアログにボタンを追加し 名前を 描画 ID を IDC_BUTTON_DRAW とします 2. 描画したい図形を宣言します 今回は FAST マークの周囲に矩形をその中心に十字線を表示させます void CDrawLineDlg::OnBnClickedDraw () FVCL::CFvGdiRectangle* GdiRect; // オーバーレイ表示用直線オブジェクト FVCL::CFvGdiLineSegment* GdiLineSeg_hrz; FVCL::CFvGdiLineSegment* GdiLineSeg_vrt; FVCL::CFvRectangle Rectangle; // 矩形 FVCL::CFvLineSegment LineSeg_hrz; // 横線 FVCL::CFvLineSegment LineSeg_vrt; // 縦線 -20-
// 描画線座標を設定 Rectangle.st.x = 100; Rectangle.st.y = 100; Rectangle.ed.x = 350; Rectangle.ed.y = 350; LineSeg_hrz.st.x = (Rectangle.ed.x + Rectangle.st.x)/2-10; LineSeg_hrz.st.y = (Rectangle.ed.y + Rectangle.st.y)/2; LineSeg_hrz.ed.x = (Rectangle.ed.x + Rectangle.st.x)/2+10; LineSeg_hrz.ed.y = (Rectangle.ed.y + Rectangle.st.y)/2; LineSeg_vrt.st.x = (Rectangle.ed.x + Rectangle.st.x)/2; LineSeg_vrt.st.y = (Rectangle.ed.y + Rectangle.st.y)/2-10; LineSeg_vrt.ed.x = (Rectangle.ed.x + Rectangle.st.x)/2; LineSeg_vrt.ed.y = (Rectangle.ed.y + Rectangle.st.y)/2+10; // オーバーレイへの図形新規作成 GdiRect = static_cast<fvcl::cfvgdirectangle*>(m_overlay->drawfigure(rectangle)) GdiLineSeg_hrz = static_cast<fvcl::cfvgdilinesegment*>(m_overlay->drawfigure(lineseg_hrz)); GdiLineSeg_vrt = static_cast<fvcl::cfvgdilinesegment*>(m_overlay->drawfigure(lineseg_vrt)); if( GdiLineSeg_hrz!= NULL && GdiLineSeg_vrt!= NULL) FVCL::CFvGdiPen pen; pen.setcol or(rgb(255,0,0)); pen.setwidth(2); // 線色の設定 // 線幅の設定 GdiLineSeg_hrz->SetPen(pen); // ペン設定の反映 GdiLineSeg_vrt->SetPen(pen); pen.setcolor(rgb(0,0,255)); GdiRect->SetPen(pen); m_view.redraw(); // 線色の設定 // 描画更新 -21-
3. 描画をクリックして 矩形と十字が表示されれば成功です -22-
WIL チュートリアル (FVCL) Vol.2 2008 年 10 月第 2 版第 1 刷発行 発行所 株式会社ファースト 本社 242-0001 神奈川県大和市下鶴間 2791-5 ユーザ サポート FAX 046-272-8692 TEL 046-272-8691 E-mail : support@fast-corp.co.jp
B-001989 再生紙を使用しています