りさーちゃーのひよこ
技術のこととか
2014年6月16日月曜日
C++/CLI フォームアプリとOpenCVの連携(cv::Mat)
#背景 先日OpenGLの画像をフォームに貼り付けました。<br /> →<a href="https://www.blogger.com/null"></a><a href="http://ameblo.jp/morimoridiary/entry-11878063364.html" target="_blank" title="">C++/CLI フォームアプリとOpenGLの連携(フォームへのレンダリングとGUI操作)</a><br /> それはよいのですが、更に以下のようなことをしたくなった。<br /> <br /> 1. OpenGL画像をOpenCV画像(cv::Mat)に変換<br /> 2. 画像処理<br /> 3. 結果画像(cv::Mat)をフォームのピクチャボックスに表示<br /> <br /> 2は知ったこっちゃ無いですね。cv::Matさえ扱えればよいのです。<br /> 1と3だけメモります。<br /> #手順 ##1. OpenGL画像をOpenCV画像(cv::Mat)に変換 超簡単です。<br /> <pre class="brush: cpp;"> // この前の段階でOpenGLレンダリングコンテキストをカレントにしておく cv::Mat cvImg = cv::Mat::zeros(winHeight, winWidth, CV_8UC3); glReadPixels(0, 0, winWidth, winHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, cvImg.data); cv::flip(cvImg , cvImg , 0); </pre> ##3. 結果画像(cv::Mat)をフォームのピクチャボックスに表示 結構はまりました。コードは簡単ですが。<br /> めぐりめぐって結局次のサイトを組み合わせて実現しました。<br /> <a href="https://www.blogger.com/null"></a><a href="http://imagingsolution.blog107.fc2.com/blog-entry-91.html" target="_blank" title="">画像処理ソリューション-【OpenCV】C++/CLIによるサンプルプログラム</a><br /> <a href="https://www.blogger.com/null"></a><a href="http://imagingsolution.blog107.fc2.com/blog-entry-108.html" target="_blank" title="">画像処理ソリューション-【C++/CLI】Graphicsオブジェクトの作成</a><br /> <a href="https://www.blogger.com/null"></a><a href="http://www.codeproject.com/Tips/741107/How-to-Display-Image-In-Picturebox-in-VCplusplus-f" target="_blank" title="">Code Project-How to Display Image In Picturebox in VC++ from Iplimage and Mat</a><br /> <br /> 2番目のサイトによると、<br /> <div> <i>1. Imageオブジェクトから作成(速いからオススメ!)</i></div> <div> <i>2. CreateGraphicsメソッドを使う方法(遅いし再描画必要からオススメしない!)</i><br /> とあるので、両方試してみた。<br /> <br /> どちらにしろ流れはこんな感じ。<br /> ・ピクチャボックスに対するGraphics オブジェクト作成する。<br /> ・Bitmat オブジェクトのバッファにOpenCV のバッファを渡す。<br /> ・Graphics オブジェクトでBitmat のバッファをピクチャボックスに描画する。<br /> <br /> 以下サンプルです。<br /> <br /> <i>1. Imageオブジェクトから作成</i><br /> ・10回計測: 平均 = 5838[us], 標準偏差 = 102[us]<br /> <pre class="brush: cpp;"> // どこかから cv::Mat cvImg がやってきたとする。 Bitmap^ bmp; IntPtr ip(cvImg.ptr()); // OpenCVの画像バッファをintポインタに変換 if ((pictureBox1->Image == nullptr) || (pictureBox1->Width != cvImg.cols) || (pictureBox1->Height != cvImg.rows)){ //ピクチャボックスをビットマップ画像サイズに合わせる pictureBox1->Width = cvImg.cols; pictureBox1->Height = cvImg.rows; //PictureBoxと同じ大きさのBitmapクラスを作成する。 Bitmap^ bmpPicBox = gcnew Bitmap(pictureBox1->Width, pictureBox1->Height); //空のBitmapをPictureBoxのImageに指定する。 pictureBox1->Image = bmpPicBox; } Graphics^g = Graphics::FromImage(pictureBox1->Image); // グラフィックオブジェクト作成 bmp = gcnew Bitmap(cvImg.cols, cvImg.rows, cvImg.step, System::Drawing::Imaging::PixelFormat::Format24bppRgb, ip); // bmp->Save("test.jpg"); // これはデバッグ用。バッファがコピーされているか確認。 g->DrawImage(bmp, 0, 0, cvImg.cols, cvImg.rows); // this->pictureBox3->Image = bmp; pictureBox1->Refresh(); // これは必要 delete g; delete bmp; </pre> <i>2. CreateGraphicsメソッドを使う方法</i></div> ・10回計測: 平均 = 3563[us], 標準偏差 = 239[us] ← 勝利<br /> <pre class="brush: cpp;"> // どこかから cv::Mat cvImg がやってきたとする。 Bitmap^ bmp; IntPtr ip(cvImg.ptr()); // OpenCVの画像バッファをintポインタに変換 Graphics^g = pictureBox1->CreateGraphics(); // グラフィックオブジェクト作成 bmp = gcnew Bitmap(cvImg.cols, cvImg.rows, cvImg.step,System::Drawing::Imaging::PixelFormat::Format24bppRgb, ip); // bmp->Save("test.jpg"); // これはデバッグ用。バッファがコピーされているか確認。 g->DrawImage(bmp, 0, 0, cvImg.cols, cvImg.rows); // pictureBox3->Refresh(); // これは除外。動画だと画面がちらつく。 delete g; delete bmp; </pre> <br /> え?2の方が速いですよ。再描画いらないし。<br /> しかも1は再描画がいらないと書いてあるけど、Refresh()関数を呼ばないとうまく描画されません。多分説明が反対なのかもしれませんね。<br /> <br /> <br />
0 件のコメント:
コメントを投稿
次の投稿
前の投稿
ホーム
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