画像処理ソリューション
これを見れば画像処理の入門から基礎〜応用まで全てがわかるのを目指して!
   
プロフィール

ニックネーム:Akira
東京都の町田事業所に勤務
画像処理ソフトの開発を行っています。リンクフリーです!
詳細プロフィールは こちら
お問い合わせは、こちら↓

【補助HP】
画像処理ソリューションWeb版 【Newブログ】
イメージングソリューション

翻訳(Translate)

ブログ内検索


カテゴリ

最近のコメント

カレンダー

04 | 2012/05 | 06
S M T W T F S
- - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31 - -

趣味のブログ

iPhone萬歳!
iPhoneの情報いろいろ。
ブログ学習帳
ブログ、SEO、アフィリエイト情報など(まだまだこれから)
俺流クラフト日記
ハンドメイド作品の記録(現在、放置中)

- PR -



最近の記事
(05/08)  2012年4月人気記事Top5
(04/06)  ユニークアクセス100万達成!
(03/19)  2012年2月人気記事Top5
(02/16)  2012年1月人気記事Top5
(01/16)  2011年12月人気記事Top5
(06/13)  引越し状況報告(6月)
(03/21)  ブログを引っ越します。
(02/19)  【C#】マウスホイールで画像の拡大縮小
(02/19)  【C#】マウスホイールイベントの追加方法
(02/11)  【.NET】Graphicsオブジェクトのアフィン変換(グローバル変換)
(02/07)  アフィン変換
(01/29)  画像処理ソリューションWeb版を公開しました。
(01/07)  アメトーク(2011.01.07)の家電芸人スペシャルで紹介されていた製品
(12/20)  【OpenCV2.2】Windows7(64bit)でUSBカメラが動作せず
(12/19)  【C++/CLI】矢印の大きさ変更、任意形状の指定方法
(12/13)  Windowsドライバの削除方法
(12/12)  【OpenCV2.2】新規プロジェクトの作成方法
(12/11)  OpenCV2.2の入手、ダウンロード、インストール、環境設定
(12/11)  国際画像機器展2010に出展しました。
(12/06)  【OpenCV2.2】ライブラリ構成(*.lib,*.hなど)
(12/06)  OpenCV2.2が公開されました。
(11/29)  Kinectの測定例
(11/27)  C#とOpenCVの融合プログラミング
(11/23)  【展示会情報】国際画像機器展2010に出展します。
(11/22)  Kinectサンプルプログラムの実行
(11/22)  Kinectドライバの入手、設定方法
(11/22)  Kinect購入
(11/20)  【OpenCV】IplImageの輝度値を参照、設定する
(11/19)  【C++/CLI】大文字/小文字、全角/半角、ひらがな/カタカナを区別せず比較する
(11/06)  パノラマ写真作成ソフト『Image Composite Editor』

【OpenCV】C++/CLIによるサンプルプログラム

 

.NETを使ったOpenCVのサンプルプログラムを探すと、OpenCVDotNetやC#用のSharperCVというようなラッパライブラリを使った解説が多いのですが、ここではそれらを使わず、C++/CLIのみでOpenCVのサンプルプログラムを作成してみました。


OpenCV2.0用のサンプルプログラムは
  【OpenCV2.0】C++/CLIによるサンプルプログラム
のページを参照願います。
以下記事はOpenCV1.0の場合です。


で、作成したプログラムはこんな感じ↓
C++/CLIによるOpenCVのサンプルプログラム

機能としては
 ■二値化
 ■平滑化
 ■ガウシアン
 ■膨張
 ■収縮
 ■輝度値の表示
 ■処理時間の表示


ぐらいの簡単なものです。
処理できる画像は24bitのカラー画像のみです。
モノクロ画像の場合、IplImageからBitmapへ変換している部分と、輝度値を拾ってきている部分が対応できていません。

で、サンプルプログラムは
こちら(右ボタン→対象をファイルに保存)よりダウンロードできます。
Visual C++ 2005 Express Editionで作成しています。 )
ただし、プログラムを実行する前にOpenCVのインストールなど、OpenCVが動作する環境設定が必要です。これらについては下記ページを参照下さい。
◆OpenCVの入手ダウンロード、インストール、環境設定
◆開発環境(VisualStudio)の設定

