今回はVFW(Video For Windows)によるウェブカメラキャプチャを行ってみます

&ref(capture.JPG);
当たり前ですがウェブカメラがないと動きません
ウェブカメラ内臓PCでない場合はウェブカメラを購入する必要があります
個人的にはLogicool製が良いと思います
VFWを使うとキャプチャー以外にもAVIの動画処理を行うことができます
動画像処理に使われるライブラリには他にもOpenCVやDirect Showなどがありますが
興味がある人は試してみるといいでしょう

	#include <tchar.h>
	#include <windows.h>
	#include <vfw.h>
	#pragma comment(lib,"vfw32.lib")
 
	// ウィンドウプロシージャ
	LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
		if(msg == WM_DESTROY) PostQuitMessage(0);
		return (DefWindowProc(hWnd, msg, wParam, lParam));
	}
 
	// キャプチャーコールバック関数
	LRESULT CALLBACK capVideoStreamCallback(HWND hWnd,LPVIDEOHDR lpVHdr){
 
		// エンターキーでスナップショット
		if(GetAsyncKeyState(VK_RETURN))
			capFileSaveDIB(hWnd,_T("capture.bmp"));
 
		// キャプチャー画像ピクセルデータ
		//lpVHdr->lpData
 
		return TRUE;
	}
 
	int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
	{
		const TCHAR* WC_BASIC = _T("Basic"); // ウィンドウクラス名
 
		/********************************************/
		/* ウィンドウクラスの定義と登録 */
		/********************************************/
  
		// シンプルウィンドウクラス設定
		WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, WndProc, 0,0,hInstance,
			(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED),
			(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED),
			(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NULL};
 
		// シンプルウィンドウクラス登録
		RegisterClassEx(&wcex);
 
		/********************************************/
		/* ウィンドウの作成 */
		/********************************************/
 
		HWND hWnd = CreateWindowEx(
			0, //拡張ウィンドウスタイル
			WC_BASIC, //ウィンドウクラス名
			_T("タイトル"), //タイトルバーにこの名前が表示されます
			WS_OVERLAPPEDWINDOW | WS_VISIBLE, //ウィンドウスタイル
			CW_USEDEFAULT, //X座標
			CW_USEDEFAULT, //Y座標
			640, //幅
			480, //高さ
			NULL, //親ウィンドウのハンドル、親を作るときはNULL
			NULL, //メニューハンドルorリソースID
			hInstance, //インスタンスハンドル
			NULL); 
 
		// キャプチャーウィンドウ
		RECT rect;
		GetClientRect(hWnd,&rect);
		HWND hWndCap = capCreateCaptureWindow(
			_T("Capture Window"),			//	キャプチャウィンドウの名前
			WS_CHILD | WS_VISIBLE,				//	ウィンドウスタイル 
			0, 0,						//	表示位置
			rect.right - rect.left, rect.bottom - rect.top,	//	ウィンドウサイズ
			hWnd,						//	親のハンドル
			NULL);                
		capDriverConnect( hWndCap, 0 ); //	チャンネル1に接続
		capPreviewRate( hWndCap, 1 );   //	プレビューレートの設定 数字が小さいほど速くキャプチャーします。
		capPreview( hWndCap, TRUE );    //	プレビューモード
 
		// ビデオフォーマット取得
		BITMAPINFO bmpinfo;
		capGetVideoFormat(hWndCap,&bmpinfo,sizeof(BITMAPINFO));
 
		// キャプチャーするたびに呼ばれる関数登録
		capSetCallbackOnFrame(hWndCap,capVideoStreamCallback);
 
		MSG msg={0};
		while (GetMessage(&msg,0,0,0)) DispatchMessage(&msg); 
 		
		capDriverDisconnect (hWndCap); 
 
		return 0;
	}

VFWを使うには以下のヘッダーとライブラリが必要です
	#include <vfw.h>
	#pragma comment(lib,"vfw32.lib")

まず、キャプチャーウィンドウをcapCreateCaptureWindow関数で作成する必要があります
ここでは子ウィンドウとして作成しています

		// キャプチャーウィンドウ
		RECT rect;
		GetClientRect(hWnd,&rect);
		HWND hWndCap = capCreateCaptureWindow(
			_T("Capture Window"),			//	キャプチャウィンドウの名前
			WS_CHILD | WS_VISIBLE,				//	ウィンドウスタイル 
			0, 0,						//	表示位置
			rect.right - rect.left, rect.bottom - rect.top,	//	ウィンドウサイズ
			hWnd,						//	親のハンドル
			NULL);                
ウィンドウ作成後
チャンネルに接続します
またプレビューモードで起動します
とりあえずは次の設定で大丈夫です 
		capDriverConnect( hWndCap, 0 ); //	チャンネル1に接続
		capPreviewRate( hWndCap, 1 );   //	プレビューレートの設定 数字が小さいほど速くキャプチャーします。
		capPreview( hWndCap, TRUE );    //	プレビューモード

キャプチャーウィンドウを破棄するときにはチャンネルの接続を切ってください
		capDriverDisconnect (hWndCap); 
 
各フレームごとにキャプチャー画像のピクセル情報を取得したい場合は
次のようなコールバック関数を用意してやります

	// キャプチャーコールバック関数
	LRESULT CALLBACK capVideoStreamCallback(HWND hWnd,LPVIDEOHDR lpVHdr){
 
		// エンターキーでスナップショット
		if(GetAsyncKeyState(VK_RETURN))
			capFileSaveDIB(hWnd,_T("capture.bmp"));
 
		// キャプチャー画像ピクセルデータ
		//lpVHdr->lpData
		return TRUE;
	}

キャプチャーコールバック関数はcapSetCallbackOnFrameマクロで登録することで
1フレームごとに呼び出しされるようになります
	// キャプチャーするたびに呼ばれる関数登録
	capSetCallbackOnFrame(hWndCap,capVideoStreamCallback);
 

キャプチャー画像を保存するにはcapFileSaveDIBマクロを使います
 capFileSaveDIB(hWnd,_T("capture.bmp"));
コールバック関数で書いてはいますが、キャプチャーが成功していればコールバック関数以外でも使えます

今回、処理はしていませんが動画像処理するときには
ピクセルデータの先頭ポインタは次のように取得できます
 // キャプチャー画像ピクセルデータ
 //lpVHdr->lpData

 
全ソースコードは下から
&ref(main.cpp);

#vote((^ω^)やったお[1],何これwww意味不すぎwww[0],。(`ω´#)。あぁん?最近、だらしねぇな[0])
#vote((^ω^)やったお[2],何これwww意味不すぎwww[0],。(`ω´#)。あぁん?最近、だらしねぇな[0])


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS