ユーザーフィルタの作成
注意 1:ユーザーフィルタの作成にはC/C++プログラミングのスキルが必要です。
注意 2:独自のC/C++コードでアプリケーション全体を簡単にクラッシュさせることができます。それに対する保護はできません。
目次
はじめに
ユーザーフィルタはC/C++で書かれ、高度なユーザーがAurora Vision Studioの機能をほぼ制約なく拡張できるようにします。 これらは新しいカメラモデルをサポートしたり、外部デバイスと通信したり、アプリケーション固有の画像処理操作を追加したりするために使用できます。
前提条件
ユーザーフィルタを作成するには以下が必要です:
- インストールされたMicrosoft Visual Studio 2015/2017/2019 for C++、Express Edition(無料)またはそれ以降のエディション、
- システムに環境変数
AVS_PROFESSIONAL_SDK5_3
(エディションによる; この変数の適切な値はAurora Vision Studioのインストール中に設定されます)、 - C/C++プログラミングスキル。
ユーザーフィルタはユーザーフィルタライブラリにグループ化されます。各ユーザーフィルタライブラリはMicrosoft Visual Studioを使用してビルドされた単一の.dllファイルです。 これにはAurora Vision Studioで開発されたプログラムで使用できる1つ以上のフィルタが含まれています。
ユーザーフィルタライブラリの場所
ユーザーフィルタライブラリには2つのタイプがあります:
- グローバル – 一度作成またはAurora Vision Studioにインポートされると、すべてのプロジェクトで使用できます。 これらのライブラリのフィルタはツールボックスのLibrariesタブで表示されます。
- ローカル – 特定のAurora Vision Studioプロジェクトに属しています。 これらのライブラリのフィルタは、ライブラリが追加されたプロジェクトでのみ表示されます。
グローバルユーザーフィルタライブラリのソリューション(.slnファイル)は、ハードディスク上の任意の場所に配置できますが、デフォルトかつ推奨される場所はDocuments\Aurora Vision Studio 5.3 Professional\Sources\UserFilters
です(パスはAurora Vision Studioのバージョンによって異なります)。ビルドされたMicrosoft Visual Studioプロジェクトの初期設定において、このパスは変更してはいけません。なぜならAurora Vision Studioはこのディレクトリを.dllファイルの変更を監視するために使用しているからです。
グローバルユーザーフィルタの.dllファイルは、Microsoft Visual Studioを使用してビルドされ、それが含まれているDocuments\Aurora Vision Studio 5.3 Professional\Filters\x64
に配置されている必要があります(この場合もパスはバージョンおよびエディションに依存します)。Aurora Vision Executor用のグローバルユーザーフィルタの.dllファイルは、Documents\Aurora Vision Studio 5.3 Runtime\Filters\x64
に配置する必要があります
(再び、正確なパスはバージョンとエディションに依存します)。ローカルユーザーフィルタの.dllファイルは、User Filterのプロパティで構成されたパスに配置する必要があります。
このパスは、Project Explorerでユーザーフィルタライブラリのプロパティを編集して変更できます。
ローカル ユーザー フィルター ライブラリは、Aurora Vision Studio で開発されたプロジェクトの一部であり、ソース ファイルと出力 .dll ファイルの両方をハード ドライブ上のどこにでも配置できます。 [プロジェクト エクスプローラー] タスク パネルを使用して、ユーザー フィルター ライブラリの出力 .dll および Microsoft Visual Studio ソリューション ファイルへのパスを確認または変更します。 出力 .dll ファイルの変更は、ファイルの場所に関係なく、Aurora Vision Studio によって監視されます。 ローカル ユーザー フィルター ライブラリ ソース (および出力 .dll) を、開発されたプロジェクトの場所 (たとえば、プロジェクトのサブディレクトリ) に相対的に保持することをお勧めします。
新しいグローバルユーザーフィルタライブラリの追加
新しいユーザーフィルタライブラリを追加するには、ファイル » グローバルユーザーフィルタの追加/変更 » 新しいグローバルユーザーフィルタライブラリ... から始めます。
もう一つのオプションは、Project ExplorerパネルからCreate New Local User Filter Libraryボタンを使用することです。
ダイアログボックスが表示され、そこで以下を選択する必要があります:
- 新しいライブラリの名前,
- ライブラリのタイプ: ローカル(現在のプロジェクトでのみ使用可能)またはグローバル(すべてのプロジェクトで使用可能),
- ソリューションディレクトリの場所,
- Microsoft Visual Studioのバージョン(2015、2017、または2019),
- Microsoft Visual Studioが自動的に開かれるべきかどうか,
- 例のユーザーフィルタのコードがソリューションに追加されるべきかどうか(ユーザーフィルタのプログラミングに経験が少ないユーザーには良いアイディアです)。
Microsoft Visual Studioを開くように選択した場合、このソリューションをすぐにビルドできます。新しいフィルタライブラリが作成され、数秒後にAurora Vision Studioにロードされます。 Aurora Vision Studioに切り替えて新しいフィルタを以下で見ることができます:
- Librariesタブの適切なカテゴリ(グローバルユーザーフィルタ、Librariesタブのカテゴリはフィルタコードで設定されたカテゴリに基づきます)
- Project Explorer(ローカルユーザーフィルタ)
Microsoft Visual StudioとAurora Vision Studioの両方で同時に作業できます。C++コードがビルドされるたびに、フィルタが再読み込まれます。変更点を確認するには、Aurora Vision Studioでプログラムを再実行してください。
上記の場所にフィルタが表示されない場合は、それらがAurora Vision Studioのアーキテクチャと互換性のあるアーキテクチャで正しくコンパイルされているかどうかを確認してください: x86(Win32)またはx64。
新しいローカルユーザーフィルタライブラリの追加
新しいローカルユーザーフィルタを追加するには、Project Explorerパネルの「Create New Local User Filter Library..」ボタンを使用してください。下の画像のように:
ユーザーフィルタの開発
ユーザーフィルタプロジェクトの構成
ユーザーフィルタプロジェクトファイル(.slnおよび.vcproj)は、新しいユーザーフィルタライブラリの追加中にAurora Vision Studioによって生成されます。
ユーザーフィルタプロジェクトの設定は、Aurora Vision Studio SDKのpropsサブディレクトリ(環境変数AVS_PROFESSIONAL_SDK5_3
)にある.propsファイルにまとめられています。通常は
C:\Program Files\Aurora Vision\Aurora Vision Studio 5.3 Professional\SDK\props
です。
既存のプロジェクトを有効なユーザーフィルタライブラリに設定する場合は、適切な.propsファイルを使用してください(v140接尾辞のファイルはMicrosoft Visual Studio 2015用に、v141は2017用に、v142は2019用にそれぞれ用意されています)。
基本的なユーザーフィルタの例
以下の例は、基本的なユーザーフィルタの全体のソースコードを示しています。この例では、フィルタが8ビットの画像に対して単純な閾値処理を行っています。
#include "UserFilter.h" #include "AVL_Lite.h" #include "UserFilterLibrary.hxx" namespace avs { // Example image processing filter class CustomThreshold : public UserFilter { private: // Non-trivial outputs must be defined as a filed to retain data after filter execution. avl::Image outImage; public: // Defines the inputs, the outputs and the filter metadata void Define() override { SetName (L"CustomThreshold"); SetCategory (L"Image::Image Thresholding"); SetImage (L"CustomThreshold_16.png"); SetImageBig (L"CustomThreshold_48.png"); SetTip (L"Binarizes 8-bit images"); // Name Type Default Tool-tip AddInput (L"inImage", L"Image", L"", L"Input image" ); AddInput (L"inThreshold", L"Integer<0, 255>", L"128", L"Threshold value"); AddOutput (L"outImage", L"Image", L"Output image" ); } // Computes output from input data int Invoke() override { // Get data from the inputs avl::Image inImage; int inThreshold; ReadInput(L"inImage", inImage); ReadInput(L"inThreshold", inThreshold); if (inImage.Type() != avl::PlainType::UInt8) throw atl::DomainError("Only uint8 pixel type are supported."); // Get image properties int height = inImage.Height(); // Prepare output image in this same format as input outImage.Reset(inImage, atl::NIL); // Enumerate each row for (int y = 0; y < height; ++y) { // Get row pointers const atl::uint8* p = inImage.RowBegin<atl::uint8>(y); const atl::uint8* e = inImage.RowEnd<atl::uint8>(y); atl::uint8* q = outImage.RowBegin<atl::uint8>(y); // Loop over the pixel components while (p < e) { (*q++) = (*p++) < inThreshold ? 0 : 255; } } // Set output data WriteOutput(L"outImage", outImage); // Continue program return INVOKE_NORMAL; } }; // Builds the filter factory class RegisterUserObjects { public: RegisterUserObjects() { // Remember to register every filter exported by the user filter library RegisterFilter(CreateInstance<CustomThreshold>); } }; static RegisterUserObjects registerUserObjects; }
ユーザーフィルタクラスの構造
ユーザーフィルタは、UserFilter.hヘッダファイルで定義されたUserFilterクラスから派生したクラスです。状態を持たないフィルタを作成する場合、 次の2つのメソッドをオーバーライドする必要があります:
- Define – フィルタのインターフェースを定義します。これにはフィルタの名前、カテゴリ、入力および出力が含まれます。
- Invoke – 入力を出力に変換するルーチンを定義します。
状態を持つフィルタ(前回の呼び出しからの情報を保存する)を作成する場合、クラスにはいくつかのデータフィールドがあり、 さらに2つの追加のメソッドをオーバーライドする必要があります:
- Init – 状態変数を初期化し、フィルタインスタンスを親とするTaskの開始時に呼び出されます。フィルタインスタンスのライフタイム中に複数回呼び出される場合があります。常にベースタイプのInvoke()メソッドを呼び出すことを忘れないでください。
- Stop – 状態変数を非初期化し、外部およびI/Oリソース(ファイルハンドルやネットワーク接続など)を解放します。フィルタのインスタンスを親とするTaskの終了時に呼び出され、(すべてのInit呼び出しに対応するように)フィルタインスタンスに影響を与える可能性はありません。
- Release – 出力変数のメモリを解放します。メモリの解放がマークされたTaskマクロフィルタの終了時に呼び出されます。
ユーザーフィルタクラスが作成されたら、登録する必要があります。これはサンプルユーザーフィルタコードの一番下で定義されたRegisterUserObjects関数で行われます。 手動で呼び出す必要はありません。Aurora Vision Studioは.dllファイルからフィルタを読み込む際にこれを呼び出します。
Defineメソッドの構造
Defineメソッドを使用して、フィルタの名前、カテゴリ、イメージ(フィルタのアイコンとして使用される)およびツールチップを設定します。 これらはすべて適切なSet...メソッドを使用して設定できます。
Defineメソッドには、フィルタの外部インターフェースの定義も含まれるべきであり、これは入力、出力、および診断出力を意味します。 外部インターフェースはAddInput、AddOutput、およびAddDiagnosticOutputメソッドを使用して定義する必要があります。 これらのメソッドを使用して、フィルタの各入力/出力の名前、タイプ、およびツールチップを定義できます。入力にはデフォルト値の定義も可能です。
Aurora Vision Studioはポートに対して追加の属性セットを使用します。ポートに属性を適用するにはAddAttributeメソッドを使用します。例:
AddAttribute(L"ArraySync", L"inA inB");
属性の一覧:
属性名 | 説明 | 例 | コメント |
---|---|---|---|
ArraySync | 同期されたポートのセットを定義します。 |
L"inA inB"
|
inAとinBの配列が同じ数の要素を必要とすることを通知します。 |
UserLevel | フィルタへのユーザーレベルアクセスを定義します。 |
L"Advanced"
|
AdvancedレベルのユーザーだけがこのフィルタをLibrariesタブで見つけることができます。 |
UsageTips | 追加のドキュメンテーションテキストを定義します。 |
L"このフィルタは線を作成するために使用してください。"
|
このフィルタが必要な場所の指示です。 |
AllowedSingleton | フィルタは入力でシングルトン接続を受け入れることができます |
L"inA"
|
ユーザーはArrayタイプのinAに単一の値を接続できます。 |
FilterGroup | フィルタグループの要素を定義します。 |
L"FilterName<VariantName> default ## グループの説明"
|
デフォルトの要素VariantNameを持つFilterNameを作成します。 "フィルタグループの定義"で詳細な説明があります。 |
Tags | このフィルタの代替名を定義します。 |
L"DrawText DrawString PutText"
|
ユーザーが「DrawText」と入力すると、このフィルタが結果リストに表示されます。 |
CustomHelpUrl | このフィルタの代替URLを定義します。 |
L"http:\\adaptive-vision.com"
|
Program EditorでユーザーがF1を押すと、代替のヘルプページが開かれます。 |
フィルタグループの定義
複数のフィルタを単一のグループにまとめることができ、非常に似た操作のバリアントを切り替えるためにユーザーに非常に役立ちます。
フィルタグループを作成するには、デフォルトのフィルタに対して属性L"FilterGroup"を定義します。 L"FilterName<VariantName> default ## グループの説明"。 "default"の単語に注意してください。 "##"の後のテキストは、グループ全体のツールチップを定義します。
デフォルトのフィルタが定義されている場合、別のフィルタを追加するには、L"FilterGroup"を使用してL"FilterName<NextVariant>"というパラメータを追加できます。
使用例:
// Default filter FindCircle -> Find: Circle AddAttribute(L"FilterGroup", L"Find<Circle> default ## Finds an object on the image"); ... // Second variant FindRectangle -> Find: Rectangle AddAttribute(L"FilterGroup", L"Find<Rectangle>"); ... // Third variant FindPolygon -> Find: Polygon AddAttribute(L"FilterGroup", L"Find<Polygon>"); ...
その結果、フィルタグループ「Find」が作成され、3つのバリアント(Circle、Rectangle、Polygon)が含まれます。
カスタムユーザーフィルタアイコンの使用
SetImage
およびSetImageBig
メソッドを使用して、ユーザーはユーザーフィルタにカスタムアイコンを割り当てることができます。フィルタのアイコンは、
出力のユーザーフィルタDLLファイルと同じディレクトリに配置する必要があります。
アイコンには4つのタイプがあります:
- 小さいアイコン - サイズが16x16ピクセルのアイコンで、Librariesタブで使用され、
SetImage
によって設定されます。名前は「_16」で終わる必要があります - 中アイコン - サイズが24x24ピクセルのアイコンで、Bigアイコンから自動的に作成されます
- 大きなアイコン - サイズが48x48ピクセルのアイコンで、
SetImageBig
によって設定され、名前は「_48」で終わる必要があります - 説明アイコン - グループからのフィルタ選択で使用されるサイズが72x72のアイコンで、
SetImageBig
から「_48」を「_D」に置換して名前が生成されます。 指定されたSetImageBig
が「custom_48.png」の場合、名前「custom_D.png」が生成されます。
Invokeメソッドの構造
Invokeメソッドには3つの要素が含まれる必要があります:
- 入力からデータを読み取る
フィルタの入力に渡された値を読み取るには、ReadInputメソッドを使用します。これは、 Aurora Vision Studioのデータ型をすべてサポートするテンプレートメソッドです。 ReadInputメソッドは、2番目のパラメータを使用して値を(参照によって)返します。
- 入力データから出力データを計算する
これが中心部分です。ここでは任意の計算ができます
- データを出力に書き込む
読み取りと同様に、フィルタの出力に対して値を設定するためには、WriteOutputメソッドを使用する必要があります。
(すなわちint、avl::Point2D、avl::Rectangle2D)を含まないデータ型は、単にローカル変数をWriteOutputメソッドに渡して返すことができます。
class MyOwnFilter : public UserFilter { int Invoke() { int length; // ... computing the length value... WriteOutput("outLength", length); } // ... }
Image、Region、ByteBufferなどの非自明なデータ型は、フィルタクラスのフィールドとして定義する必要があります。
この方法には2つの利点があります:
- 各フィルタ実行で新しいオブジェクトを作成する際のパフォーマンスオーバーヘッドを削減します。
- ブロブを含む型がフィルタ実行後に解放されないようにします。
わかりやすさのために、すべてのフィルタ変数をクラスメンバとして定義するのが良い習慣です。
class MyOwnFilter : public UserFilter { private: // Non-trivial type data avl::Image image; int Invoke() { // ... computing image ... WriteOutput("outImage", image); } // ... }
Invokeは、次のいずれかの値を返す必要があります:
- INVOKE_ERROR - 何かがうまくいかず、プログラムを継続できない場合。
- INVOKE_NORMAL - すべてが正常で、フィルタを再度呼び出すことができる場合。
- INVOKE_LOOP - すべてが正常で、フィルタがさらに反復を要求する場合。
- INVOKE_END - すべてが正常で、フィルタが現在のループを停止するよう要求する場合。
例えば、フィルタReadVideoは新しいフレームが正常に読み取られるたびにINVOKE_LOOPを返し、終了時にINVOKE_ENDを返します。INVOKE_NORMALは、現在のループの継続または終了に影響を与えないフィルタ(例:ThresholdImage)によって返されます。
すべてのフィルタの出力は、フィルタがステータスを返す前にWriteOutputで割り当てられるべきです。割り当てが不足すると、複雑なプログラム構造でランダムなデータアクセスが発生する可能性があります。INVOKE_ENDの場合、フィルタは出力値をフィルタの最後の反復として設定する必要があります。
エラーの場合、例外もスローできます。入力データに関連する問題を通知するためには、atl::DomainErrorを使用します。すべてのハードウェアの問題はatl::IoErrorを使用して通知する必要があります。詳細については、エラー処理を参照してください。
配列の使用
ユーザーフィルタは、単一のデータオブジェクトだけでなく、それらの配列も処理できます。Aurora Vision Studioでは、配列はArrayサフィックスを持つデータ型で表されます(例:IntegerArray、ImageArray、RegionArrayArray)。多次元配列には複数のArrayサフィックスが使用されます。
ユーザーフィルタのC++コードでは、オブジェクトを配列に格納するためにatl::Array<T>コンテナが使用されます:
atl::Array< int > integers;
atl::Array< avl::Image > images;
atl::Array< atl::Array< avl::Region > > regions2Dim;
atlおよびavl名前空間の型に関する詳細は、Aurora Vision Libraryのドキュメントを参照してください。
診断モードの実行と診断出力
ユーザーフィルタには診断出力があります。診断出力は、Aurora Vision Studioでプログラムを開発する際に役立ちます。
この機能の主な目的は、ユーザーがデータプレビューで診断データを表示できるようにすることですが、診断データはデータフローに参加し、他のフィルタの入力に接続できます。このタイプの接続は診断接続と呼ばれ、宛先フィルタがプログラムの実行の診断モードでのみ呼び出されるようにします。
プログラムがNon-Diagnosticモードで実行されている場合、診断出力の値は(パフォーマンスのために)フィルタによって計算されないべきです。 ユーザーフィルタでは、診断出力のために生成されたデータの条件付き計算にIsDiagnosticMode()メソッドを使用する必要があります。 メソッドがTrueを返す場合、実行はDiagnosticモードであり、診断出力の値を計算する必要があります。それ以外の場合、実行はNon-Diagnosticモードであり、フィルタはそのような値を計算してはいけません。
フィルタ作業のキャンセル
Aurora Vision Studioでは、各フィルタの実行中に時間のかかる計算を停止できるようになっています。このオプションを使用するには、IsWorkCancelled()関数を使用できます。 関数がTrueを返す場合、ユーザーが「停止」ボタンを押したため、長い計算を終了する必要があります。
依存するDLLの使用
ユーザーフィルタライブラリは、多くの場合、サードパーティライブラリ(例:特定のハードウェアのAPIのラッパー)として作成されます。これらのライブラリは通常、DLLファイルの形式で提供されます。 ユーザーフィルタが正しく機能するためには、他のDLLファイルが実行時にアクセス可能なディスクの場所にある必要があります。そうでないと、ユーザーはエラーコード126、「指定されたモジュールが見つかりませんでした」となります。 MSDNドキュメントでは、記事Dynamic-Link Library Search Orderで可能なオプションを指定しています。 Aurora Vision Studioのユーザーフィルタの観点からは、ほとんどのカメラメーカーがこの方法に従っているため、PATH環境変数を変更することに関連するものが最も一般的です。 ローカルユーザーフィルタの場合、依存するDLLをユーザーフィルタDLLディレクトリと同じディレクトリに追加することも許可されています。
代替として、新しいディレクトリをグローバルユーザーフィルタライブラリに作成することも可能です:
Documents\Aurora Vision Studio 5.3 Runtime\Filters\Deps_x64
。その後、ユーザーフィルタの依存DLLファイルをそのディレクトリに保存できます。
高度なトピック
AVLのフルバージョンの使用
デフォルトでは、ユーザーフィルタはAurora Vision Library Liteライブラリを基にしています。これはAurora Vision Library Professionalの無料版で、'full'エディションのAurora Vision Libraryからデータ型と基本的な機能を含んでいます。 詳細な機能や機能については、Aurora Vision Library LiteおよびAurora Vision Library Professionalのドキュメントを参照してください。
'full' Aurora Vision Libraryのライセンスを購入した場合、Liteエディションの代わりにユーザーフィルタで使用できます。次の手順が必要です:
-
プロジェクトのコンパイラ設定で、追加のインクルードディレクトリ
$(AVL_PATH5_3)\include
を追加します (構成のプロパティ | C/C++ | 一般 | 追加のインクルードディレクトリ)。 -
プロジェクトのリンカ設定で、新しい追加のライブラリディレクトリ
$(AVL_PATH5_3)\lib\$(Platform)
を追加します (構成のプロパティ | リンカ | 一般 | 追加のライブラリディレクトリ)。 -
プロジェクトのリンカ設定で、
AVL_Lite.lib
追加の依存関係をAVL.lib
に置き換えます (構成のプロパティ | リンカ | 入力 | 追加の依存関係)。 -
ソースコードファイルで、
AVL_Lite.h
をAVL.h
に変更します。
ユーザーフィルタからコンソールへのアクセス
InvokeメソッドからAurora Vision Studioのコンソールにメッセージを追加することが可能です。ログメッセージは問題の可視化だけでなく、デバッグにも使用できます。メッセージを追加するには、次のいずれかの関数を使用します:
bool LogInfo (const atl::String& message); bool LogWarning(const atl::String& message); bool LogError (const atl::String& message); bool LogFatal (const atl::String& message);
ジェネリックユーザーフィルタ
ジェネリックフィルタは、処理するデータの型が厳密に定義されていないフィルタです。ジェネリックフィルタは、使用する前にデータ型で具体化する必要があります。 Aurora Vision Studioには多くのジェネリックフィルタが組み込まれています(例:ArraySize)、ユーザーフィルタもジェネリックにすることができます。
ジェネリックユーザーフィルタを作成するには、1つ以上のフィルタのポートをジェネリックとして定義する必要があります。 AddInput メソッドの呼び出しで、第2パラメータ(データ型)には < T > を含める必要があります。
使用例:
AddInput ("inArray", "<T>Array", "", "Input array"); AddInput ("inObject", "<T>", "", "Object of any type");
ユーザーフィルタの Invoke メソッドでは、GetTypeParam 関数を使用してフィルタが具体化されたデータ型を解決することができます。 データ型がわかったら、if-else ステートメントを使用してデータを適切に処理できます。 以下はその例です。
atl::String type = GetTypeParam(); // Getting type of generic instantiation as string. int arrayByteSize = -1; if (type == "Integer") { atl::Array< int > ints = GetInputArray< int >("inArray"); arrayByteSize = ints.Size() * sizeof(int); } else if (type == "Image") { atl::Array< avs::Image > images = GetInputArray< avs::Image >("inArray"); arrayByteSize = 0; for (int i = 0; i < images.Size(); ++i) arrayByteSize += images[i].pitch * images[i].height; }
ユーザーフィルタでユーザータイプの作成
ユーザーフィルタを作成するときに、プロジェクトにAVTYPEファイルを追加して、ユーザータイプの説明を記述します。 このファイルは、プログラムでユーザータイプを作成するのと同じ形式で型の説明を含んでいる必要があります。 ユーザータイプの作成を参照してください。
サンプルのユーザータイプの説明ファイル:
enum PartType { Nut Bolt Screw Hook Fastener } struct Part { String Name Real Width Real Height Real Tolerance }
C++ コードでは、同じフィールドの型、名前、順序を持つ構造体/列挙型を宣言します。 列挙型を作成すると、プロジェクトでこの型の使用を即座に開始できます。 構造体の場合は、シリアル化と逆シリアル化のための ReadData 関数と WriteData 関数のオーバーライドを提供する必要があります。
これらの関数では、型定義ファイルで宣言したのと同じ順序で構造体のすべてのフィールドをシリアル化/逆シリアル化する必要があります。
ソース コード内の前の例の構造 Part をサポートするには、以下を追加する必要があります。
構造宣言:
struct Part { atl::String Name; float Width; float Height; float Tolerance; };
構造体の逆シリアル化関数:
void ReadData(atl::BinaryReader& reader, Part& outPart)
{
ReadData(reader, outPart.Name);
ReadData(reader, outPart.Width);
ReadData(reader, outPart.Height);
ReadData(reader, outPart.Tolerance);
}
構造シリアル化関数:
void WriteData(atl::BinaryWriter& writer, const Part& inValue) { WriteData(writer, inValue.Name); WriteData(writer, inValue.Width); WriteData(writer, inValue.Height); WriteData(writer, inValue.Tolerance); }
列挙型宣言:
enum PartType
{
Nut,
Bolt,
Screw,
Hook,
Fastener
};
列挙型のカスタムシリアライズ/デシリアライズは必要ありません。
ユーザータイプの定義が含まれたファイルは登録が必要です。これは、ユーザーフィルターコードの一番下に定義されている RegisterUserObjects クラスコンストラクタで行います。 そこにファイルを RegisterTypeDefinitionFile("fileName.avtype") として登録する必要があります。 ファイル名は、タイプ定義ファイルへのパスです。パスはユーザーフィルターの DLL ファイルに対する絶対または相対のパスである必要があります。
ユーザーフィルターライブラリで定義されたタイプは、このライブラリ内およびプロジェクトの他のモジュールで使用できます。 同じタイプを複数のユーザーフィルターライブラリで使用する場合は、各ユーザーフィルターライブラリでこれらのタイプを宣言する必要があります。
"User Filter With User Defined Types" というサンプルプログラムは、ユーザーフィルターでのユーザータイプの使用例を示しています。
トラブルシューティングと例
Aurora Vision Studioの新しいバージョンへのユーザーフィルターのアップグレード
User Filters をより新しいバージョンの Aurora Vision にアップグレードする場合は、お気に入りのテキストエディタ(例: メモ帳)でユーザーフィルターの vcxproj ファイルを手動で編集する必要があります。編集を行う前に Microsoft Visual Studio でソリューションファイルを閉じることを確認してください。
このファイル内で AVS_PROFESSIONAL_SDKxx(xx は現在の Aurora Vision のバージョン)のすべての出現箇所を AVS_PROFESSIONAL_SDK5_3
に変更し、変更内容を保存してプロジェクトを再構築します。
ビルドが成功したら、新しいバージョンの Aurora Vision でユーザーフィルターライブラリを使用できるようになります。
コード内で関数を使用している場合にコンパイル時にエラーが発生する可能性があります。その場合は、ドキュメントとリリースノートを参照して、その関数が現在のバージョンでどのように変更されたかを確認してください。
注意事項
- PDB ファイルがロックされている問題が発生した場合、Windows タスク マネージャーを使用して mspdbsrv.exe プロセスを終了してください。これは Microsoft Visual Studio での既知の問題です。代わりに Release 構成を使用することもできます。
- ユーザーフィルターはデバッグ可能です。詳細は ユーザーフィルターのデバッグ を参照してください。
- 一つのバージョンの Aurora Vision Studio で SDK を使用してビルドされたユーザーフィルターライブラリ(.dll ファイル)は、他のバージョンと常に互換性があるわけではありません。異なるバージョンでユーザーフィルターライブラリを使用する場合は、ライブラリを再ビルドする必要があるかもしれません。
- Aurora Vision Library('full' edition)をユーザーフィルターで使用する場合、Aurora Vision Library と Aurora Vision Studio は同じバージョンである必要があります。
- ユーザーフィルターライブラリのソリューションには、例題フィルターが含まれることがあります。独自のフィルターの書き方に不慣れであれば、これらの例題を研究するのが良いでしょう。
- ライブラリを他のコンピュータユニットで使用するには、リリース構成でのみライブラリをコンパイルできます。デバッグ構成ではできません。
例: IDS カメラからの画像取得
ユーザーフィルターの最も一般的な使用例の一つは、標準の GenICam インダストリアル インターフェースを(完全には)サポートしていないハードウェアとの通信です。Aurora Vision Studio には、IDS 社のカメラからの画像取得用のユーザーフィルターの準備が整っています。この例は、特定のハードウェアのサポートを実装する際の参考として使用できます。
ソースコードは以下のディレクトリにあります:
%PUBLIC%\Documents\Aurora Vision Studio 5.3 Professional\Sources\UserFilters\IDS
以下は、コード内で最も重要なクラスの一覧です:
- CameraManager – IDS デバイス ドライバーとのすべての接続を管理するシングルトン。
- IDSCamera – 1 つの画像取得ストリームを管理するクラス。同じデバイスに接続された複数のフィルターで共有されます。
- IDS_BaseClass – すべてのユーザーフィルター クラスの共通の基本クラス。
- IDS_GrabImage, IDS_GrabImage_WithTimeout, IDS_StartAcquisition – 個々のユーザーフィルターのクラス。
CameraManager のコンストラクタは、適切なカメラベンダーの dll ファイルがシステムに存在するかどうかを確認します。ユーザーフィルター プロジェクトは、遅延読み込み DLL オプションをオンにしてライブラリをロードし、ファイルが存在しない場合に正しく処理するようにしています。
要件: IDS カメラ用のユーザーフィルターを使用するには、IDS Software Suite をインストールする必要があります。IDS Software Suite は IDS のウェブページ からダウンロードできます。
プロジェクトが適切な Win32/x64 構成でビルドされたら、(グローバルの)ユーザーフィルターが Aurora Vision Studio に自動的にロードされます。これらはツールボックスの Libraries タブ、「User Filters」セクションに表示されます。
例: Aurora Vision Studio で PCL ライブラリを使用する
この例では、ユーザーフィルターで PCL を使用する方法を示しています。
ソースコードは以下のディレクトリにあります:
%PUBLIC%\Documents\Aurora Vision Studio 5.3 Professional\Sources\UserFilters\PCL
この例を実行するには、PCL ライブラリがインストールされている必要があり、システムの PCL_ROOT が定義されている必要があります。