注!!!
OpenCVのVer.1.1prea1版をインストールすると、ファイルを開くとき、
 -----------------------------------------------------------------
'System.Threading.ThreadStateException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました。

追加情報: OLE が呼び出される前に、現在のスレッドが Single Thread Apartment (STA) モードに設定されていなければなりません。Main 関数に STAThreadAttribute が設定されていることを確認してください。 この例外はデバッガがプロセスにアタッチされている場合にのみ発生します。
 -----------------------------------------------------------------
というメッセージが出て、ファイルを開く事ができません。
その場合は、現状ではVer1.0版のOpenCVをインストールして下さい。


以下、簡単なソースの解説です。

 画像ファイルの読込
ファイルメニューのファイル→開くでファイルを開くダイアログボックスを使って、画像ファイルを選択し、cvLoadImage関数で画像の読込を行っています。

 private: System::Void mnuFileOpen_Click(System::Object^  sender, System::EventArgs^  e) {
     //ファイルメニュー⇒開く

     ///////////////////////////////////
     //  ビットマップファイルの取得
     //  
     //ファイルを開くダイアログの作成

     OpenFileDialog^ dlg = gcnew OpenFileDialog;
     //ファイルフィルタ
     dlg->Filter = "画像ファイル(*.bmp,*.jpg,*.png,*.tif,jp2)|*.bmp;*.jpg;*.png;*.tif;*.jp2";
     //ダイアログの表示
     if (dlg->ShowDialog() == System::Windows::Forms::DialogResult::Cancel) return;
     //System::String^型のファイル名
     System::String^ strFilename = dlg->FileName;

     ///////////////////////////////////
     // src_img の解放
     //
     if (src_img != NULL){
      IplImage *temp_img = src_img;
      cvReleaseImage(&temp_img);
      src_img = NULL;
     }   
    
     ///////////////////////////////////
     //  IplImageの確保
     //
     //System::String^からchar*へ変換
     char* pStr = (char*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(strFilename).ToPointer();
     //アンマネージ関数へchar*を渡す
     src_img = cvLoadImage(pStr, CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
     //メモリの解放
     System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr(pStr));

     ///////////////////////////////////
     //IplImageをピクチャボックスへ描画
     //
     DrawCvImage(src_img);

    }

ここでのポイントはStringToHGlobalAnsiメソッドを使ってString^からchar*に変換している部分でしょうか。


 IplImageのPictureBoxへの描画

OpenCVの画像データのポインタ(imageData)をBitmapへ渡し、Bitmapを確保して、DrawImageを使ってピクチャボックスへ描画しています。

 private: System::Void DrawCvImage(IplImage *CvImage) {
    //IplImageをピクチャボックスへ描画
   
    ///////////////////////////////////
    //  Graphicsの確保
    //

    if ((pictureBox1->Image == nullptr)
     || (pictureBox1->Width != CvImage->width)
     || (pictureBox1->Height != CvImage->height)){
     //ピクチャボックスをビットマップ画像サイズに合わせる
     pictureBox1->Width = CvImage->width;
     pictureBox1->Height = CvImage->height;
     //PictureBoxと同じ大きさのBitmapクラスを作成する。
     Bitmap^ bmpPicBox = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height);
     //空のBitmapをPictureBoxのImageに指定する。
     pictureBox1->Image = bmpPicBox;
    }

    //Graphicsクラスの作成(空のピクチャボックスからGraphicsを作成する)
    Graphics^g = Graphics::FromImage(pictureBox1->Image);
   
    ///////////////////////////////////
    //  IplImageからBitmapの確保
    //     
    //IplImageの画像データのポインタ(imageData)をBitmapへ渡し、Bitmapを作成

    Bitmap^ bmp = gcnew Bitmap(CvImage->width, CvImage->height, CvImage->widthStep,
     System::Drawing::Imaging::PixelFormat::Format24bppRgb, IntPtr(CvImage->imageData));

   
    ///////////////////////////////////
    //  画像の描画
    //
    //ピクチャボックスのImageへ

    g->DrawImage(bmp, 0, 0, CvImage->width, CvImage->height); 
    pictureBox1->Refresh();
   
    delete g;
   }



 OpenCVの処理

