• 検索結果がありません。

ORiN CAO USB (3) CAO CAO USB ORiN CAO USB 1 2 (4) CAO 3 CAO USB 4 PC OS 1 CPU:Pentium IV 2. 8GHz :512MByte Windows XP SP2 Professional ORiN2 SDK USB D

N/A
N/A
Protected

Academic year: 2021

シェア "ORiN CAO USB (3) CAO CAO USB ORiN CAO USB 1 2 (4) CAO 3 CAO USB 4 PC OS 1 CPU:Pentium IV 2. 8GHz :512MByte Windows XP SP2 Professional ORiN2 SDK USB D"

Copied!
14
0
0

読み込み中.... (全文を見る)

全文

(1)

ORiN でプログラムを組みたいと思っても,FA 機器やロボッ

トのような実機を持っていない方も多いのではないでしょうか.

しかし,ORiN は,マウスや USB カメラなどの身近なハードウ

ェア,さらには,データベースやファイル,ソケット通信など

のソフトウェア資源に対しても有効なものです.例えば,マウ

スと ORiN を使用して,図 1 のように,マウスの現在位置情報

やボタンの押下状態を監視するような簡単なアプリケーション

を作成することも可能です

1

本章では,ORiN のプログラミング入門として,身近なハー

ドウェアデバイスを対象とした簡単な CAO プロバイダとクラ

イアントアプリケーションの作成方法を解説します.

図 1 マウスアプリケーションの構成

1 遠隔監視システムの製作

今回作成するのは,市販の USB カメラを利用した簡単な「遠

隔監視システム」です.近年,セキュリティに関する世間の感

心は高まっており,ホームセキュリティを各家庭に設置するこ

とも一般的になってきました.USB カメラを使用した専用のソ

フトウェアもいくつか出回っていますが,ORiN を使用するこ

とで,自分好みの機能を持たせたシステムを簡単に作成するこ

とができます.

今回作成する遠隔監視システムには,以下のような機能を持

たせることにします.

・ カメラの画像を表示する

・ カメラ画像に変化があった場合にイベントを通知する

・ 画像変化の検出感度を設定する

●システム構成

遠隔監視システムの構成を図 2 および図 3 に示します.

図 2 遠隔監視システムの構成(イメージ)

図 3 遠隔監視システムの構成

1

紙面の都合上,本アプリケーションの解説は割愛します.ソース

コード一式はWebサイトからダウンロードすることができますの

で,興味のある方はお試し下さい.

ORiN プログラミング入門

USB カメラで作る遠隔監視システム

執筆者:小林 佑介 (こばやし・ゆうすけ)

池添 明宏 (いけぞえ・あきひろ)

飯田 学 (いいだ・まなぶ)

所属 :株式会社セック 開発本部 宇宙先端システムビジネスフィールド

(2)

ロバイダウィザードを利用します.

生成された CAO プロバ

PC

CPU:Pentium IV 2.

8GHz

メモリ:512MByte

OS

Windows XP SP2 Professional

利用ソフトウェア

ORiN2

SDK 評価

DirectX 9.0 SDK

Microsoft Visual C++ 6.0

Microsoft Visual Studio .NET 2003

USB-CA

1 開発環境

USB カメラ

M30MS

(アイ・オー・デー

タ機器)

トウ

どをおこな

アプリケーションを作成します.

の表示,

表 1 に示す環境で,開発および動作確認をおこ

いました

2

2

プロバイダの一般的な開発の流れは

(1)

にあわせて,実装する

(2)

これには,CAO プ

ORiN では,ロボット向けのインタフェースと,アプリケー

ション向けのインタフェースが用意されています.ロボット向

けのインタフェースに準じたソフトウェアを「CAO プロバイ

ダ」

アプリケーション向けのインタフェースに準じたソフ

(3)

イダのテンプレートに,必要な

(4)

バイダの具体的な実装手順について,解説していきます

4

メソッドを実装します.

作成した CAO プロバイダの動作確認をおこない,正常

に動作しなかった場合はデバッグ作業を実施します

3

以降,今回作成する CAO プロバイダを「USB カメラプロバ

イダ」と呼ぶこととし,上記の手順に従って,USB カメラプ

ェアを「クライアントアプリケーション」と呼びます.

本システムでは,USB カメラから画像を取得するなどの機能

を持つ CAO プロバイダと,取得した画像の表示な

うクライアント

●開発の流れ

以降,この遠隔監視システムを例に,ORiN アプリケーショ

ンの開発について解説していきます.はじめに,CAO プロバイ

ダについて,USB カメラからの画像の取得,カメラ画像の変化

のチェックなど,

ハードウェア側の処理を実装します.

続いて,

クライアントアプリケーションとして,取得した画像

画像変化のイベント通知などの処理を実装します.

なお,今回は

図 4 USB カメラプロバイダ構成

カメラプロバイダには以

・ クライアントからの要求に従い,USB カメラの画像を

生じた場合,それを検知し,クライ

用マルチ

ディア拡張 API「DirectShow」を利用します.

USBカメラプロバイダの設計

まずは,USB カメラプロバイダの設計をおこないます.遠隔

監視システムを構築するために,USB

の機能を持たせることにします.

・ 一定周期で USB カメラから画像を取得する

クライアントに渡す

カメラ画像に変化が

アントに通知する

USBカメラプロバイダの作成

それではまず,USB カメラを利用するための CAO プロバイ

ダを作成しましょう.CAO

・ 変化を検知する際の感度を設定する

USB カメラプロバイダの構成は図 4 のようになります.図の

ように,自動生成される CAO プロバイダのテンプレートの中

に,必要な機能を実装していくことになります.また,USB カ

メラとのアクセスには,DirectX に含まれる Windows

下のようになります.

CAO プロバイダの設計をおこないます.

CAO プロバイ

ダで扱うターゲット(デバイスなど)

クラスとメソッドを決定します.

CAO プロバイダの設計を決定したら,次に CAO プロ

バイダのテンプレートを生成します.

3

CAOプロバイダのデバッグ方法については,ORiN2 SDKに収録

の「CAOプロバイダ作成ガイド」を参照して下さい.

2

USBカメラは,Windows Driver Model(WDM)というドライバ規

格に対応している必要があります.お持ちのUSBカメラがWDM対

応であることをご確認ください.また,

USBカメラから画像を取得

するためには,DirectX SDKが必要となります.事前にMicrosoft

社のサイト(

http://www.microsoft.com/downloads/

)からダウンロー

ドし,インストールをおこなってください.

4

CAOプロバイダの作成にあたっては,HRESULTやBSTR,

VARIANT,SAFEARRAYなど,COM(Component Object Model)

特有のデータ型を使用します.詳細はORiN2 SDKに収録の

「ORiN2プログラミングガイド」で解説しています.合わせてご覧

下さい.

(3)

表2 CAOプロバイダのクラス機能概要

表3 USBカメラプロバイダ仕様

表4 CCameraManagerクラスの公開メソッド

クラス名

メソッド

説明

FinalInitialize

カメラプロバイダの初期化処理をおこないます.

FinalConnect

USB カメラへの接続処理をおこないます.

FinalDisconnect

USB カメラリソースの開放処理をおこないます.

OnTimer

一定周期で画像の変化を監視します.

CaoProvController

