概要

OpenCVで2つのカメラを開きカメラで撮影した動画をMat型に2つ並べてコピーしウィンドウに表示するプログラムである。撮影された動画はtemp.wmvに保存される
動画の上部に日時が表示される。
Visual C++ を対象としておりOpenCVのインストールが必要である。
キャプチャーサイズは各カメラ320*240です。
プログラムを終了させるためにはいずれかのキーを押します。
以下は動作例です。ウィンドウの中の画像ははめ込み画像です。

テスト環境

コンパイラ

Visual C++ 2008 Express(32bit)/Standard(32/64bit) with OpenCV2.3.1
Visual C++ 2013 Express 32bit/64bit with OpenCV2.4.10

実行環境

Windows 7 32/64bit

OpenCVのインストール及び環境設定

プログラムソースの概要

#include の後の行からusing namespace cv;の手前までは、Visual C++のバージョン及びRelease/Debug 32bit/64bit 静的リンク/動的リンクに合わせてロードするLIBのファイル名を自動的に作成するために記述しています。
固定された環境であれば、簡素に記述可能です。
例えば Visual C++ 2013 32bit Release 動的リンクであれば、以下のように簡素に記述できます。
#pragma comment(lib, "c:/opencv2.4.10/opencv/build/vc12/x86/lib/opencv_core2410.lib")
#pragma comment(lib, "c:/opencv2.4.10/opencv/build/vc12/x86/lib/opencv_highgui2410.lib")
using namespace cv; により名前空間をcvにします。これを定義しない場合は、OpenCVの関数を使う場合には関数名の前にcv::を付加する必要があります。

_tWinMain

VideoCaptureのコンストラクタでそれぞれのカメラを開きます。引数はカメラ番号を示しています。
数字が指定できます。
カメラの選択には、DirectShowを使用してカメラ名をリストボックスに表示しカメラの選択結果を表示するを参考にしてプログラムを修正すれば、キャプチャー前にカメラ番号を選択させることも可能となります。
VideoCaptureのisOpend関数でカメラが開けない場合は、プログラムを終了させます。
解像度はset関数により320*240に設定しています。
2つのjpgファイルを横に並べた大きさのMat型baseを作成します。
baseに張り付ける領域を示すMat型 roi1とroi2を作成します
Rectで領域を指定していますが、張り付け後の領域であるのがミソです
VideoWriteのコンストラクタによりtest.wmvを開きます。
namedWindow関数によりウィンドウを開きます。
cap0 >> frame0,cap1 >> frame1によりカメラで撮影された画像をMat型変数のfram0,fram1へコピーします。
copyToによりbaseをroi1とroi2にコピーします。
time関数により世界標準時を取得しlocaltime_sで日本標準時に変換します。
sprintf_sにより日時を文字列に変換し、putTextによりimgに文字列を表示します。
imshow関数によりimgをウィンドウに表示します。
writer << baseによりbaseをファイルへ書き込みます。
waitkey(33)により33m秒待機しキー入力があればプログラムを終了させます。
キー入力がなければ、撮影を繰り返します。

ソースコード

//	OpenCVを使用して2つのカメラから動画をキャプチャーして横に並べて表示、保存するサンプル
//	動画の上部に日時を表示
//	
//	Open CV 2.3.1/2.4.10 サポート
//	例えばVisual C++ 2013でOpen CV 2.4.10でコンパイルする場合の設定は以下の通りとなる
//		VCのインクルードディレクトリに C:\opencv2.4.10\opencv\build\include; を付加
//		動的リンクで作成した場合は、サンプルの実行には環境変数PATHに以下のフォルダーを登録する必要がある。
//		win64	C:\opencv2.4.10\opencv\build\x64\vc12\bin
//		win32	C:\opencv2.4.10\opencv\build\x86\vc12\bin
//	動作確認
//		Visual C++ 2008 Standard Release 64bit 動的/静的	OpenCV 2.3.1
//		Visual C++ 2008 Standard Debug 64bit 動的/静的		OpenCV 2.3.1
//		Visual C++ 2008 Standard Release 32bit 動的/静的	OpenCV 2.3.1
//		Visual C++ 2008 Standard Debug 32bit 動的/静的		OpenCV 2.3.1
//		Visual C++ 2013 Express Debug 32bit 動的/静的		OpenCV 2.4.10
//		Visual C++ 2013 Express Release 32bit 動的/静的		OpenCV 2.4.10
//		Visual C++ 2013 Express Debug 64bit 動的/静的		OpenCV 2.4.10
//		Visual C++ 2013 Express Release 64bit 動的/静的		OpenCV 2.4.10

#include <windows.h>
#include <opencv2/opencv.hpp>
#include <stdio.h>
#include <tchar.h>
#include <time.h>

#ifdef _DLL	//	動的リンク
 #define CV_LINK_MODE "/lib/"
#else 	//	静的リンク
 #define CV_LINK_MODE "/staticlib/"
#endif

// バージョン取得
#define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)

#define CV_INST_SUB_DIR  "opencv" ## CVAUX_STR(CV_MAJOR_VERSION) ## "." CVAUX_STR(CV_MINOR_VERSION) ## "." CVAUX_STR(CV_SUBMINOR_VERSION)

#define CV_INST_DIR "c:/" ## CV_INST_SUB_DIR ## "/opencv/build"


//	32bit/64bit ランタイムのリンクモード等に応じてLIBファイルのフォルダー名(CV_LIB_DIR)を作成

#ifdef _WIN64
 #ifdef _DLL
  #define CV_LIB_DIR  CV_INST_DIR ## "/x64/" ## CV_MS_VER ## "/lib/"
 #else
  #define CV_LIB_DIR  CV_INST_DIR ## "/x64/" ## CV_MS_VER ## "/staticlib/"
 #endif
#else
 #ifdef _DLL
  #define CV_LIB_DIR  CV_INST_DIR ## "/x86/" ## CV_MS_VER ## "/lib/"
 #else
  #define CV_LIB_DIR  CV_INST_DIR ## "/x86/" ## CV_MS_VER ## "/staticlib/"
 #endif
#endif


#if _MSC_VER==1500
 #define VCVER 2008
 #define CV_MS_VER "vc9"
#endif

#if _MSC_VER==1600
 #define VCVER 2010
 #define CV_MS_VER "vc10"
#endif

#if _MSC_VER==1700
 #define VCVER 2012
 #define CV_MS_VER "vc11"
#endif

#if _MSC_VER==1800
 #define VCVER 2008
 #define CV_MS_VER "vc12"
#endif


#ifdef _DEBUG	//	デバック
 #define CV_EXT_STR "d.lib"
#else	//	リリース
 #define CV_EXT_STR ".lib"
#endif

#pragma comment(lib, CV_LIB_DIR "opencv_core"  CV_VERSION_STR CV_EXT_STR)
#pragma comment(lib, CV_LIB_DIR "opencv_highgui" CV_VERSION_STR CV_EXT_STR)

#ifdef _DLL	//	動的リンク

#else
 #pragma comment(lib,"comctl32.lib")
 #pragma comment(lib,"vfw32.lib")

 #pragma comment(linker, "/nodefaultlib:\"msvcprt"  CV_EXT_STR "\"")

 #if CV_MAJOR_VERSION==2 && CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION==10
  #pragma comment(lib, CV_LIB_DIR "IlmImf"  CV_EXT_STR )
 #endif
 #pragma comment(lib, CV_LIB_DIR "libjasper"  CV_EXT_STR )
 #pragma comment(lib, CV_LIB_DIR "libjpeg"  CV_EXT_STR )
 #pragma comment(lib, CV_LIB_DIR "libpng"  CV_EXT_STR )
 #pragma comment(lib, CV_LIB_DIR "libtiff"  CV_EXT_STR )
 #pragma comment(lib, CV_LIB_DIR "zlib"  CV_EXT_STR )