サンプルプログラムのメニューのOpenCV以下のフィルタ処理のイベント処理は、それぞれのイベントごとに処理を書くのが面倒だったので、全て同じイベント処理を通すようにしてみました。

private: System::Void mnuOpenCV_Click(System::Object^  sender, System::EventArgs^  e) {
    //OpenCVメニュー

    //処理後の画像データ
    IplImage* dst_img;
    //描画時間計測用
    Diagnostics::Stopwatch^ sw = gcnew Diagnostics::Stopwatch;  
    //メニューアイテム(どのメニューがクリックされたのか?)
    ToolStripMenuItem^ mnu = (ToolStripMenuItem^)sender;

    //画像データが無い場合
    if (src_img == NULL) return;

    //処理時間計測開始
    sw->Start();

    //src_imgと同じサイズのIplImageの確保
    dst_img = cvCreateImage(cvSize(src_img->width, src_img->height),
         src_img->depth, src_img->nChannels);

    //クリックされたメニューごとにOpenCVの処理
    if (mnu->Name == "mnuThreshold"){
     //二値化(しきい値127)
     cvThreshold(src_img, dst_img, 127, 255, CV_THRESH_BINARY);

    }else if (mnu->Name == "mnuSmooth3_3"){
     //平滑化(3×3)
     cvSmooth(src_img, dst_img, CV_BLUR, 3, 3);

    }else if (mnu->Name == "mnuGaussian21_21"){
     //ガウシアン(21×21)
     cvSmooth(src_img, dst_img, CV_GAUSSIAN , 21, 21);

    }else if (mnu->Name == "mnuDilate"){
     //膨張
     cvDilate(src_img, dst_img, NULL , 1);

    }else if (mnu->Name == "mnuErode"){
     //収縮
     cvErode(src_img, dst_img, NULL , 1);

    }else{
     return;
    }

    //処理後の画像を元の画像データにコピーする。
    cvCopy(dst_img, src_img);

    //解放
    cvReleaseImage(&dst_img);

    //処理時間計測停止
    sw->Stop();

    //処理時間の表示
    toolStripStatusLabel2->Text =
     mnu->Text + "処理時間 = " + sw->ElapsedMilliseconds.ToString() + "msec";

    //画像の描画
    DrawCvImage(src_img);

   }


 輝度値の取得

画像の輝度値はピクチャボックスのMouseMoveイベントでマウスポインタの位置の輝度値をステータスバーに表示するようにしました。
OpenCVにおける輝度値はIplImageのimageDataのポインタを参照することで拾うことができるのですが、imageDataのポインタはなぜか符号付char型になっているので、符合なしのucharで受けています。
って、
opencv.jpの内容をそのままマネしただけですけど...

private: System::Void pictureBox1_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
   
//画像の輝度値の表示

    //画像データが無い場合
    if (src_img == NULL) return;

    //輝度値の取得
    uchar p[3];
    p[0] = src_img->imageData[src_img->widthStep * e->Y + e->X * 3];        // B
    p[1] = src_img->imageData[src_img->widthStep * e->Y + e->X * 3 + 1];    // G
    p[2] = src_img->imageData[src_img->widthStep * e->Y + e->X * 3 + 2];    // R

    //輝度値表示
    //輝度値(X座標, Y座標) = (R, G, B)
    toolStripStatusLabel1->Text =
     "輝度値(" + e->X.ToString() + "," + e->Y.ToString() + ") = (" +
     p[2].ToString() + "," + p[1].ToString() + "," + p[0].ToString() + ")" ;
   }



Loading...

この記事に対するコメント

とても魅力的な記事でした!!
また遊びに来ます!!
ありがとうございます。。
【2012/02/01 15:20】 URL | 履歴書のサンプル #- [ 編集]


この記事に対するコメントの投稿














管理者にだけ表示を許可する


この記事に対するトラックバック
トラックバックURL
→http://imagingsolution.blog107.fc2.com/tb.php/91-c8ad5dcd
この記事にトラックバックする(FC2ブログユーザー)

現在の閲覧者数: / 合計