GetCameraManager カメラ管理オブジェクトへのポインタを取得します.

FinalInitialize

CaoProvVariable の初期化をおこないます.

FinalGetValue

画像の変化の検出感度を取得します.

CaoProvVariable

FinalPutValue

画像の変化の検出感度を設定します.

FinalInitialize

CaoProvFile の初期化をおこないます.

CaoProvFile

FinalGetValue

カメラから取得した画像データを取得します.

メソッド名

説明

CCameraManager();

コンストラクタです.

virtual ~CCameraManager();

デストラクタです.

HRESULT Initialize ();

DirectShow の初期化をおこないます.

void Finalize();

DirectShow の終了処理をおこないます.

HRESULT Capture();

USB カメラから画像を取得し,カメラ管理クラスが保持しているメモリ上の画像デー

タを更新します.

BOOL IsDiffDetected();

現在の画像と 1 サンプリング前の画像を比較し,違いが検出された場合は True を返し

ます.画像を比較する際の閾値が小さい場合は,画像のわずかな変化でも検出し,True

を返します.逆に,閾値を大きくすると,画像が大きく変化しないと True を返さなく

なります.

BYTE *GetImage(long *lSize);

キャプチャした画像のバイナリデータを取得するメソッドです.引数として long 型の

ポインタを渡すことで,画像のサイズを取得することができます.

long GetThreshold();

画像を比較する際の閾値を取得します.

void SetThreshold( long threshold ); 画像を比較する際の閾値を設定します.

クラス名

説明

CaoProvController

コントローラクラス.コントローラのリソース全般に関わる機能を提供します.

CaoProvVariable

変数クラス.変数リソースに関わる機能を提供します.

CaoProvRobot

ロボットクラス.ロボットリソースに関わる機能を提供します.

CaoProvFile

ファイルクラス.ファイル,フォルダリソースに関わる機能を提供します.

CaoProvTask

タスククラス.タスクリソースに関わる機能を提供します.

CaoProvCommand

コマンドクラス.コマンドリソースに関わる機能を提供します.

CaoProvExtension

拡張クラス.拡張ボードリソースに関わる機能を提供します.

CaoProvMessage

メッセージクラス.メッセージリソースに関わる機能を提供します.

(4)

上にあげた機能を実現するように,USB カメラプロバイダに

実装するクラスとメソッドを決定します.CAO プロバイダは,

表 2 に示すような機能を持つクラスから構成されています.こ

の中でも最も重要なクラスは CaoProvController であり,必ず実

装する必要があります.その他のクラスに関しては,必要な機

能に対応するクラスだけを実装すれば OK です.また,各クラ

スには複数の公開メソッドが用意されていますが,これらをす

べて実装する必要はなく,必要なメソッドのみを実装します

5

今回は,USB カメラプロバイダを表 3 のように実装すること

とします.また,USB カメラプロバイダのクラス構成を図 5 に

示します.CAO プロバイダの標準クラスとは別に,USB カメ

ラを管理するクラスとして,CCameraManager クラスを用意し

ます.

図5 USBカメラプロバイダのクラス構成

●テンプレートの生成

プロバイダの設計が決まったら,USB カメラプロバイダのテ

ンプレートを作成します.ORiN2 SDK には,CAO プロバイダ

ウィザードという,CAO プロバイダの開発を支援するツールが

用意されています.このツールを利用することで,CAO プロバ

イダを開発するための Visual C++6.0 のプロジェクトと,テンプ

レートを簡単に作成することができます.

CAO プロバイダウィザードの使い方を説明します.

スタート

メニューから「ORiN 2」→「CAO Provider」→「CaoProvWiz」

を選択して,CAO プロバイダウィザードを起動してください.

最初に,図 6 に示す画面が表示されますので,CAO プロバイ

ダを作成するフォルダの場所を選択してください

6

「Next >」ボタンを押すと,図 7 に示す画面が表示されます.

本画面には,作成する CAO プロバイダの情報を入力します.

DLL Name は,生成される DLL ファイルの名前になります.

Vender Name と Module Name は,CAO プロバイダを利用すると

きの ID となります.また,MFC を利用する場合は,Use MFC

にチェックを入れてください.なお,DLL Name と Vender Name

の入力は必須となります.Module Name は,省略した場合,DLL

Name と同じ名前になります.

ここでは,カメラプロバイダに関する情報として,以下のと

おり入力します.

DLL Name

:Camera

Vender Name

:Samples

Module Name

:Camera

Use MFC

:チェックなし

「Next >」ボタンを押下すると,確認ダイアログが表示され

ますので,間違いがなければ「はい」を選択してください.

これで,CAO プロバイダのテンプレートが生成されます.出

力先として選択したフォルダに,図 8 に示すようなファイルが

生成されていることを確認してください.

図 6 CAO プロバイダ作成フォルダ選択画面

図 7 プロバイダ情報入力画面

5

クラスごとに,必ず実装しなければならないメソッドもあります

ので,注意して下さい.詳細は,ORiN2 SDKに附属の「CAOプロ

バイダ作成ガイド」を参照して下さい.

6

プロバイダの作成先のフォルダには,図6のように,終端に「Src」

という名のサブフォルダを含めることを推奨します.

(5)

・ 「リンクタブ」の「オブジェクト/ライブラリモジュー

ル」に以下のライブラリを追加する.

strmiids.lib

●カメラ管理クラスCCameraManagerの実装

CAO プロバイダの各クラスの実装をおこなう前に,USB カ

メラの管理クラス CCameraManager を実装します.

カメラ管理クラスは,

DirectShow 経由で USB カメラにアクセ

スし,画像データを取得します

7

.また,前回撮影画像との比較

や,画像比較のための閾値の更新などをおこないます.

カメラ管理クラスの公開メソッドを表 4 に示します.また,

ソースコードをリスト 1,リスト 2 に示します,この 2 つのフ

ァイルを,

先ほどの USB カメラプロバイダのプロジェクトに追

加して下さい.

リスト1 CameraManager.h

図 8 CAO プロバイダウィザードで生成されるファイル一覧

#ifndef __CAMERAMANAGER_H_ #define __CAMERAMANAGER_H_ #include "stdafx.h" #include <dshow.h> #include <qedit.h> #include <conio.h> #include <math.h> /** USB カメラを管理するクラス */ class CCameraManager { public: CCameraManager(); virtual CCameraManager(); HRESULT Initialize(); void Finalize(); HRESULT Capture(); BOOL IsDiffDetected(); BYTE *GetImage(long *lSize); long GetThreshold();

void SetThreshold( long threshold ); private:

IPin* GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir); private: IGraphBuilder *m_pGraph; // フィルタグラフマネージャ IMediaControl *m_pMC; // メディアコントロール IMediaEvent *m_pEV; // メディアイベント ICaptureGraphBuilder2 *m_pCapture; // キャプチャグラフ IBaseFilter *m_pF; // グラバフィルタ IBaseFilter *m_pbf; // デバイスフィルタ IBaseFilter *m_pNull; // Null レンダラフィルタ ISampleGrabber *m_pGrab; // サンプルグラバ BYTE *m_pBuffer_Cur; // 画像格納バッファ(カレント) BYTE *m_pBuffer_Pre; // 画像格納バッファ(前) BYTE *m_pImage; long m_imageSize; BOOL m_bInitialize; long m_threshold; // 画像変化の閾値 HANDLE m_hMutex; }; #endif // __CAMERAMANAGER_H_

●環境設定

Visual C++ 6.0 で CAO プロバイダの開発をおこなうためには,

いくつかの環境設定が必要です.まずは,生成されたファイル

の中から,プロジェクトワークスペースファイル(CaoProv.dsw)

を選択し,Visual C++6.0 を起動して,以下の設定をおこなって

ください.

・ メニューバーの「ツール」→「オプション」でオプシ

ョンダイアログを開く.

・ ディレクトリタブを選択する.

・ 表示するディレクトリから「インクルードファイル」

を選択し,以下を追加する.

<ORiN インストールディレクトリ>¥CAO¥Include

・ 表示するディレクトリから「ライブラリファイル」を

選択し,以下を追加する.

<ORiN インストールディレクトリ>¥CAO¥Lib

同様に,DirectShow を使用するために,以下の設定をおこな

います.

・ メニューバーの「ツール」→「オプション」でオプシ

ョンダイアログを開く.

・ ディレクトリタブを選択する.

・ 表示するディレクトリから「インクルードファイル」

を選択し,以下を追加する.

<DirectX SDK インストールディレクトリ>¥Include

・ 表示するディレクトリから「ライブラリファイル」を

選択し,以下を追加する.

<DirectX SDK インストールディレクトリ>¥Lib

・ メニューバーから「プロジェクト」→「設定」でプロ

ジェクトの設定ダイアログを開く.

リスト

2 CameraManager.cpp

・ 設定の対象を「すべての構成」にし,画面左のツリー

表示から「CAOPROV」を選択する.

7

紙面の都合上,DirectXやDirectShowに関する説明は割愛します。

詳細は,DirectXのマニュアルを参照してください.

(6)

#include "stdafx.h" #include "CameraManager.h" /** コンストラクタ */ CCameraManager::CCameraManager(){ m_pF = NULL; m_pGrab = NULL; m_pbf = NULL; m_pMC = NULL; m_pEV = NULL; m_pGraph = NULL; m_pCapture = NULL; m_pBuffer_Cur = NULL; m_pBuffer_Pre = NULL; m_pImage = NULL; m_bInitialize = FALSE; m_threshold = 10; } /** デストラクタ */ CCameraManager:: CCameraManager(){ } /** 初期化 */ HRESULT CCameraManager::Initialize(){ HRESULT hr; AM_MEDIA_TYPE amt; // メディアタイプ m_hMutex = CreateMutex(NULL,FALSE,NULL); //ミューテックス生成 // COM の初期化 CoInitialize(NULL); // (1) フィルタグラフマネージャ作成

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGraph); if (FAILED(hr)) {

return hr; }

// (2) デバイスフィルタの準備 // システムデバイス列挙子を作成 ICreateDevEnum *pDevEnum =NULL;

hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum); if (FAILED(hr)) {

return hr; }

// ビデオキャプチャデバイス列挙子を作成 IEnumMoniker *pClassEnum = NULL; pDevEnum->CreateClassEnumerator (CLSID_VideoInputDeviceCategory, &pClassEnum, 0); if (pClassEnum == NULL){ // ビデオキャプチャは存在しない pDevEnum->Release(); return S_FALSE; } // 最初に見つかったビデオキャプチャデバイスのオブジェクトの // インタフェースを得る

IMoniker *pMoniker = NULL; ULONG cFetched;

if (pClassEnum->Next(1, &pMoniker, &cFetched) == S_OK) { pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_pbf); pMoniker->Release();

}

pClassEnum->Release(); pDevEnum->Release();

// デバイスフィルタをフィルタグラフに追加 hr = m_pGraph->AddFilter(m_pbf, L"Video Capture"); if (FAILED(hr)) {

return hr; }

// (3) キャプチャグラフビルダ作成

CoCreateInstance(CLSID_CaptureGraphBuilder2 , NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapture); // フィルタグラフをキャプチャグラフに組み込む hr = m_pCapture->SetFiltergraph(m_pGraph); if (FAILED(hr)) { return hr; } // (4) サンプルグラバ作成

hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (LPVOID *)&m_pF);

if (FAILED(hr)) { return hr; }

hr = m_pF->QueryInterface(IID_ISampleGrabber, (void **)&m_pGrab); if (FAILED(hr)) { return hr; } // (5) メディアタイプの設定 // グラバフィルタの挿入場所の特定のための設定 ZeroMemory(&amt, sizeof(AM_MEDIA_TYPE));

// Sample Grabber の入力ピン(Capture Device の出力ピン)は UYVY amt.majortype = MEDIATYPE_Video; amt.subtype = MEDIASUBTYPE_RGB24; amt.formattype = FORMAT_VideoInfo; hr = m_pGrab->SetMediaType(&amt); if (FAILED(hr)) { return hr; } // グラバフィルタをフィルタグラフに追加 hr = m_pGraph->AddFilter(m_pF, L"Grabber"); if (FAILED(hr)) { return hr; } // (6) Null Renderer フィルタの作成

hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&m_pNull);

if (FAILED(hr)) { return hr; } hr = m_pGraph->AddFilter(m_pNull, L"Renderer"); if (FAILED(hr)) { return hr; } // (7) フィルタの接続

IPin *pSrcOut = GetPin(m_pbf, PINDIR_OUTPUT); IPin *pSGrabIN = GetPin(m_pF, PINDIR_INPUT); IPin *pSGrabOut = GetPin(m_pF, PINDIR_OUTPUT); IPin *pNullIN = GetPin(m_pNull, PINDIR_INPUT); // ソースフィルタ←→サンプルグラバフィルタの接続 hr = m_pGraph->Connect(pSrcOut, pSGrabIN); if (FAILED(hr)) { return hr; } // サンプルグラバフィルタ←→Null レンダラの接続 hr = m_pGraph->Connect(pSGrabOut, pNullIN); if (FAILED(hr)) { return hr; } pSrcOut->Release(); pSGrabIN->Release(); pSGrabOut->Release(); pNullIN->Release(); // (8) グラバのモードを適切に設定 hr = m_pGrab->SetBufferSamples(TRUE); if (FAILED(hr)) { return hr; } hr = m_pGrab->SetOneShot(FALSE); if (FAILED(hr)) { return hr; } // (9) メディアコントロール作成

hr = m_pGraph->QueryInterface(IID_IMediaControl, (LPVOID *)&m_pMC); if (FAILED(hr)) {

return hr; }

(7)

hr = m_pGraph->QueryInterface(IID_IMediaEvent, (LPVOID *)&m_pEV); if (FAILED(hr)) { return hr; } // (10) 画像格納領域確保 AM_MEDIA_TYPE mt; // メディアタイプ取得 hr = m_pGrab->GetConnectedMediaType(&mt); if (FAILED(hr)) { return hr; } m_imageSize = mt.lSampleSize; WaitForSingleObject(m_hMutex,INFINITE); m_pBuffer_Cur = (BYTE *)malloc(m_imageSize); ReleaseMutex(m_hMutex);

if (m_pBuffer_Cur==NULL) { return S_FALSE; }

m_pBuffer_Pre = (BYTE *)malloc(m_imageSize); if (m_pBuffer_Pre==NULL) {

return S_FALSE; }

m_pImage = (BYTE *)malloc(

m_imageSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); if (m_pImage==NULL) { return S_FALSE; } // ファイルヘッダ部分を書き込む BITMAPFILEHEADER bfh; memset(&bfh, 0, sizeof(bfh)); bfh.bfType = 'MB';

bfh.bfSize = sizeof(bfh) + m_imageSize + sizeof(BITMAPINFOHEADER); bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.pbFormat;

// ビットマップフォーマットを書き込む BITMAPINFOHEADER bih; memset(&bih, 0, sizeof(bih)); bih.biSize = sizeof(bih); bih.biWidth = vih->bmiHeader.biWidth; bih.biHeight = vih->bmiHeader.biHeight; bih.biPlanes = 1; bih.biBitCount = 24;

memcpy(m_pImage, &bfh, sizeof(bfh));

memcpy(m_pImage + sizeof(bfh), &bih, sizeof(bih) ); hr = m_pMC->Run(); if (FAILED(hr)) { return hr; } m_bInitialize = TRUE; // (11) スナップショット取得 Sleep(1000); // 初期化が終了するまで 1 秒待つ Capture(); return S_OK; } /** 終了処理 */ void CCameraManager::Finalize(){ if (m_pF != NULL) m_pF->Release(); if (m_pGrab != NULL) m_pGrab->Release(); if (m_pbf != NULL) m_pbf->Release(); if (m_pMC != NULL) m_pMC->Release(); if (m_pEV != NULL) m_pEV->Release(); if (m_pGraph != NULL) m_pGraph->Release(); if (m_pCapture != NULL) m_pCapture->Release(); if (m_pNull != NULL) m_pNull->Release(); if (m_pBuffer_Cur != NULL) free(m_pBuffer_Cur); if (m_pBuffer_Pre != NULL) free(m_pBuffer_Pre); if (m_pImage != NULL) free(m_pImage); // COM のリリース CoUninitialize(); CloseHandle(m_hMutex); } /** キャプチャ */ HRESULT CCameraManager::Capture(){ HRESULT hr; if (!m_bInitialize) { return S_FALSE; } // 画像格納バッファの退避 WaitForSingleObject(m_hMutex,INFINITE);

CopyMemory(m_pBuffer_Pre, m_pBuffer_Cur ,m_imageSize); // バッファサイズ取得 long work; hr = m_pGrab->GetCurrentBuffer(&work, NULL); if (FAILED(hr)) { return hr; } // バッファ取得

hr = m_pGrab->GetCurrentBuffer(&work, (long *)m_pBuffer_Cur); ReleaseMutex(m_hMutex); if (FAILED(hr)) { return hr; } return S_OK; } /** ピン取得 */

IPin* CCameraManager::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir){ BOOL bFound = FALSE;

IEnumPins *pEnum; IPin *pPin; HRESULT hr;

hr = pFilter->EnumPins(&pEnum); if (FAILED(hr)) {

return (IPin *)NULL; }

while(pEnum->Next(1, &pPin, 0) == S_OK) { PIN_DIRECTION PinDirThis; pPin->QueryDirection(&PinDirThis); // 引数で指定した方向のピンなら break if (PinDir == PinDirThis) { bFound = TRUE; break; } pPin->Release(); } pEnum->Release();

return (bFound ? pPin : (IPin *)NULL); }

/** 画像差分検出 */

BOOL CCameraManager::IsDiffDetected(){ double s = 0.0;

WaitForSingleObject(m_hMutex,INFINITE); for (int i = 0; i < m_imageSize; i++) { // 差分をとる

s = s + fabs(m_pBuffer_Cur[i] - m_pBuffer_Pre[i]); }

ReleaseMutex(m_hMutex);

// s / サイズ > m_threshold(閾値) の場合はアラーム return ( (s / m_imageSize) > m_threshold ? TRUE : FALSE );

}

/** 画像取得 */

BYTE *CCameraManager::GetImage(long *lSize ){ WaitForSingleObject(m_hMutex,INFINITE);

*lSize = m_imageSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); memcpy(m_pImage + sizeof(BITMAPFILEHEADER) +

sizeof(BITMAPINFOHEADER), m_pBuffer_Cur, sizeof(BYTE) * m_imageSize); ReleaseMutex(m_hMutex);

(8)

return m_pImage; } /** 閾値取得 */ long CCameraManager::GetThreshold(){ return m_threshold; } /** 閾値設定 */

void CCameraManager::SetThreshold( long threshold ){ m_threshold = threshold; }

●StdAfx.h の編集

続いて,プリコンパイル済みヘッダファイル(StdAfx.h)の編集

をおこないます.本ファイル中に「各社追加部分はこれ以下に

記述する」とありますので,まずは,リスト 3 の①を追加して

下さい.①は,CameraManager.h ファイルをインクルードして

います.これで,カメラプロバイダから CCameraManager クラ

スが利用できるようになります.次に,リスト 3 の②に示すよ

うに,

CAOP_TIMER_INTERVAL マクロの定義を 0 から 10 に変

更してください.本マクロの詳細については後述します.

リスト3 StdAfx.h

// ========== 各社追加部分はこれ以下に記述する.========== #include "CameraManager.h" …① #define CAOP_TIMER_INTERVAL 10 …②

●CaoProvControllerの実装

それではいよいよ,CAO プロバイダの各クラスを実装してい

きましょう.最初は,CaoProvController クラスの実装をおこな

います.CaoProvController クラスは,CAO プロバイダのメイン

となるクラスです.USB カメラプロバイダでは,カメラ管理ク

ラスの初期化処理や終了処理などを実装します.

CaoProvController.h の編集.

まずは,CaoProvController.h ファイルを開いて,実装するメソ

ッドのコメントアウトを解除します.リスト 4 の①,②のよう

に , FinalInitialize メ ソ ッ ド , FinalConnect メ ソ ッ ド ,

FinalDisconncet メソッドのコメントアウトを解除してください.

次に,リスト 4 の④で,カメラ管理オブジェクトへのポイン

タとして,m_cameraManager を宣言します.カメラ管理クラス

は,CaoProvController クラス以外でも使用しますので,カメラ

管理オブジェクトのポインタを取得するためのメソッドとして,

リスト 4 の③に示す GetCameraManager メソッドを宣言します.

FinalInitialize メソッド

続いて,各メソッドの実装に移ります.CaoProvController.cpp

を開いてください.

まずは,FinalInitialize メソッド実装です.このメソッドは,

CAO プロバイダが生成されるときに呼び出されます.ソース

ファイル中のコメントアウトを解除し,

リスト 5 の①のように

実装します.

ここでは,

特別な初期化処理はおこなわず,

単に,

処理の成功を意味する「S_OK」を戻り値とします.

FinalConnect メソッド

次に FinalConnect メソッドを実装します.このメソッドは,

クライアントアプリケーションから CAO プロバイダに接続し

たときに呼び出されます.コメントアウトを解除し,リスト 5

の②のように実装をおこなってください.ここでは,カメラ管

理クラスのインスタンスの生成をおこなった後,Initialize メソ

ッドを呼び出し,DirectShow の初期化をおこないます.

FinalDisconnect メソッド

