OpenCVをWin32ベースで利用するの2回目です。前回はベースになるダイアログベースのアプリケーションを作成しました。今回はこのアプリケーションにOpenCVを組み込んで実際に動かしてみます。
(※2014.11.16追記)
以下でOpenCVを組み込む前の画面上の入出力用のコントロールを追加したバージョンを作成しました。
OpenCVをWin32ベースで利用する(その5)GUIコントロールの追加
今回のソース一式は以下からダウンロード出来ます。(※必要な場合は用途に限らずご利用頂いて問題ありませんが、一切無保証です。弊社は一切の責任を負いません。)
今回のソース一式(※OpenCVを取り込んでいるため72M程度のサイズになっています。)
まずOpenCVの組み込みはここではNuGetを使います。以下のページに書きました。より詳細はこちらを参照して下さい。
NuGetでOpenCVを導入する
前回のプロジェクトの状態から、ツールメニュー → NuGetパッケージマネージャー → ソリューションのNuGetパッケージの管理 から管理画面を起動します。
検索エリアからOpenCVで検索をして見つかったOpenCVを選択してインストールをします。これでOpenCVの組み込みは完了です。現状では、OpenCV 2.4.8が導入出来ます。
次にソースファイルの上に以下のインクルードファイルを追加します。C言語、C++の両方を使えるようにインクルードします。
#include <opencv\cv.h> #include <opencv\highgui.h> #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp>
これでビルドを実行するとエラーになります。これについては以下で書きました。
Visual C++ CRT(Cランタイムライブラリ)のビルドエラー
ここでは対処法だけ書きます。stdafx.hの#pragma onceの下に以下の行を挿入します。これでエラーは出なくなります。(文字コードのワーニングは気にしないことにします。)以上でOpenCVの組み込みは完了です。
#define _CRT_SECURE_NO_WARNINGS 1
ここからですが、以下のような処理の流れを想定してプログラムを作成しました。
1. 読み込みボタンで画像を読み込んでメインダイアログに表示する。(読み込み方は必ず3チャンネルカラー画像)
↓
2. ボタンを押した際に何かしらの画像処理を行う。(ボタンは5個あり各ボタンクリック時の関数を用意)
↓
3. 画像処理の結果を表示する(結果の表示はOpenCVのGUIを利用)
↓
4. 画像処理の結果を保存用の変数にセットする(必要な場合のみ)
↓
5. 画像処理の結果を保存する(必要な場合のみ)
ここで大事なのは、2.と3.です。ここでやりたいOpenCVの処理を書きます。実際に例として簡単ですが読み込んだ画像をグレースケールに変換して表示するというプログラムを作りました。(※ページ先頭のソース一式です。)
読み込みボタンから画像を読み込みます。普通のファイルダイアログです。
読み込んだ画像が表示されます。画像が大きい場合は縮小して表示します。
処理1ボタンでグレースケール画像を作成して表示します。(※元々が曇りの天候の時の画像のようであまり変わっていないようですが。)
保存ボタンでグレースケールの画像が保存出来ます。普通のファイルダイアログです。
以上のような流れです。OpenCVの処理はグレースケール画像の作成の処理です。その部分のソースコードについて書きます。ソースは以下です。処理1ボタンがクリックされると実行されます。
/*------------------------------------------------ 処理1 -------------------------------------------------*/ void func1(HWND hWnd) { if (imgMatRead.rows == 0){ MessageBox(hWnd, "画像が無効です", "エラー", MB_OK); return; } //読み込んだ画像をグレースケースに変換して表示する cv::Mat grImg; cv::cvtColor(imgMatRead, grImg, CV_BGR2GRAY); cv::imshow("gray", grImg); //保存用の画像に設定する imgMatWrite = grImg; }
関数内に定義のない変数についてです。以下の定義がソースファイルの上部にあります。
//入力画像、出力画像 cv::Mat imgMatRead; //読み込み用(読み込んだ画像はここに保持される) cv::Mat imgMatWrite; //書き込み用(保存する際はここに対象画像を設定すること)
imgMatReadがファイルダイアログから読み込んだ画像が保持される変数です。無条件に3チャンネルカラー画像で読み込んでいるので必要な場合は変換して使います。(今回ではグレースケールに変換しています。)imgMatWriteが保存用の画像を設定する変数です。読み込み、保存は別の処理があるので、ボタンがクリックされた時の処理はOpenCVの処理に集中すればいいです。結果の表示はWin32APIを使わなくてもOpenCVのGUIでいいかなと思いました。
それから、ここではC++を使っていますが、C言語で処理する場合は、cv::MatとIplImageを相互変換すればいいです。
imgMatReadをIplImageに変換する場合は、以下のように代入で変換出来ます。
IplImage img = imgMatRead;
あとは、OpenCVのC言語の関数でimgを使って画像処理を行えばいいです。
IplImageをimgMatWriteに変換するには以下のように変換出来ます。
IplImage imgの場合です。
imgMatWrite = cv::cvarrToMat(&img);
IplImage* imgの場合です。
imgMatWrite = cv::cvarrToMat(img);
こうすれば読み込み、保存はそのまま使えます。
以上のようにボタンをクリックした時の処理に集中すればいいので分かるやすくプログラムが書けるかなと思って作ってみましたがいかかでしょうか。
あと、OpenCVの処理としては画像が大きい場合にピクチャーコントロールに入るように縮小する際に、cv::resize()を使っています。補間手法はデフォルトのバイリニア補間を指定しています。他の補間方法もcv::resize()の最後の引数で指定出来ます。
ここでの補間という意味は画像の拡大、縮小の際のピクセル間のデータの再計算のことです。画像を拡大、縮小するとピクセルの数が当然変化するので拡大、縮小後の各ピクセルのデータを元画像からどう計算して処理するかということです。(※画像処理関連としては基本かもしれないですが、その補間手法が何種類もあって、このOpenCVのresize()で指定出来るというのが何かすごいなと思ったので書きました。)
その他の内部的な処理は、Win32APIになりますのでここでは取り上げないことにします。必要な場合はソースを読んでみて下さいということでご了承頂ければと思います。ソースはページ始めのリンクからダウンロード出来ます。
今回はここまでです。次回はカメラからの画像を入力にして処理をするプログラムを書きます。
関連書籍
(※APIで学ぶWindows徹底理解は中古でしか手に入らないようですが私も持っています。)
(※OpenCV 2 プログラミングブックは私も持っています。)
(※ここからはKindle版で英語ですが最新の情報もあるようです。また価格的にはいいかもしれないです。)