#endif

using namespace cv;

#define FOURCC_AVI CV_FOURCC('X','V','I','D')
#define FOURCC_WMV1 CV_FOURCC('W','M','V','1')
#define FOURCC_WMV2 CV_FOURCC('W','M','V','2')

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, char* CmdLine, int nCmdShow){
	VideoCapture cap0(CV_CAP_DSHOW +0);	//	DirectShowでキャプチャ カメラ番号0を開く
	VideoCapture cap1(CV_CAP_DSHOW +1);	//	DirectShowでキャプチャ カメラ番号1を開く
	if(!cap0.isOpened()){
		MessageBox(0,_TEXT("カメラ0を開くことができませんでした。"),_TEXT("エラー"),MB_OK);
		return 1;
	}
	if(!cap1.isOpened()){
		MessageBox(0,_TEXT("カメラ1を開くことができませんでした。"),_TEXT("エラー"),MB_OK);
		return 2;
	}

	int fps=30;	//	フレームレート
	//	キャプチャサイズの指定
	Size cap_size( 320 , 240 );
	cap0.set(CV_CAP_PROP_FRAME_WIDTH , cap_size.width);
	cap0.set(CV_CAP_PROP_FRAME_HEIGHT , cap_size.height);
	//	キャプチャフレームレートの設定
	cap0.set(CV_CAP_PROP_FPS , fps);

	//	キャプチャサイズの指定
	cap1.set(CV_CAP_PROP_FRAME_WIDTH , cap_size.width);
	cap1.set(CV_CAP_PROP_FRAME_HEIGHT , cap_size.height);
	//	キャプチャフレームレートの設定
	cap1.set(CV_CAP_PROP_FPS , fps);
	
	//	Mat img;
	Mat frame0;
	Mat frame1;

	//	2つの画像を横に並べた大きさのMat型を作成する
	Mat base(cap_size.height , cap_size.width*2 , CV_8UC3);

	//	frame0を張り付ける領域をあらわすMat型を作成する
	Mat roi1(base, Rect(0 , 0 , cap_size.width , cap_size.height) );
	//	frame1を張り付ける領域をあらわすMat型を作成する
	Mat roi0(base, Rect(cap_size.width , 0 , cap_size.width , cap_size.height) );

	cap_size.width = cap_size.width * 2;

	VideoWriter writer("test.wmv",FOURCC_WMV2,fps,cap_size);

	namedWindow("dual capture",CV_WINDOW_AUTOSIZE);
	for(;;){
		cap0 >> frame0;	//	カメラ0から1フレーム分の画像を取得
		cap1 >> frame1;	//	カメラ1から1フレーム分の画像を取得

	//	frame0をroi0にコピーする
		frame0.copyTo(roi0);
	//	frame1をroi1にコピーする
		frame1.copyTo(roi1);

	//	現在時刻を取得
		time_t now=time(NULL);
		struct tm tms;
		struct tm* tmp=&tms;
	//	日本時間に変換
		localtime_s(tmp,&now);
		char buf[64];
		sprintf_s(buf,sizeof(buf),"%i/%02i/%02i %02i:%02i:%02i",tmp->tm_year+1900,tmp->tm_mon+1,tmp->tm_mday,tmp->tm_hour,tmp->tm_min,tmp->tm_sec);

	//	ウィンドウに文字を表示
		putText(base,buf,Point(20,20),FONT_HERSHEY_SIMPLEX,0.7,Scalar(0,0,255),1,CV_AA);
	//	ウィンドウを更新
		imshow("dual capture",base);
		writer << base;	//	画像をファイルへ書き込む
		if(waitKey(1000/fps) >=0 )
			break;
	}
	return 0;
}

実行ファイルとソースファイルのダウンロード(dualcapture.zip)