FinalDisconnect メソッドは,クライアントアプリケーション

が,CAO プロバイダとの接続を切断したときに呼び出されます.

FinalDisconncet メソッドをリスト 5 の③のように実装してくだ

さい.ここでは,カメラ管理オブジェクトの Finalize メソッド

をコールし,DirectShow の終了処理をおこないます.

OnTimer メソッド

OnTimer メソッドは,CAO プロバイダの実行中に一定周期で

呼び出されるメソッドです.

今回の遠隔監視システムでは,

USB

カメラから定期的に画像を取得するために利用します.本メソ

ッ ド の 呼 び 出 し 周 期 は , StdAfx.h に 定 義 さ れ て い る

CAOP_TIMER_INTERVAL マクロにミリ秒単位で設定します.

先ほど,

CAOP_TIMER_INTERVAL マクロの値を 10 としました

ので,OnTimer メソッドは 10 ミリ秒周期で呼び出されます.な

お,値が 0 のときは,OnTimer メソッドは呼び出されません.

OnTimer メソッドは,リスト 5 の④に示すように実装します.

このメソッドでは,まず,カメラ管理オブジェクトの Capture

メソッドを呼び出し,USB カメラから画像を取得します.次に,

IsDiffDetected メソッドで,画像に変化があったかどうかの判別

をおこないます.ここで,画像に変化が生じた場合は,メッセ

ージを生成し,CaoEngine へとメッセージを送信します.メッ

セージを受け取った CaoEngine は,クライアントアプリケーシ

ョンにイベントを通知します.

GetCameraManager

最後に,CaoProvFile クラスや CaoProvVariable クラスから,

カ メ ラ 管 理 オ ブ ジ ェ ク ト に ア ク セ ス で き る よ う に ,

GetCameraManagerメソッドをリスト5の⑤のように実装します.

このメソッドでは,カメラ管理オブジェクトへのポインタを返

り値とします.

リスト4 CaoProvController.h

∼中略∼ protected: HRESULT FinalInitialize(); …① // void FinalTerminate(); HRESULT FinalConnect(); …② HRESULT FinalDisconnect(); ∼中略∼ // ========== 各社追加関数はこれ以下に記述する.==========

(9)

CCameraManager *GetCameraManager(); …③ private: // ========== 各社追加関数はこれ以下に記述する.========== CCameraManager *m_cameraManager; …④ ∼中略∼

リスト5 CaoProvController.cpp

∼中略∼ HRESULT CCaoProvController::FinalInitialize() { return S_OK; …① } ∼中略∼ HRESULT CCaoProvController::FinalConnect() { // USB カメラから画像を取得するための初期化処理をおこなう. HRESULT hr;

m_cameraManager = new CCameraManager(); …② hr = m_cameraManager->Initialize(); return hr; } ∼中略∼ HRESULT CCaoProvController::FinalDisconnect() { // USB カメラの終了処理をおこなう. m_cameraManager->Finalize(); …③ return S_OK; } ∼中略∼ void CCaoProvController::OnTimer() { HRESULT hr; …④ // キャプチャ hr = m_cameraManager->Capture(); if (FAILED(hr)) { return; } // 画像の変化を検出 if (m_cameraManager->IsDiffDetected()) { SYSTEMTIME st; char szData[32]; VARIANT vntData; VARIANT vntNowTime; CComPtr<CCaoProvMessage> pMess; // メッセージを設定 wsprintf(szData, "画像が変化しました¥n"); CComBSTR bstrMessage(szData); vntData.vt = VT_BSTR; vntData.bstrVal = bstrMessage; // 現在時刻を設定 GetLocalTime(&st); vntNowTime.vt = VT_DATE; double dDate = 0.0; // SYSTEMTIME から double に変換する SystemTimeToVariantTime(&st, &dDate); vntNowTime.date = dDate; // メッセージを生成/送信

hr = CreateMessage(&pMess, 0, &vntData, &vntNowTime);

if (SUCCEEDED(hr)) {

SendMessage(pMess, CAO_MSG_NORMAL │ CAO_MSG_OUTPUT_LOG);

} } return; } ∼中略∼ // ========== 各社追加関数はこれ以下に記述する.========== CCameraManager *CCaoProvController::GetCameraManager(){ return m_cameraManager; …⑤ }

●CaoProvVariableの実装

続いて,CaoProvVariable クラスの実装をおこないます.

CaoProvVariable クラスは,

CAO プロバイダ側で管理する情報を,

変数として扱うための機能を提供するクラスです.ここでは,

画像の変化を検出するための感度を設定する機能を実装します.

CaoProvVariable.h の編集

まず,CaoProvVariable.h を開き,リスト 6 に示すように,

FinalInitialize メソッド,FinalGetValue メソッド,FinalPutValue

メソッドのコメントアウトを解除してください.また,メンバ

変 数 と し て , カ メ ラ 管 理 オ ブ ジ ェ ク ト へ の ポ イ ン タ

m_cameraManager を宣言します.

FinalInitialize

次に,FinalInitialize メソッドの実装をおこないます.

このメソッドは,クライアントアプリケーション側で

CaoVariable を取得した際に呼び出されます.このメソッドを,

リスト 7 のように実装してください.このメソッドは,引数と

して,親オブジェクトへのポインタを受け取ります.ここで,

親オブジェクトの判定をおこない,親が CaoProvController だっ

た場合は,①に示すように GetCameraManager メソッドを呼び

出し,カメラ管理オブジェクトへのポインタを取得します.

FinalGetValue

続いて,FinalGetValue メソッドの実装をおこないます.この

メソッドは,変数を取得する際に呼び出されるメソッドです.

ここでは,リスト 7 の③のように,カメラ管理オブジェクト

から,画像の変化を検出するための感度を取得し,VARIANT

型の引数として渡された pVal に値をセットします.

FinalPutValue

続いて,FinalPutValue メソッドの実装をおこないます.この

メソッドでは,クライアントアプリケーションから渡された,

画像の変化を検出するための感度の値を,カメラ管理オブジェ

クトに設定する機能を実装します.

ここでは,リスト 7 の④に示すように,クライアントアプリ

ケーションから受け取ったデータが,VT_I4(4 バイト整数型)で

あるかどうかを確認し,VT_I4 型であれば,カメラ管理オブジ

ェクトにその値を設定します.

リスト6 CaoProvVariable.h

∼中略∼ protected:

(10)

HRESULT FinalInitialize(PVOID pObj); …① // void FinalTerminate();

∼中略∼

HRESULT FinalGetValue(/*[out, retval]*/ VARIANT *pVal); …② HRESULT FinalPutValue(/*[in]*/ VARIANT newVal); ∼中略∼ // ========== 各社追加関数はこれ以下に記述する.========== private: // ========== 各社追加関数はこれ以下に記述する.========== CCameraManager *m_cameraManager; …③ ∼中略∼

リスト7 CaoProvVariable.cpp

∼中略∼

