前回、OpenCVを使って画像の回転や二値化などを行って動作確認をしました。
今回はMFCでダイアログベースのアプリケーションを作成し、ピクチャーコントロールにOpenCVで読み込んだ画像を表示させてみましょう。
簡単なサンプルプログラムとして、「ボタンを押下されたらOpenCVで画像を読み込み、ピクチャーコントロールのサイズに合わせてリサイズし描画」させてみましょう。
サンプルプログラムの作成
プロジェクトを作成しよう!
では、サンプルプログラム用のプロジェクトを作成していきましょう。
- Visual Studio 2017を起動し、[ファイル]-[新規作成]-[プロジェクト]をクリックします。
- 「新しいプロジェクト」ダイアログでは、「MFCアプリケーション」を選択し、プロジェクト名とソリューション名を入力します。
今回は前回のソリューションに追加する形で作成しています。
- 「MFCアプリケーションウィザード」のようこそ画面ではそのまま[次へ]ボタンをクリックします。
- 「アプリケーションの種類」は[ダイアログベース]を選択、[Security Development Lifecycleチェック]のチェックを外します。
- 「ユーザーインターフェイス機能」は特に変更せずに、[次へ]ボタンをクリック。
- 「高度な機能」ではすべてのチェックをを外します。
- 「生成されたクラス」では特に変更せずに、[完了]ボタンをクリックします。
ダイアログの外観を設定しよう!
次に、
- 画像を読み込むためのButton
- 画像を表示するPicture Control
を配置します。
画像表示用のPicture Controlのプロパティは以下のように設定しておきます。

IDC_STATICからIDC_IMAGEに変更
・[Type]:
フレームから四角形に変更
次に、追加したボタンを右クリックし、[イベントハンドラーの追加]をクリック。
[イベントハンドラーウィザード]の内容は変更せずに、[追加して編集]ボタンをクリックします。
さて、これでコーディングを開始したいところですが、前回と同様に「追加のインクルードディレクトリ」と「追加のライブラリディレクトリ」を設定します。
追加の方法は前回の記事を参考にしてみてくださいネ。
コーディングしよう!
ではコードを入力していきます。
0 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 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <opencv2\core\core.hpp> #include <opencv2\imgproc\imgproc.hpp> #include <opencv2\highgui\highgui.hpp> #if defined _DEBUG #define CV_EXT "d.lib" #else #define CV_EXT ".lib" #endif #pragma comment(lib, "opencv_core2413" CV_EXT) #pragma comment(lib, "opencv_imgproc2413" CV_EXT) #pragma comment(lib, "opencv_highgui2413" CV_EXT) // ... void CMFCCollaborateDlg::OnBnClickedButton1() { CDC *dc = GetDlgItem(IDC_IMAGE)->GetDC(); HDC dstDC = dc->GetSafeHdc(); CRect rc; GetDlgItem(IDC_IMAGE)->GetClientRect(&rc); cv::Size size(rc.Width() & ~0x03, rc.Height() & ~0x03); cv::Mat img = cv::imread("lenna.tif"); cv::resize(img, img, size); cv::flip(img, img, 0); BITMAPINFO info = {}; info.bmiHeader.biBitCount = 24; info.bmiHeader.biWidth = size.width; info.bmiHeader.biHeight = size.height; info.bmiHeader.biPlanes = 1; info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); info.bmiHeader.biCompression = BI_RGB; StretchDIBits(dstDC, 0, 0, size.width, size.height, 0, 0, size.width, size.height, img.data, &info, DIB_RGB_COLORS, SRCCOPY); ReleaseDC(dc); } |
注意しなければならないのは、24行目の部分です。
0 |
cv::Size size(rc.Width() & ~0x03, rc.Height() & ~0x03); |
イメージのサイズはPicture Controlのサイズに合わせてリサイズしていますが(27行目)、24行目で設定したサイズが4の倍数になっていない場合、上手く表示できません。
そのため、幅と高さの下位2ビットを削り、必ず4の倍数になるように設定しています。
参考:Google 検索-[ウィンドウズDIB 4バイト境界]
また、33行目でBITMAPINFOHEADER::biHeightに正の値を設定しており、この画像はボトムアップDIBとなるため、28行目で画像を上下反転させています。
28行目をコメントアウトし、33行目のbiHeightに負数(-size.Height)を入力し、トップダウンDIBと指定しても同じ結果になります。
参考:トップダウン DIB とボトムアップ DIB | MSDN
28行目をコメントアウトし、33行目のbiHeightを変更しなければ上下反転された状態で描画されることも確認してみてくださいネ。
まとめ
これでOpenCVに画像処理を任せて、得られた結果をサンプルのようにPicture Controlに描画させることができました。
今回は単純にするためボタンが押されたら、特定の画像を読み込み表示するようなサンプルでしたが、実際には、
- ボタンが押されたらファイル選択ダイアログが表示される
- 画像のデータをImageクラスで保持する
- 表示した画像をマウスホイールで拡大・縮小する
などなどたくさんの実装が必要になると思います。
まだまだ改善の余地は多くありますが、ひとまず動くことが確認できたので改善もしやすいのではないでしょうか。