株式会社インデペンデンスシステムズ横浜

システム開発エンジニアの西田五郎が運営しております。Raspberry Pi や Arduino その他新規開発案件のご依頼をお待ちしております。

OpenCV

OpenCVをWin32ベースで利用する(その3)カメラ入力からの画像処理

投稿日:2014年11月1日 更新日:

OpenCVをWin32ベースで利用するの3回目です。前回は画像ファイルを入力にしてその画像に対してOpenCVで画像処理を行うというプログラムでした。今回は大きくは変わらないですが、カメラからの画像を入力にして画像処理を行います。今回のプログラムで重要になってくるのはWin32APIでのスレッド処理です。しかしながら、スレッド処理はOpenCVとは関係ないのでポイントだけということで書いていきたいと思います。

(※2017年2月8日 いまさらですが、ソースが中途半端で動作しないというご指摘を頂きましたので修正しました。読み込みボタンでカメラの起動処理を実行して、キャプチャやグレースケールスケール変換が出来ると思います。何かありましたら、フィードバックページ等をご利用下さい。)

今回のソース一式は以下からダウンロード出来ます。(※必要な場合は用途に限らずご利用頂いて問題ありませんが、一切無保証です。弊社は一切の責任を負いません。)
今回のソース一式
(※OpenCVを取り込んでいるため58M程度のサイズになっています。)

それではまずは今回のプログラムの動作からです。以下のような流れを想定しました。当然ですがカメラが接続(または内蔵)されていて利用出来ることが前提です。前回から変わっているのは入力がカメラになったということです。

1. 読み込みボタンでカメラからの画像をメインダイアログに表示する。(読み込み方は必ず3チャンネルカラー画像)

2. ボタンを押した際に何かしらの画像処理を行う。(ボタンは5個あり各ボタンクリック時の関数を用意)

3. 画像処理の結果を表示する(結果の表示はOpenCVのGUIを利用)

4. 画像処理の結果を保存用の変数にセットする(必要な場合のみ)

5. 画像処理の結果を保存する(必要な場合のみ)

ここで大事なのは前回と同様に、2.と3.です。ここでやりたいOpenCVの処理を書きます。ここではまずはビデオ画像をキャプチャして表示するという処理と、キャプチャした画像をグレースケールに変換して表示するというプログラムを作りました。(※ページ先頭のソース一式です。)

以下のような動きをします。
起動時
0001

読み込みボタンでキャプチャ開始
0002

キャプチャーボタンでキャプチャーして別画面表示
0005

グレースケールボタンでキャプチャーしてグレースケールに変換後に別画面で表示
0008

すいません、夜の時間帯に室内から窓の外を撮ったものであまり違いがはっきりしないですがご了承ください。
あと、保存処理は前回と同様です。保存用の画像変数に設定した画像が保存出来ます。

次に今回のプログラムの要点のスレッド処理についてです。(理解されている方は当然理解されていると思いますが)スレッドとはプログラム内(Windowsの場合はプロセスという表現が出来ると思いますが)で別々の独立した処理の流れのことです。C言語の場合は独立した処理というのは関数単位です。最新の様々なプログラミング言語仕様では非同期という処理が可能なので今回のような処理も非同期を使えば比較的に簡単に出来るかと思いますがやはりスレッドは重要なプログラミングの要素です。

しかしながらですが、最初に書いたように、スレッド処理は、OpenCVとは関係ないのでポイントだけ書きます。以下がポイントになるかと思います。

・カメラ入力の処理はリアルタイムに動いているのでこれを別スレッドとして実行する。
(メインダイアログでの処理とは別にしてメインダイアログは常に処理を受け付けている状態とする。)

・Win32APIのスレッド起動は、_beginthreadex()を使う。
(最も安全に利用できる関数(API)である。)

・カメラ入力の別スレッドではGUIを操作しない。
(C言語(Win32API)の場合は、おそらく問題なく動作する場合もあると思うが基本的には別スレッドからはGUIは操作しない。)