HRESULT CCaoProvVariable::FinalInitialize(PVOID pObj) {

CCaoProvController* pCaopCtrl = NULL; CCaoProvExtension* pCaopExp = NULL; CCaoProvFile* pCaopFile = NULL; CCaoProvRobot* pCaopRobot = NULL; CCaoProvTask* pCaopTask = NULL; // 親オブジェクトの判定 switch (m_ulParentType) { case SYS_CLS_CONTROLLER: // カメラ管理オブジェクトへのポインタを取得する pCaopCtrl = (CCaoProvController*)pObj; m_cameraManager = pCaopCtrl->GetCameraManager(); …① break; case SYS_CLS_EXTENSION: pCaopExp = (CCaoProvExtension*)pObj; break; case SYS_CLS_FILE: pCaopFile = (CCaoProvFile*)pObj; break; case SYS_CLS_ROBOT: pCaopRobot = (CCaoProvRobot*)pObj; break; case SYS_CLS_TASK: pCaopTask = (CCaoProvTask*)pObj; break; } return S_OK; …② } ∼中略∼

HRESULT CCaoProvVariable::FinalGetValue(VARIANT *pVal) { // カメラ管理クラスから感度を取得し戻り値とする pVal->vt = VT_I4; …③ pVal->lVal = m_cameraManager->GetThreshold(); return S_OK; } ∼中略∼

HRESULT CCaoProvVariable::FinalPutValue(VARIANT newVal) {

// カメラ管理クラスに感度を設定する

if( newVal.vt == VT_I4 ){

m_cameraManager->SetThreshold( newVal.lVal ); return S_OK; …④ } else { return S_FALSE; } } ∼中略∼

●CaoProvFileの実装

最後に,CaoProvFile クラスの実装をおこないます.このクラ

スは,先ほどの変数(CaoProvVariable)と同様,情報をファイルと

して扱う場合に利用します.カメラプロバイダでは,カメラ画

像をバイナリデータとして取得する機能を実装します.

CaoProvFile.h の編集

まずは,

他のクラスと同様に,

CaoProvFile.h ファイルを開き,

リ ス ト 8 の ①, ②の よう に, FinalInitialize メ ソッ ドと

FinalGetValue メソッドのコメントアウトを解除してください.

また,メンバ変数として,リスト 8 の③に示すように,カメラ

管理オブジェクトへのポインタm_cameraManagerを宣言します.

FinalInitialize

次に,FinalInitialize メソッドの実装をおこないます.ここで

も,CaoProvVariable クラスと同様に,リスト 9 の①に示すよう

に,親オブジェクトが CaoProvController クラスだった場合は,

GetCameraManager メソッドを呼び出し,カメラ管理オブジェク

トへのポインタを取得します.

FinalGetValue

続いて,FinalGetValue メソッドの実装をおこないます.

このメソッドでは,USB カメラが取得した画像データを取得

するための機能を実装します.

ここでは,リスト 9 の③に示すようにカメラ管理オブジェク

トの GetImage メソッドを呼び出し,カメラ画像のバイナリデー

タを取得します.その後,画像サイズと同じ大きさの

SAFEARRAY を用意し,画像データをコピーします.

リスト8 CaoProvFile.h

∼中略∼ protected:

HRESULT FinalInitialize(PVOID pObj); …① // void FinalTerminate();

∼中略∼

HRESULT FinalGetValue(/*[out, retval]*/ VARIANT *pVal); …② ∼中略∼ // ========== 各社追加関数はこれ以下に記述する.========== private: // ========== 各社追加関数はこれ以下に記述する.========== CCameraManager *m_cameraManager; …③ ∼中略∼

リスト9 CaoProvFile.cpp

∼中略∼

(11)

{

CCaoProvController* pCaopCtrl = NULL; CCaoProvFile* pCaopFile = NULL;

// 親オブジェクトの判定 switch (m_ulParentType) { case SYS_CLS_CONTROLLER: // カメラ管理オブジェクトへのポインタを取得する pCaopCtrl = (CCaoProvController*)pObj; m_cameraManager = pCaopCtrl->GetCameraManager(); …① break; case SYS_CLS_FILE: pCaopFile = (CCaoProvFile*)pObj; break; } return S_OK; …② } ∼中略∼

HRESULT CCaoProvFile::FinalGetValue(VARIANT *pVal) {

long lSize;

// カメラ管理クラスから画像データを取得する.

BYTE *buf = m_cameraManager->GetImage(&lSize);

SAFEARRAY* pSa;

SAFEARRAYBOUND bounds = {lSize , 0}; // Elemnts, LBound

// BYTE 型の SAFEARRAY を用意し画像データをコピーする

pSa = SafeArrayCreate(VT_UI1, 1, &bounds);

BYTE* pbstrArray;

SafeArrayAccessData(pSa, (void **)&pbstrArray); …③ for (long i= 0; i < lSize; i++) {

pbstrArray[i] = *buf;

buf++;

}

SafeArrayUnaccessData(pSa);

pVal->vt = VT_ARRAY │ VT_UI1;

pVal->parray = pSa; return S_OK; } ∼中略∼

●プロバイダのビルド

以上で,USB カメラプロバイダの実装がすべて完了しました.

メニューバーの「ビルド」→「アクティブな構成の設定」で,

「Win32 Release MinDependency」(リリース版)を選択し,メニ

ューバーの「ビルド」→「リビルド」を実行して,プロバイダ

のビルドをおこなってください.

3 遠隔監視クライアントの作成

前節で作成した USB カメラプロバイダを利用して,遠隔監視

をおこなうクライアントアプリケーションを作成します.

以降,

作成するクライアントアプリケーションを,

「遠隔監視クライア

ント」と呼ぶことにします.

遠隔監視クライアントには以下の機能を実装します.

・ カメラの画像を表示する

・ カメラ画像が変化した場合に,ユーザに知らせる

・ 画像変化の検出感度を変更する

ORiN のクライアントアプリケーションは,いくつかの開発

環境を選択することができます.ここでは,Visual Studio

2003 .NET の Visual Basic .NET を利用します.

●プロジェクトの作成

プロジェクトを新規に作成し,CAO プロバイダを利用したク

ライアントアプリケーションを作成するための環境設定をおこ

ないます.

Visual Studio .NET 2003 を起動し,メニューバーの「ファイル」

→「新規作成」→「プロジェクト」から「Visual Basic プロジェ

クト」→「Windows アプリケーション」を選択して,新しいプ

ロジェクトを作成してください.

次に,メニューバーから「プロジェクト」→「参照の追加」

から COM タブを選択します.コンポーネント名が「CAO 1.0 タ

イプライブラリ」とあるアイテムを選んで,OK ボタンを押し

てください.

●GUIの作成

次はGUI の作成です.

図9 に示すように,ピクチャボックス,

トラックバー,開始/終了ボタンを持つフォームを作成してく

ださい.また,フォームおよび各コントロールの Name プロパ

ティは,表 5 に示すように設定してください.

表 5 GUI のフォーム/コントロール構成

フォーム名/

コントロール名

Name プロパティ

用途

Form frmMain

アプリケーションの

メインウィンドウ

Button btnStart 監視開始ボタン

Button btnStop 監視終了ボタン

PictureBox pctBox

画像表示領域

TrackBar barThreshold

感度調節バー

図9 フォームの作成

●CaoEngineの生成

それでは,遠隔監視クライアントの実装に移りましょう.

(12)

まずは,frmMain.vb のソースコードを開いてください.リス

ト 10 の①に示すように,Imports ステートメントで名前空間の

指定をおこなってください.次にメンバ変数の追加をおこない

ます.②で宣言しているメンバ変数は,カメラプロバイダを利

用するために必要となるオブジェクトのための変数です.

次に,フォームが生成されたときの処理を実装します.フォ

ーム上でダブルクリックすると frmMain_Load メソッドが生成

されるので,リスト 10 のように実装してください.

③では,CaoEngine を生成し,CaoWorkspace の取得をおこな

います.クライアントアプリケーションで ORiN を利用する場

合は,このように,CaoEngine と CaoWorkspace を必ず生成する

必要があります.

●プロバイダへの接続

USB カメラプロバイダへの接続処理を実装します.この処理

は,開始ボタンが押されたときにおこなわれるようにします.

フ ォ ー ム 上 の 開 始 ボ タ ン を ダ ブ ル ク リ ッ ク す る と ,

btnStart_Click メソッドが生成されます.

リスト 10 のように実装

してください.

④では,

まず CaoWorkspace の AddController メソッドで,CAO

プロバイダへの接続をおこないます.このメソッドの引数は,

先頭からコントローラ名,プロバイダ名,マシン名,パラメー

タとなっています.そして戻り値として,CaoController オブジ

ェクトを返します.

クライアントアプリケーションが CAO プロバイダからのイ

ベントを取得するには,AddHandler キーワードを使用してイベ

ントハンドラを取得する必要があります.

さらに,生成した CaoController オブジェクトの AddFile メソ

ッドと AddVariable メソッドを呼び出し,CaoFile オブジェクト

と CaoVariable オブジェクトを生成します.

●プロバイダの解放

上で取得した CaoController や CaoFile を解放する処理を実装

します.

まず,CaoFile や,CaoVariable を解放するためには,リスト

10 の⑤に示すように,以下の手順でおこないます.

・ 上位のオブジェクト(今回の場合は CaoController)のコレク

ションから,削除する

・ メモリを解放する

・ Nothing を代入する

CaoController の解放も基本的には同様ですが,イベントハン

ドラを登録している場合は,⑥のように RemoveHandler キーワ

ードを利用して,

登録したメソッドを削除する必要があります.

この解放処理をおこなうメソッドを releaseCAO とし,終了ボ

タンが押されたときに実行されるようにします.フォーム上の

終了ボタンをダブルクリックするとbtnStop_Clickメソッドが生

成されるので,このメソッドから releaseCAO メソッドを呼び出

すようにしてください.

●画像の取得

USB カメラプロバイダから画像を取得する処理を実装しま

す.リスト 10 に示す setPicture メソッドを実装してください.

USB カメラプロバイダから画像を取得するには,⑦のように

m_filePicture の Value プロパティを取得するだけで OK です.

●イベントの受付

先ほど AddHandler で登録したイベントハンドラの実装をお

こないます.リスト 10 に示す m_ctrlCamera_OnMessage メソッ

ドを実装してください.CAO プロバイダがイベントを通知する

と,この登録したメソッドが呼び出されます.

ここでは,イベントを受け取ると,setPicture メソッドを呼び

出し,ピクチャボックスに画像を表示させます.

●感度の設定

画像変化の検出感度を設定する処理を実装します.この処理

は,トラックバーをスクロールさせたときに実行されるように

しましょう.フォーム上のトラックバーをダブルクリックする

と,barThreshold_Scroll メソッドが生成されるので,リスト 10

のように実装してください.

⑧では,トラックバーの現在値を CaoVariable の Value プロパ

ティに設定しています.これにより,USB カメラプロバイダ側

の CaoProvVariable に,トラックバーの値が渡されます.

リスト

10 frmMain.vb

Imports System.IO Imports System.Text …① Imports CAOLib '遠隔監視アプリケーションメインクラス Public Class frmMain

Inherits System.Windows.Forms.Form

∼中略∼ " Windows フォーム デザイナで生成されたコード "

' CAO エンジン

Private m_caoEng As CaoEngine

' CAO ワークスペース

Private m_caoWS As CaoWorkspace

' USB カメラの CAO コントローラ …②

Private WithEvents m_ctrlCamera As CaoController

' カメラ画像の CAO ファイル

Private m_filePicture As CaoFile

' カメラの感度設定 CAO 変数

Private m_varThreshold As CaoVariable ' 画像のバイナリデータ

Private m_bArray() As Byte 'アプリケーションの初期化をおこなう

Private Sub frmMain_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Try

'CAO エンジンと CAO ワークスペースの作成

m_caoEng = New CaoEngine …③ m_caoWS = m_caoEng.Workspaces.Item(0) btnStart.Enabled = True

btnStop.Enabled = False Catch ex As Exception

MsgBox("初期化処理に失敗しました" & vbCrLf & ex.Message) Me.Close()

End Try End Sub

(13)

'カメラプロバイダに接続をおこない画像計測を開始する Private Sub btnStart_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStart.Click Try ' USB カメラプロバイダへの接続 m_ctrlCamera = m_caoWS.AddController( _ "camera", "CaoProv.Samples.Camera", "", "") ' イベントハンドラの設定 AddHandler m_ctrlCamera.OnMessage, _ …④ AddressOf m_ctrlCamera_OnMessage ' CAO ファイルの取得 m_filePicture = m_ctrlCamera.AddFile("Picture") ' CAO 変数の取得 m_varThreshold = m_ctrlCamera.AddVariable("Threshold") btnStart.Enabled = False btnStop.Enabled = True setPicture() Catch ex As Exception

MsgBox("プロバイダにアクセスできません" & vbCrLf & ex.Message) End Try

End Sub

'画像計測を終了しカメラプロバイダのリソースを解放する Private Sub btnStop_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStop.Click Try

releaseCAO() btnStart.Enabled = True btnStop.Enabled = False Catch ex As Exception

MsgBox("プロバイダを解放できません" & vbCrLf & ex.Message) End Try

End Sub

'取得していた CAO のリソースを解放する Private Sub releaseCAO()

Try

' CAO 変数の解放

If Not m_varThreshold Is Nothing Then

m_ctrlCamera.Variables.Remove(m_varThreshold.Index) System.Runtime.InteropServices.Marshal. _ …⑤ ReleaseComObject(m_varThreshold) m_varThreshold = Nothing End If ' CAO ファイルの解放

If Not m_filePicture Is Nothing Then

m_ctrlCamera.Files.Remove(m_filePicture.Index) System.Runtime.InteropServices.Marshal. _ ReleaseComObject(m_filePicture) m_filePicture = Nothing End If ' CAO コントローラの解放 If Not m_ctrlCamera Is Nothing Then

' イベントハンドラの解放 RemoveHandler m_ctrlCamera.OnMessage, _ …⑥ AddressOf m_ctrlCamera_OnMessage m_caoWS.Controllers.Remove(m_ctrlCamera.Index) System.Runtime.InteropServices.Marshal. _ ReleaseComObject(m_ctrlCamera) m_ctrlCamera = Nothing End If Catch ex As Exception Throw ex End Try End Sub 'カメラプロバイダから画像を取得しピクチャボックスに表示 Private Sub setPicture()

Try

' 画像データの取得

m_bArray = m_filePicture.Value …⑦ ' バイナリデータから MemoryStream オブジェクトを作成する Dim mstreamCur As New MemoryStream(m_bArray)

' ストリームから Image オブジェクトを作成し,ピクチャボックスに表示 pctBox.Image = Image.FromStream(mstreamCur) Catch ex As Exception Throw ex End Try End Sub 'カメラプロバイダからのイベントを受付け画像を表示する

Private Sub m_ctrlCamera_OnMessage(ByVal pICaoMess As CAOLib.CaoMessage) Try

setPicture() Catch ex As Exception

MsgBox("失敗しました" & vbCrLf & ex.Message) releaseCAO() btnStart.Enabled = True btnStop.Enabled = False End Try End Sub 'カメラの検出感度を変更する

Private Sub barThreshold_Scroll(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles barThreshold.Scroll Try ' 感度の設定 …⑧ m_varThreshold.Value = barThreshold.Value Catch ex As Exception End Try End Sub End Class

4 動作の確認

作成した USB カメラプロバイダと遠隔監視クライアントの

動作確認をおこないます.

●USBカメラプロバイダとの接続

遠隔監視クライアントと USB カメラプロバイダ間の接続を

確認します.先ほど作成した遠隔監視クライアントのプロジェ

クトが読み込まれた状態で,Visual Basic のメニューバーの「デ

バッグ」→「開始」を選択し,プログラムを起動してください.

開始ボタンを押下すると,カメラプロバイダへの接続がおこ

なわれ,続けて setPicture メソッドが呼び出されるので,図 10

に示すように,

ピクチャボックスに USB カメラから取得した画

像が表示されます.

アプリケーションの動作が重たくなるようであれば,USB カ

メ ラ プ ロ バ イ ダ の , リ ス ト 3(StdAfx.h) の ② に 示 す

CAOP_TIMER_INTERVAL マクロの値を,100 などの大きな値

に変更し,試してみてください.

●イベント通知

遠隔監視クライアントの起動(開始ボタン押下)中に,カメラ

の前で手を振ったりしてみてください.USB カメラプロバイダ

側で画像が変化したことを検知して,クライアントにイベント

が通知され,表示画像が切り替わります.

●感度設定の確認

イベント通知のときと同様に,今度はトラックバーを左右に

スクロールさせてみてください.トラックバーが左にいくほど

画像変化の感度がよくなり,小さな変化でもイベントが発生す

るようになります.逆に,トラックバーを右にすると,感度が

悪くなり,画像が大きく変化しないと,イベントは発生しなく

なります.

(14)

●遠隔監視

ORiN では,DCOM(Distributed Component Object Model)や,

ORiN 独自のインターネット対応プロトコル CAP を利用するこ

とで,ネットワーク経由で簡単に CAO プロバイダにアクセス

することができます.これらの機能を用いれば,ネットワーク

に接続された,別の PC 上に接続されている USB カメラからの

情報を取得することができます

8

具体的に,

クライアントアプリケーションからDCOMやCAP

を利用するには,リスト 11 のようにします.CAO プロバイダ

に接続する際のAddController メソッドの引数に,

DCOM やCAP

の指定をおこなうだけで OK です.

リスト

11 DCOM,CAPを利用したプロバイダへの接続

' DCOM を利用して,USB カメラプロバイダへの接続 ' HOSTNAME:CAO プロバイダの動作している PC のホスト名 m_ctrlCamera = m_caoWS.AddController( _

"camera", "CaoProv.Samples.Camera", "HOSTNAME", "") ' CAP プロバイダを利用して,USB カメラプロバイダへの接続 ' HOSTNAME:Web サーバの動作している PC のホスト名 m_ctrlCamera = m_caoWS.AddController( _ "camera", "CaoProv.CAP", "", _ "Provider=CaoProv.Samples.Camera,Server=HOSTNAME")

図10 実行中のクライアント画面

5 システム拡張の可能性

今回作成した遠隔監視システムはシンプルなものですが,本

システムをベースに様々な機能を拡張することによって,より

高度な機能を持ったシステムに応用することができます.例え

ば,遠隔監視クライアントの機能として,異常検知時のメール

送信機能,ログ機能などを付加することで,システムがより実

用的になります.紙面の都合上,紹介することはできませんで

したが,この拡張版の遠隔監視クライアントは Web サイトから

ダウンロードできますので,興味のある方はお試し下さい.

その他,図 11 に示すような拡張例が考えられます.

・ DCOM や CAP の技術を利用して,遠隔の複数台の USB

カメラを接続し,それらを一元的に監視する.

・ USB カメラプロバイダと,他の CAO プロバイダとを連携

させる.例えば,USB カメラプロバイダから異変が通知

された場合に,ブザーを鳴らしたり,ランプを点灯させた

り,

さらに,

警備ロボットに異常を知らせたりする,

など.

・ 取得した画像をデータベースに蓄積する.

・ USB カメラプロバイダを拡張し,より高度な画像認識処

理や,ストリーミング再生機能を実装する.

ORiN を利用することの利点は,CAO プロバイダが用意され

ていれば,デバイスの詳細を知らなくても,ORiN の共通のイ

ンタフェースを用いて,アプリケーションを容易に作成できる

ようになることです.ORiN2 SDK には標準でいくつかの CAO

プロバイダが既に用意されていますので,これらを利用してア

プリケーションを作成あるいは拡張させることもできます.ま

た,複数の CAO プロバイダを,クライアント側で統合的に監

視,制御することができることもあげられます.

上記に示したシステム拡張案も,ORiN を利用することで,

実現が容易になります.

●まとめ

以上,駆け足で ORiN プログラミングの解説をおこなってき

ましたが,いかがだったでしょうか?ここで紹介した内容は,

まだ ORiN の基本的な部分だけです.本特集を機会に,少しで

も ORiN に興味を持っていただければ幸いです.

図 11 システムの拡張

8

DCOMやCAPを利用するには,別途,環境設定をおこなう必要が

あります.設定方法については,

ORiN2 SDKに附属の「ORiN2プ

ログラミングガイド」を参照して下さい.

参照

関連したドキュメント

タッチ センシング cypress.com/touch USB コントローラー cypress.com/usb ワイヤレス cypress.com/wireless. PSoC

Macdonald in [11], and a proof of Macdonald’s identities for infinite families of root systems was given by D..

Bluetooth® Low Energy プロトコルスタック GUI ツールは、Microsoft Visual Studio 2012 でビルドされた C++アプリケーションです。GUI

The surrounding structure of Fe 2+ was examined using light, X-ray absorption spectroscopy, and molecular dynamics simulation.. The results suggest that Fe 2+ ions in Na 2

LC06111TMT Battery Protection Controller with Integrated MOSFET, 1-Cell Lithium-Ion LC05711ARA Battery Protection Controller with Integrated MOSFET, 1-Cell Lithium-Ion

Buyer purchase or use SCILLC products for any such unintended or unauthorized application, Buyer shall indemnify and hold SCILLC and its officers, employees, subsidiaries,

ESMPRO/ServerAgent for GuestOS Ver1.3(Windows/Linux) 1 ライセンス Windows / Linux のゲスト OS 上で動作するゲスト OS 監視 Agent ソフトウェア製品. UL1657-302

When the device is operating as a sink and it receives a Hard Reset or a Power Role Swap, the automatic discharge circuitry and SNK output will be disabled by the host processor