以下がスレッドの関数です。スレッドの形式は、ここではこういった決まった形式で実装するということにしておきます。OpenCVの処理としては、最初に見つかったビデオ入力(カメラと想定しています)をオープンして終了のフラグがセットされるまで入力用の画像に取り込んでWin32APIでメインダイアログに表示し続けています。

/*------------------------------------------------
 カメラキャプチャー
-------------------------------------------------*/
unsigned int __stdcall CameraCaptureThread(PVOID pv)  {

	cv::VideoCapture cap(0);
	if (!cap.isOpened()){
		return -1;
	}

	while (1){

		if (endFlag){
			break;
		}

		cap >> imgMatRead;

		img = imgMatRead;
		imgFromOpenCV = &img;

		//メモリを確保
		if (bmpData != NULL){
			HeapFree(GetProcessHeap(), 0, bmpData);
		}

		bmpData = (LPDWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, imgFromOpenCV->width * imgFromOpenCV->height * 4);

		//iplImageからDIBへ変換
		iplTobmp(imgFromOpenCV, bmpInfo, bmpData);

		//ここで描画
		StretchDIBits(hDC,
			0, 0, imgFromOpenCV->width, imgFromOpenCV->height,
			0, 0, imgFromOpenCV->width, imgFromOpenCV->height,
			bmpData, &bmpInfo, DIB_RGB_COLORS, SRCCOPY);
	}

	return 0;
}

このスレッドを起動する処理が以下です。該当部分のみです。

case ID_READ:
	//カメラキャプチャー開始
	if (threadHandle != NULL)
	{
		break;
	}
		
	//スレッド起動
	threadHandle = (HANDLE)_beginthreadex(
		NULL,          
		0,              
		CameraCaptureThread,  
		NULL,
		0,               
		(unsigned int*)&dwThread);

	if (!threadHandle) {
		MessageBox(hDlg, "スレッド起動エラー", "debug", MB_OK);
	}

	break;

プログラム全体はページ先頭のリンクからダウンロード出来ます。全体が必要な場合はお手数ですがダウンロードをして下さい。

今回はここまでです。次回はカメラ入力は同じですがリアルタイムに画像処理を行って画像処理を動画として保存出来るようなプログラムに変更してみます。

関連書籍
(※APIで学ぶWindows徹底理解は中古でしか手に入らないようですが私も持っています。)

(※OpenCV 2 プログラミングブックは私も持っています。)

(※ここからはKindle版で英語ですが最新の情報もあるようです。また価格的にはいいかもしれないです。)


AdSense

AdSense

-OpenCV

執筆者:

関連記事

NuGetでOpenCVを導入する

Visual Studio Express 2013 for Windows Desktopの開発環境でNuGetを使ってOpenCVを導入してみました。その方法についてです。 まずは、OpenCV( …

OpenCV2 cv::Matクラスの基礎

OpenCV2のcv::Matクラスの基礎についてです。OpenCV 2.0からはC++のインターフェースが追加されました。cv::MatクラスはそのC++インターフェースで画像を扱うクラスです。まず …

OpenCVで背景差分とテスト的な動体検知

OpenCVで背景差分を試してみました。あとテスト的な動体検知も試してみました。背景差分とはあらかじめ取得した画像を背景画像として、観測時点の画像とその背景画像との差分を取ることによりその差分を前景領 …

OpenCVをWin32ベースで利用する(その5)GUIコントロールの追加

OpenCVをWin32ベースで利用するの5回目です。前回の4回目で一度終了したのですが、画面上の入出力用のコントロール、つまり、ラベル、エディット、コンボ等のコントロールがなかったので追加してみまし …

OpenCVをWin32ベースで利用する(その4)カメラ入力からの動画処理

OpenCVをWin32ベースで利用するの4回目です。前回はカメラ入力からの画像処理(静止画)を扱いましたが、今回は動画を処理します。動画と言っても特に変わることはなくキャプチャしたフレームごとに処理 …