コンテンツにスキップ

fglib5#

fglib5 ライブラリは、コンピューター内のフレームグラバーの初期化と制御を管理します。

ライブラリを使用するには、インクルードファイル basler_fg.h をソースコードに追加する必要があります。

#include <basler_fg.h>

さらに、 fglib5.lib をMicrosoft Visual Studioプロジェクトに追加するか、 libfglib5.so を Linux プロジェクトに追加します。CMake を使用している場合、パッケージ名は FgLib5 です。CMake はインクルードディレクトリを変数に保存します ${FgLib5_INCLUDE_DIR} およびライブラリを次の場所に保存します ${FgLib5_LIBRARIES}。プロジェクトの詳細およびCMakeの使用方法については、 前提条件 を参照してください。

Frame Grabber Libraryにおけるエラーハンドリング#

const char * Fg_getErrorDescription(
    Fg_Struct * fg,
    int result);

int Fg_getLastErrorNumber(
    Fg_Struct * fg);

API のほとんどの関数は int 結果コードを返します。関数呼び出しが正常に実行された場合、戻り値は FG_OKになります。負の値は、ほとんどの場合、エラー状態を示します。エラーコードは次のヘッダーファイルで定義されています basler_fg.h.

関数 Fg_getErrorDescription() を使用して、特定の結果コードの文字列表現を取得できます。この関数の最初の引数であるフレームグラバーへのハンドルは使用されず、API の下位互換性のためにのみ含まれています。常に次を渡す必要があります nullptr.

関数 Fg_getLastErrorNumber() は、常に同じスレッドコンテキストで最後に呼び出された関数の結果コードを返します。これは、関数自体が結果コードを返さない場合に最も役立ちます。この関数は引数としてフレームグラバーハンドルを受け入れます。これは nullptr 最後に呼び出された関数がフレームグラバーハンドルを受け取らなかった場合に使用できます。フレームグラバーハンドルを必要とする関数の結果コードを要求するには、同じハンドルを次に渡す必要があります Fg_getLastErrorNumber().

情報

エラーコードはスレッドローカルストレージに保存されます。つまり、次を呼び出すことにより Fg_getLastErrorNumber() あるスレッドからアプリケーションが別のスレッドで発生したエラーコードを要求することはできません。

次のコードは、フレームグラバーハンドルに特定されないコンテキストで発生した最後のエラーとその説明を出力します。

int result = Fg_getLastErrorNumber(nullptr);
if (result != FG_OK) {
    const char * description = Fg_getErrorDescription(nullptr, result);

    std::cout << "Error " << result
              << ": " << description
              << std::endl;
}

このマニュアルの残りの部分にあるコード例には、アプリケーションの要件に固有のものであるためエラー処理は含まれていません。ただし、関数の正常終了を確認するため、可能な限りリターンコードがチェックされます。

Frame Grabber Libraryの初期化#

int Fg_InitLibraries(
    const char *);

void Fg_FreeLibraries();

ライブラリ fglib5 を使用する前に、次の関数を呼び出して初期化する必要があります。 Fg_InitLibraries()。この関数は内部目的でのみ使用される引数を受け入れ、nullptr に設定する必要があります。

アプリケーションがライブラリの使用を終了した後は、次の関数を呼び出します。 Fg_FreeLibraries() これにより、前回の初期化によって割り当てられたリソースが解放されます。

int result = Fg_InitLibraries(nullptr);
if (result != FG_OK) {
    // handle error ...
}

// use frame grabber ...

Fg_FreeLibraries();

システム情報#

フレームグラバーを初期化する前に、使用されている Framegrabber API のバージョン、コンピューターにインストールされているフレームグラバーの数と種類、およびその他の情報に関する情報を要求できます。

Framegrabber APIバージョン#

const char * Fg_getSWVersion();

Framegrabber API のバージョンの文字列表現は、次を使用して要求できます。 Fg_getSWVersion().

const char * rtVersion = Fg_getSWVersion();
std::cout << "Runtime SDK version: " << rtVersion
          << std::endl;

一般的なシステム情報#

int Fg_getIntSystemInformationGlobal(
    Fg_Info_Selector information,
    FgProperty propertyId,
    int * value);

情報

関数 Fg_getIntSystemInformationGlobal() は Framegrabber API バージョン 5.9 で追加されました。セクションを参照してください。 Plain Cにおけるシステム情報 (旧インターフェース用)。

次の情報は、次の関数を通じて要求できます。 Fg_getIntSystemInformationGlobal() プロパティを使用する PROP_ID_VALUE:

情報 説明 タイプ
INFO_NR_OF_BOARDS コンピュータ内で検出されたボードの数 int32_t
INFO_MAX_NR_OF_BOARDS サポートされるボードの最大数 int32_t
INFO_SERVICE_ISRUNNING 0: サービスは実行されていません。1: サービスは実行中です int32_t

たとえば、コンピューターにインストールされているフレームグラバーの数は、次のように要求できます。

int numBoards = 0;
int result = Fg_getIntSystemInformationGlobal(INFO_NR_OF_BOARDS, PROP_ID_VALUE, &numBoards);
if (result == FG_OK) {
    std::cout << "Number of boards: " << numBoards
              << std::endl;
}

ボード固有のシステム情報#

int Fg_getIntSystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
     FgProperty propertyId,
     int * value);

int Fg_getInt64SystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int64_t * value);

int Fg_getStringSystemInformationForBoardIndex(
    unsigned int board,
    Fg_Info_Selector information,
    FgProperty propertyId,
    std::string & value,
    const std::string & arg = "");

int Fg_getIntSystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int * value);

int Fg_getInt64SystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    int64_t * value);

int Fg_getStringSystemInformationForFgHandle(
    Fg_Struct * fg,
    Fg_Info_Selector information,
    FgProperty propertyId,
    std::string & value,
    const std::string & arg = "");

情報

この章で説明されている機能は、Framegrabber APIのバージョン5.9で追加されました。古いインターフェースについては、System Information in Plain Cのセクションを参照してください。

任意のフレームグラバーについて、ほとんどのその他の情報は次の関数を通じて要求できます。 Fg_getIntSystemInformationForBoardIndex(), Fg_getInt64SystemInformationForBoardIndex() および Fg_getStringSystemInformationForBoardIndex() ボードインデックスまたはフレームグラバーハンドルとプロパティを使用する PROP_ID_VALUE:

情報 説明 タイプ
INFO_TIMESTAMP_FREQUENCY 画像タイムスタンプに使用されるTimestampの周波数 int64_t
INFO_BOARDNAME microDiagnosticsなどに表示されるボード名 string
INFO_BOARDTYPE sisoboards.hで定義されているボードタイプ int32_t
INFO_BOARDSERIALNO ボードのシリアル番号 int32_t
INFO_FIRMWAREVERSION ボードのファームウェアバージョン string
INFO_HARDWAREVERSION ボードのハードウェアバージョン string
INFO_CAMERA_INTERFACE ボードによって提供されるカメラインターフェース(「CameraLink」または「CXP」) string
INFO_DRIVERVERSION ボードに使用されるドライバーバージョン string
INFO_DRIVERARCH ボードに使用されるドライバーアーキテクチャ string
INFO_DRIVERFULLVERSION ボードに使用される、アーキテクチャを含む完全なドライバーバージョン string
INFO_DRIVERGROUPAFFINITY ドライバーのIRQグループアフィニティ(Support for Non-Uniform Memory Accessを参照) int32_t
INFO_DRIVERAFFINITYMASK ドライバーIRQプロセッサアフィニティマスク(Support for Non-Uniform Memory Accessを参照) int64_t
INFO_LICENSE_GROUP_CODE フレームグラバーライセンスグループコード(アプレットライセンスグループコードのスーパーセットである必要がありますa) int32_t
INFO_LICENSE_USER_CODE フレームグラバーライセンスユーザーコード(アプレットライセンスユーザーコードと一致している必要があります) int32_t
INFO_IS_POCL 0: ボードがPoCLをサポートしていません。1: ボードがPoCLをサポートしています int32_t
INFO_NR_OF_CXP_PORTS CXPインターフェースを搭載したボード上のポート数 int32_t
INFO_NR_OF_CL_PORTS CameraLinkインターフェースを搭載したボード上のポート数 int32_t
INFO_NR_OF_PORTS CameraLinkHSインターフェースを搭載したボード上のポート数 int32_t
INFO_NR_OF_GIGE_PORTS GigEインターフェースを搭載したボード上のポート数 int32_t
INFO_APPLET_DESIGN_ID アプレットのHAP ID(アプレットのパスをパラメータargに渡す必要があります) string
INFO_APPLET_BITSTREAM_ID アプレットのビットストリームID(アプレットのパスをパラメータargに渡す必要があります) string
INFO_STATUS_PCI_LINK_WIDTH フレームグラバーで使用されているPCIeレーン数 int32_t
INFO_STATUS_PCI_EXPECTED_LINK_WIDTH フレームグラバーでサポートされているPCIeレーン数 int32_t
INFO_STATUS_PCI_LINK_SPEED フレームグラバーで使用される PCIe の世代 int32_t
INFO_STATUS_PCI_EXPECTED_LINK_WIDTH フレームグラバーでサポートされる PCIe の世代 int32_t
INFO_STATUS_PCI_PAYLOAD_SIZE フレームグラバーで使用される PCIe ペイロードサイズ int32_t

上記のリストは網羅的なものではなく、アプリケーションに有用な情報に関する Property のみが含まれています。API のその他の使用例については、Framegrabber API referenceを参照してください。

たとえば、次のコードはボードの種類と名前を要求します。

const int boardIndex = 0;

int boardType = 0;
int result =
    Fg_getIntSystemInformationForBoardIndex(boardIndex, INFO_BOARDTYPE,
                                            PROP_ID_VALUE, &boardType);

std::string boardName;
if (result == FG_OK) {
    result =
        Fg_getStringSystemInformationForBoardIndex(boardIndex, INFO_BOARDNAME,
                                                   PROP_ID_VALUE, boardName);
}

if (result == FG_OK) {
    std::cout << "Board #" << boardIndex
              << " is a " << boardName
              << " (type " << std::hex << boardType
              << std::dec << ")" << std::endl;
}

初期化後にフレームグラバーハンドルが使用可能になったら、次の関数を使用します。 Fg_getIntSystemInformationForFgHandle(), Fg_getInt64SystemInformationForFgHandle() および Fg_getStringSystemInformationForFgHandle() を使用すると、上記のリストに従ってボード固有の情報を取得できます。(章を参照してください フレームグラバーの初期化。)フレームグラバーハンドルと Property を使用して、次の情報を要求できます PROP_ID_VALUE:

情報 説明 タイプ
INFO_APPLET_CAPABILITY_TAGS アプレットの機能を表すキーと値のペアのリスト string
INFO_OWN_BOARDINDEX フレームグラバーのボードインデックス int32_t
INFO_FPGA_BITSTREAM_ID FPGA でアクティブなアプレットのビットストリーム ID string
INFO_APPLET_FULL_PATH アプレットのフルパス string
INFO_APPLET_FILE_NAME アプレットファイル名 string
INFO_APPLET_TYPE 0: HAP ファイル、1: DLL/SO ファイル(Appletsを参照) int32_t

上記のリストは網羅的なものではなく、アプリケーションに役立つ情報のプロパティのみが含まれています。API のその他のユースケースについては、Framegrabber API リファレンスを参照してください。

ボードインデックスの使用#

フレームグラバーは、ボードインデックスを使用して選択されます。システムに存在するボードの数が分かっている場合、デフォルトでは、最初のボードはインデックス 0、2番目のボードはインデックス 1 で識別されます。

Framegrabber API を使用すると、microDiagnostics 内から生成できる設定ファイルを使用して、各ボードに一意のインデックスを割り当てることができます。その場合、ユーザーは割り当てと対応するボードインデックスを把握しておく必要があります。

アプレット#

フレームグラバーを使用するには、アプレットが必要です。アプレットは、一般的に次のようないくつかの要素の集合です:

  • カメラデバイスからの画像受信から、処理済みの画像をコンピューターの Memory に送信するまでの画像処理を実装する、フレームグラバー上の FPGA 用のデザイン
  • デザインで使用されている VisualApplets オペレーターと、パラメーターを FPGA レジスタにマッピングするための情報を含む、ソフトウェアデザインの記述
  • オペレーターのパラメータ値と FPGA レジスタの内容との間の変換の処理を行うクラスインスタンスのジェネレーターとして機能する、ソフトウェアインターフェイスライブラリのコレクション
  • すべてのオペレータークラスのインスタンス化、初期化、およびアプレットとのインターフェイスを処理するトップレベルライブラリである VAS

アプレットは、VisualApplets を使用して設計された場合は HAP ファイルの形式で、Framegrabber SDK によってプレインストールされている場合はラップされたアプレットライブラリファイルの形式で提供されます。HAP ファイルは通常、Framegrabber SDK インストールのボード固有のサブディレクトリ内に保存され、一方、ラップされたアプレットライブラリファイルは以下の Hardware Applets ディレクトリのボード固有のサブディレクトリにインストールされます。 dll これらのサブディレクトリは、このドキュメント全体において、対応するタイプのアプレットの標準的な場所と呼ばれます。

各アプレットは、提供されている機能を設定するための一連のパラメータを提供しています。アプレットによって提供される機能とパラメータの詳細な説明については、使用する特定のアプレットのドキュメントを参照してください。

適切なアプレットの選択#

Framegrabber SDK と共にインストールできるアプレットは、通常、ラップされたライブラリファイルとして提供されます。これらのファイルの命名規則にはいくつかのルールがあります:

  • ファイル名は通常、 Acq_。(これらのアプレットは Advanced Acquisition Appletと呼ばれ、前世代は Standard Applet と呼ばれており、命名規則が異なっていました。)
  • 次に、アプレットがサポートするカメラの数が次の形式で示されます: Single, Dual または Quad.
  • 次に、サポートされているカメラインターフェイスが示されます。例えば、 CXP12 は、CoaXPress Standard Version 2.0 で指定されている最大 12 Gbit/s の CoaXPress カメラインターフェイスを示します。
  • 古いフレームグラバープラットフォームでは、サポートされる Camera Link 接続の最大数が次の形式で示されます: x1, x2 または x4。(これは命名規則から除外されました。なぜなら、 x4 は以下をサポートし、 x2 および x1, x2 は以下をサポートしており、 x1 サポートされるリンクの最大数は通常、サポートされるカメラの数とフレームグラバーが提供する物理ポートの数から明確になるはずであるためです。)
  • 次に、サポートされているセンサータイプが示されます。これは、 Area または Lineのいずれかです。エリアセンサーとラインセンサーの両方をサポートするアプレットの場合、これは省略されます。
  • 名前の最後の部分は、 Gray8, Bayer16, RGB24などの、アプレットがサポートするデータフォーマットです。複数のデータフォーマットをサポートするアプレットの場合、これは省略されます。

例えば、アプレット Acq_SingleCXP12Area は、最大 12 Gbit/s の 1 台の CXP カメラとエリアセンサーをサポートする高度な Acquisition Applet です。このアプレットは複数のデータフォーマットをサポートしています。サポートされているデータフォーマットとセンサーサイズについては、アプレットのマニュアルを参照してください。

例えば、12 Gbit/s の CXP カメラ 2 台と 10 ビット階調出力のライン型センサーが必要な場合は、以下のようなアプレットを探してください。 Acq_DualCXP12Line, Acq_DualCXP12LineGray10 または Acq_DualCXP12LineGray16 を参照し、付属のマニュアルをお読みください。カメラが単一の物理リンクのみを使用して接続する場合は、 Quad のアプレットのバリエーションも検討できます。

起動時の動作#

Framegrabber SDK が fglib5 ライブラリの初期化を開始するときは、Frame Grabber Initializationで説明されているように、アプレットがロードされる前であってもフレームグラバーへのアクセスが必要になります。これは、たとえば、シリアル番号に従ってボードを並べ替えるため、またはロード可能なすべてのアプレットを表示するためなどに必要です。

この初期化に使用されるアプレットは、使用するフレームグラバーによって異なります。次のセクションの情報を使用して、事前定義されたアプレットで起動するようにフレームグラバーを設定できます。事前定義されたアプレットとは異なるアプレットを使用する場合 呼び出し Fg_Init 起動時間が長くなります。

起動時に、Framegrabber SDK はデフォルトで、以下の条件で使用された最後のアプレットをロードします。 Fg_Init.

システム環境変数を設定することで、この動作を無効にすることができます。 FGSDK_LOAD_LAST_APPLET_ON_INIT=Off.

microEnable 5 marathon Frame Grabbersの起動動作#

microEnable 5 marathon フレームグラバーでは、利用可能なパーティションのいずれかにアプレットをボードにフラッシュする必要があります。Framegrabber SDK のデフォルトの動作は、以下の設定で使用されるアプレットを設定することです。 Fg_Init をブートパーティションとして使用します。起動時には、システムの電源投入時にボードを初期化するために、ブートパーティション内のアプレットが使用されます。このアプレットは、Framegrabber SDK の最初の初期化フェーズでも使用されます。

microEnable 6 Frame Grabbersの起動動作#

CXP-12 Interface Card、imaWorx CXP-12 Quad、imaFlex CXP-12 Quad、または imaFlex CXP-12 Penta フレームグラバーでは、Framegrabber SDK は最後にロードされたアプレットを開こうとします。最後にロードされたアプレットは、 LastApplet セクションのキーで定義されます。 FG という名前の設定ファイル内 me6_<n>_init.configここで、 <n> はボードのドライバーインデックスです。ドライバーインデックスは、セクションで説明されているボードインデックスに非常に似ていますが、ドライバー固有のものであり、ボードの再ソートの影響を受けません。Windowsでは、 ボードインデックスの使用ただし、これはドライバー固有のものであり、ボードの再ソートの影響を受けません。 Windows 、 driver index 0 は、ドライバーによって検出された最初の CXP-12 Interface Card、imaWorx CXP-12、または imaFlex CXP-12 フレームグラバーを指し、 driver index 1 は 2 番目のボードを指します。他のすべてのオペレーティングシステムでは、ドライバーインデックスは、再並べ替えを行わずにボードインデックスと同一になります。

Windows システムでは、設定ファイルは通常、次のディレクトリにあります。 %APPDATA%\basler他のすべてのオペレーティングシステムでは、設定ファイルは次の場所にあります。 $HOME/.config/basler ディレクトリ。設定ファイルが見つからない場合、Framegrabber SDK は Framegrabber SDK インストールのルートフォルダーを検索します。

フレームグラバーの設定ファイルが見つからない場合、または初期化に失敗した場合は、デフォルトのアプレットが使用されます。デフォルトのアプレットは通常、物理ポートごとに 1 つのエリアセンサー型カメラをサポートするアプレットです。

デフォルトのアプレットでも初期化に失敗した場合、Framegrabber SDK は使用可能な任意のアプレットを開きます。

アプレットの列挙#

int Fg_getAppletIterator(
    int board,
    FgAppletIteratorSource source,
    Fg_AppletIteratorType * iter,
    int flags);

Fg_AppletIteratorItem Fg_getAppletIteratorItem(
    Fg_AppletIteratorType iter,
    int index);

int64_t Fg_getAppletIntProperty(
    Fg_AppletIteratorItem item,
    FgAppletIntProperty property);

const char * Fg_getAppletStringProperty(
    Fg_AppletIteratorItem item,
    FgAppletIntProperty property);

int Fg_freeAppletIterator(
    Fg_AppletIteratorType iter);

通常、アプリケーションは 1 つまたは少数の特定のアプレットを使用し、機能はアプレットのマニュアルを通じて既知となるため、次の関数はほとんどのアプリケーションにとって有用ではありません。アプリケーションをより動的に設計する場合、Framegrabber API はアプレットの列挙やアプレットに関するさまざまな情報の要求を可能にする関数を提供します。

アプレットを列挙するには、関数 Fg_getAppletIterator() を呼び出すことができます。Framegrabber SDK のインストールで使用可能なアプレットを列挙する場合は、ソース FG_AIS_FILESYSTEM を使用する必要があります。指定したボードにロードできるアプレットのみを列挙するには、フラグとして FG_AF_IS_LOADABLE を渡します。これにより、API によって返されたアプレットを、その後のフレームグラバー初期化の呼び出しで使用できるようになります。この関数は、イテレータ内のアイテム数を返します。

アプレットイテレータのアイテムは、次を呼び出すことで取得できます: Fg_getAppletIteratorItem().

アイテムに関する以下の情報は、次を呼び出すことで要求できます: Fg_getAppletIntProperty() または Fg_getAppletStringProperty():

Property 説明 タイプ
FG_AP_INT_FLAGS アプレットに適用されるフラグ(FG_AF_...定数) int32_t
FG_AP_INT_INFO アプレットに適用されるタグ(FG_AI_...定数) int32_t
FG_AP_INT_PARTITION アプレットが書き込まれているパーティション(mE5のみ) int32_t
FG_AP_INT_NR_OF_DMA アプレットによって提供されるDMAチャネルの最大数 int32_t
FG_AP_INT_NR_OF_CAMS アプレットの使用時にアクセスできるカメラの最大数 int32_t
FG_AP_INT_GROUP_CODE アプレットライセンスグループコード(フレームグラバーライセンスグループコードのサブセットである必要がありますa) int32_t
FG_AP_INT_USER_CODE アプレットライセンスユーザーコード(フレームグラバーライセンスユーザーコードと一致している必要があります) int32_t
FG_AP_INT_DESIGN_VERSION FPGAデザインのメジャーバージョン int32_t
FG_AP_INT_DESIGN_REVISION FPGAデザインのバージョンリビジョン int32_t
FG_AP_STRING_APPLET_UID アプレットファイルを識別するUID string
FG_AP_STRING_BITSTREAM_UID FPGAデザインを識別するUID string
FG_AP_STRING_DESIGN_NAME FPGAデザインの名前 string
FG_AP_STRING_APPLET_NAME アプレットの名前 string
FG_AP_STRING_DESCRIPTION アプレットの説明 string
FG_AP_STRING_CATEGORY アプレットのカテゴリー string
FG_AP_STRING_APPLET_PATH アプレットのフルパス string
FG_AP_STRING_SUPPORTED_PLATFORMS サポートされているプラットフォームのカンマ区切りリスト string
FG_AP_STRING_TAGS タグのカンマ区切りリスト string
FG_AP_STRING_VERSION アプレットのバージョン string
FG_AP_STRING_APPLET_FILE アプレットのファイル名 string
FG_AP_STRING_RUNTIME_VERSION 必要な Framegrabber SDK のバージョン string

上記のリストは網羅的なものではなく、アプリケーションに役立つ情報のプロパティのみが含まれています。API のその他のユースケースについては、Framegrabber API リファレンスを参照してください。

アプレットイテレータを使用した後は、次を呼び出して解放する必要があります: Fg_freeAppletIterator().

名前が一意であり、アプレットが標準ロケーションのいずれかに配置されている限り、そのアプレット名は、その後のフレームグラバー初期化呼び出しに使用するのに十分です。複数のアプレットが同じ名前を使用している場合や、アプレットが標準ロケーション以外の場所に配置されている場合は、フルパスを使用する必要があります。次の例は、標準ロケーションで見つかったすべてのアプレットからアプレット名を抽出する方法を示しています:

const in boardIndex = 0;

Fg_AppletIteratorType iter = 0;
int numItems =
    Fg_getAppletIterator(boardIndex, FG_AIS_FILESYSTEM,
                         &iter, FG_AF_IS_LOADABLE);

if (numItems >= 0) {
    std::cout << "Found " << numItems << " applets";

    for (int i = 0; i < numItems; ++i) {
        auto item = Fg_getAppletIteratorItem(iter, i);

        const char * appletName =
            Fg_getAppletStringProperty(item, FG_AP_STRING_APPLET_NAME);

        std::cout << " " << appletName;
    }

    std::cout << std::endl;
    Fg_freeAppletIterator(iter);
}

フレームグラバーの初期化#

Fg_Struct * Fg_Init(
    const char * applet,
    unsigned int board);

int Fg_FreeGrabber(
    Fg_Struct * fg);

フレームグラバーを使用するには、まず初期化する必要があります。これを行うには、次の関数を使用してアプレットをロードします Fg_Init()。この関数は、指定されたアプレットでフレームグラバーを初期化した後、指定されたボードインデックスのフレームグラバーへのハンドルを返します。このハンドルは、後続の章で説明するほとんどの API 関数で使用されます。

アプリケーションがフレームグラバーの使用を終了したら、次を呼び出して解放する必要があります Fg_FreeGrabber().

たとえば、次のコードは、次のアプレットを使用して CXP-12 フレームグラバーを初期化します Acq_SingleCXP12Area:

const int boardIndex = 0;
const char * applet = "Acq_SingleCXP12Area";

Fg_Struct * fg = Fg_Init(applet, boardIndex);
if (fg != nullptr) {
    // use frame grabber ...

    Fg_FreeGrabber(fg);
}

設定ファイル#

Fg_Struct * Fg_InitConfig(
    const char * config,
    unsigned int board);

int Fg_loadConfig(
    Fg_Struct * fg,
    const char * config);

int Fg_saveConfig(
    Fg_Struct * fg,
    const char * config);

microDisplay X を使用してフレームグラバーの初期設定を行い、セットアップをテストする場合、設定はプログラム内から保存できます。メイン設定ファイルの拡張子は .mcf になり、拡張子が .mfs の2番目のファイルが同時に作成されます。これら2つのファイルを使用すると、API 呼び出しを通じて設定を再現する代わりに、アプリケーションはこれら2つのファイルを使用して直接フレームグラバーを初期化できます。

ここでのコンフィギュレーションとは、フレームグラバーの初期化に使用されたアプレット、およびそのアプレットのパラメータ設定を指します。詳細については、アプレットパラメータの操作の章を参照してください。

情報

関数のパラメータで使用されるのは、拡張子を持つメイン設定ファイル .mcf のみです。拡張子を持つファイル .mfs は、拡張子までのファイル名が同じである限り、自動的に使用されます。

設定ファイルからフレームグラバーを初期化するには、 Fg_InitConfig() の代わりに次の関数を呼び出すことができます Fg_Init()。この関数は、指定されたメイン設定に従ってフレームグラバーを初期化した後、指定されたボードインデックスのフレームグラバーへのハンドルを返します。

アプリケーションがフレームグラバーの使用を終了したら、次を呼び出して解放する必要があります Fg_FreeGrabber().

アプリケーションに異なる設定セットが必要な場合は、 Fg_loadConfig() を呼び出した後の任意の時点で次を呼び出すことで、それらをフレームグラバーに適用できます Fg_Init() または Fg_InitConfig().

現在の設定をコンフィギュレーションファイルに書き込むには、次を呼び出します Fg_saveConfig() を呼び出した後の任意の時点で次を呼び出すことで、それらをフレームグラバーに適用できます Fg_Init() または Fg_InitConfig().

次の例は、フレームグラバーの設定を保存および復元する方法を示しています:

const char * config = "SavedState.mcf";

int result = Fg_saveConfig(fg, config);
if (result != FG_OK) {
    // handle error ...
}

// change frame grabber configuration ...

result = Fg_loadConfig(fg, config);
if (result != FG_OK) {
    // handle error ...
}

アプレットパラメータの操作#

アプレットを使用してフレームグラバーを初期化したら、アプレットのパラメータを読み取るか操作することができます。たとえば、カメラから画像を取得するには、カメラが送信する画像データに応じて、正しい画像寸法と画像フォーマットを使用するようにアプレットを設定する必要があります。もう一つの例は、アプリケーションの要件に合わせて、アプレットによって提供されるトリガーモジュールを設定することです。

パラメータ識別子とパラメータ名#

int Fg_getParameterIdByName(
    Fg_Struct * fg,
    const char * name);

const char * Fg_getParameterNameById(
    Fg_Struct * fg,
    unsigned int id,
    unsigned int dma);

FgParamTypes Fg_getParameterTypeById(
    Fg_Struct * fg,
    unsigned int id,
    unsigned int dma);

情報

関数 Fg_getParameterTypeById() は、Framegrabber SDKバージョン5.9で追加されました。

アプレットの各パラメータはその名前で識別されますが、APIではパラメータ値やPropertyにアクセスするために数値識別子を使用します。多くのパラメータには、ヘッダーファイルで指定されている固定の数値識別子があります。 basler_fg.hただし、最も一般的なパラメータ以外での使用はお勧めしません。パラメータの数値識別子を取得するには、関数 Fg_getParameterIdByName() を使用します。名前を識別子に変換する際にエラーが発生した場合、この関数は0または負のエラーコードを返します。

数値識別子が既知であるパラメータの名前を取得するには、関数 Fg_getParameterNameById() を使用できます。

数値識別子が既知であるパラメータの型を取得するには、関数 Fg_getParameterTypeById() を使用できます。

パラメータタイプ#

パラメータには型があり、パラメータの値を取得または設定するには、アプレットのマニュアル、VisualAppletsを使用して社内で設計されたアプレットによる暗黙的な情報、または関数を使用して型を要求することにより、型が既知である必要があります。 Fg_getParameterTypeById().

パラメータタイプ C/C++ Type
FG_PARAM_TYPE_INT32_T int32_t
FG_PARAM_TYPE_UINT32_T uint32_t
FG_PARAM_TYPE_INT64_T int64_t
FG_PARAM_TYPE_UINT64_T uint64_t
FG_PARAM_TYPE_DOUBLE double
FG_PARAM_TYPE_CHAR_PTR string
FG_PARAM_TYPE_SIZE_T size_t
FG_PARAM_TYPE_STRUCT_FIELDPARAMINT FieldParameterAccess
FG_PARAM_TYPE_STRUCT_FIELDPARAMINT64 FieldParameterAccess
FG_PARAM_TYPE_STRUCT_FIELDPARAMDOUBLE FieldParameterAccess

フィールドパラメータ型のいずれかを持つパラメータは、プレーンC使用時の考慮事項の章の「フィールドパラメータへのアクセス」のサブセクションで説明されている FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS APIの説明については、以下のサブセクションを参照してください。 フィールドパラメータへのアクセス 章の Plain Cを使用する際の考慮事項.

パラメータ値へのアクセス#

int Fg_getParameterWithType(
    Fg_Struct * fg,
    int id,
    int32_t * value,
    unsigned int dma);

// Fg_getParameterWithType() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value
int Fg_setParameterWithType(
    Fg_Struct * fg,
    int id,
    int32_t value,
    unsigned int dma);

// Fg_setParameterWithType() is overloaded for:
//     int32_t value
//     uint32_t value
//     int64_t value
//     uint64_t value
//     float value
//     double value
//     const std::string & value

パラメータの値を取得または設定するには、オーバーロードされた関数 Fg_getParameterWithType() および Fg_setParameterWithType() を使用する必要があります。

たとえば、以前の fg の呼び出しによるフレームグラバーハンドル Fg_Init()が与えられた場合、次のコードはアプレットの最初のDMAチャネルの幅を1024に設定します。

const int dma = 0;
const int width = 1024;
int result = FG_INVALID_PARAMETER;

int paramId = Fg_getParameterIdByName(fg, "FG_WIDTH");
if (paramId > 0) {
    result = Fg_setParameterWithType(fg, paramId, width, dma);
}

関数 Fg_getParameterWithType() および Fg_setParameterWithType() に渡される最後のパラメータは、ほとんどの場合DMAチャネルを指します。 FG_WIDTH, FG_HEIGHT などのパラメータはDMAチャネルごとに異なる場合があり、これらのパラメータの各インスタンスは、DMAチャネルの番号を関数に渡すことで要求または変更できます。

場合によっては、最後のパラメータが他の論理インデックスを指すこともあります。たとえば、パラメータ FG_NR_OF_DMAS または FG_NR_OF_CAMS は、VisualAppletsで定義されたスコープであるアプレットのプロセスごとに複数のインスタンスで存在します。

他のパラメータはアプレットのコンテキストではグローバルであり、関数内の最後のパラメータは無視されます。そのようなパラメータの1つが FG_NR_OF_PROCESSESになります。しかしさらに重要なことに、アプリケーション開発者がVisualAppletsを使用して独自のアプレットを設計する場合、アプレットを制御するすべてのパラメータが一意の名前で識別されるためグローバルとみなされ、関数内の最後のパラメータは無視されます。

一部のパラメータは、取得される画像ごとに異なり、DMAチャンネルとフレーム番号またはバッファ番号の両方が必要になります。これは、画像がコンピュータのMemoryに転送されたときのタイムスタンプ、実際の画像データの長さ、その他の同様の情報といった画像メタデータに適用されます。これらのパラメータは、前述の関数では処理できません。このトピックについては、画像取り込みの章で詳しく説明します。

パラメータPropertyへのアクセス#

int Fg_getParameterPropertyWithType(
    Fg_Struct * fg,
    int id,
    FgProperty propertyId,
    int32_t * value);

// Fg_getParameterPropertyWithType() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value
int Fg_getParameterPropertyWithTypeEx(
    Fg_Struct * fg,
    int id,
    FgProperty propertyId,
    int32_t * value,
    unsigned int dma);

// Fg_getParameterPropertyWithTypeEx() is overloaded for:
//     int32_t * value
//     uint32_t * value
//     int64_t * value
//     uint64_t * value
//     float * value
//     double * value
//     std::string & value

情報

この章で説明する関数は、Framegrabber SDKのバージョン5.9で追加されました。古いインターフェースについては、プレーンCでのパラメータプロパティへのアクセスのセクションを参照してください。

パラメーターには、現在の値以外にもさまざまな Property があります。オーバーロードされた関数を使用する Fg_getParameterPropertyWithType() ことは推奨されません。関数呼び出しが暗黙的に DMA チャネル 0 を使用するためであり、パラメーターの Property はチャネルによって異なる場合があります。オーバーロードされた関数を使用すると、 Fg_getParameterPropertyWithTypeEx() 次の Property を取得できます。

Property 説明 タイプ
PROP_ID_VALUE 現在のパラメータ値 パラメーターと同じ
PROP_ID_DATATYPE パラメータタイプ
(FgParamTypesに応じた列挙型値)
int32_t
PROP_ID_NAME 説明的な名前 string
PROP_ID_PARAMETERNAME パラメータ名 string
PROP_ID_VALUELLEN 値を文字列にエンコードするために必要な長さ int32_t
PROP_ID_ACCESS パラメータのアクセスフラグ int32_t
PROP_ID_MIN 最小パラメータ値b パラメーターと同じ
PROP_ID_MAX 最大パラメータ値b パラメーターと同じ
PROP_ID_STEP パラメータのステップサイズb パラメーターと同じ
PROP_ID_IS_ENUM 0:列挙型パラメータではありません
n:PROP_ID_ENUM_VALUESに必要なバッファサイズ
int32_t
PROP_ID_ENUM_VALUES 列挙型値(列挙型値パラメータプロパティへのアクセスを参照) FgPropertyEnumValues[]
PROP_ID_FIELD_SIZE フィールドパラメータ内の要素数 int32_t

上記のリストはすべてを網羅しているわけではなく、非推奨とみなされていない情報に関する Property のみが含まれています。API のその他のユースケースについては、Framegrabber API リファレンスを参照してください。

paramId が次の型のパラメーターであると仮定して、パラメーターの最小値を取得する方法を次の例に示します。 FG_PARAM_TYPE_INT32_T:

int minVal = 0;
int result =
    Fg_getParameterPropertyWithTypeEx(fg, paramId, PROP_ID_MIN,
                                      &minVal, dma);
if (result == FG_OK) {
    // work with the property ...
}

Memory管理#

カメラから画像を取り込むには、その画像を転送し、プログラム内から画像データにアクセスするためのMemoryがコンピュータ上に必要となります。Framegrabber APIは、循環バッファMemoryモデルを使用します。Memoryバッファは、通常フレームバッファまたはサブバッファと呼ばれる少なくとも2つのアイテムで構成され、カメラから取得される後続のフレームのために再利用されます。使用するフレームバッファの数はさまざまな要因によって決まりますが、最も重要なのは、1つのフレームがまだ処理されている間にさらに何フレーム到着するかということです。これについては、画像取り込みの章の取り込みモデルのセクションで詳しく説明します。

各フレームバッファーは同じサイズでなければならず、アプリケーション要件に応じた最大サイズの画像を格納できる大きさである必要があります。通常、これは幅(width) FG_WIDTH、高さ(height) FG_HEIGHT 、および Pixel Format FG_FORMATによって定義されます。(VisualApplets で設計されたアプレットの場合、幅、高さ、および Pixel Format の設定は通常、より複雑になります。)

サーキュラーバッファーは、仮想アドレス空間で連続しており、同じサイズに分割された 1 つの大きな Memory ブロックにすることができます。あるいは、Memory 内で個別に割り当てられ、管理構造に追加されたフレームバッファーで構成することもできます。 dma_mem APIによって使用されます。

void * Fg_AllocMem(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames,
    unsigned int dma);

int Fg_FreeMem(
    Fg_Struct * fg,
    unsigned int dma);

メモリ管理に使用できる関数セットは3つあります。ただし、次の関数を使用することは Fg_AllocMem() および Fg_FreeMem() 標準集録モデル(ACQ_STANDARD)の使用に制限されているため、推奨されません。残りの2つの関数セットは、3つのすべての集録モデル(ACQ_STANDARD、ACQ_BLOCK、ACQ_SELECT)で使用でき、シンプルなユースケースからアプリケーションのより具体的な要件まで幅広く適用できるため、ここでより詳細に説明します。

高度なMemory管理#

dma_mem * Fg_AllocMemEx(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames);

int Fg_FreeMemEx(
    Fg_Struct * fg,
    dma_mem * mem);

関数 Fg_AllocMemEx() を使用して、サイズが totalSize の1つの大きな連続したメモリバッファを割り当てることができます。これは numFrames 個の同じサイズのフレームバッファに分割されます。この関数は、メモリ管理構造体へのハンドルを返します。エラーが発生した場合はnullptrを返します。

返されたポインタはメモリバッファ自体へのポインタではないため、直接使用しないでください。メモリが不要になった後は、 Fg_FreeMemEx().

次の例では、1024 x 1024サイズの24ビットRGB画像を保持できる16個のフレームバッファ用のメモリバッファをコードで割り当てます。

const int width = 1024, height = 1024;
const int bytesPerPixel = 3;
const frameindex_t numFrames = 16;
const size_t frameSize = static_cast<size_t>(width) * height * bytesPerPixel;
const size_t totalSize = frameSize * numFrames;

dma_mem * mem = Fg_AllocMemEx(fg, totalSize, numFrames);
if (mem != nullptr) {
    // use memory, acquire and process images ...

    Fg_FreeMem(fg, mem);
}

イメージ static_cast<size_t>(width) の計算において frameSizeで使用されます。これは、非常に大きな画像のサイズが正しく計算されるようにするために必要です。

柔軟なMemory管理#

dma_mem * Fg_AllocMemHead(
    Fg_Struct * fg,
    size_t totalSize,
    frameindex_t numFrames);

int Fg_AddMem(
    Fg_Struct * fg,
    void * frameBuffer,
    size_t size,
    frameindex_t index,
    dma_mem * mem);

int Fg_DelMem(
    Fg_Struct * fg,
    dma_mem * mem,
    frameindex_t index);

int Fg_FreeMemHead(
    Fg_Struct * fg,
    dma_mem * mem);

Framegrabber APIにメモリ管理を処理させるのではなく、アプリケーション固有のメモリ割り当て要件がある場合は、関数 Fg_AllocMemHead() を使用してメモリ管理構造体を準備できます。この関数は、 Fg_AllocMemEx()と同じパラメータを必要としますが、メモリの割り当ては行いません。アプリケーション側でメモリを割り当てた後、 Fg_AddMem()を使用して各フレームバッファを個別に追加する必要があります。集録実行中にメモリバッファに使用されるフレームバッファを動的に変更する必要があるアプリケーションの場合は、関数 Fg_DelMem() を使用して、メモリバッファからフレームバッファを削除できます。メモリバッファが不要になった後は、 Fg_FreeMemHead() を呼び出して管理構造体を最初に解放し、その後にフレームバッファのメモリを解放する必要があります。

次のコードは、'Fg_AllocMemEx()'関数がより柔軟なメモリ管理APIの便利なラッパーである方法を示しています。

int Fg_AllocMemEx(Fg_Struct * fg, size_t totalSize, frameindex_t numFrames)
{
    const size_t frameSize = totalSize / numFrames;
    char * buf = nullptr;

    dma_mem * mem = Fg_AllocMemHead(fg, totalSize, numFrames);
    if (mem != nullptr) {
        try {
            buf = new char[totalSize];
            for (frameindex_t frame = 0; frame < numFrames; ++frame) {
                const int result =
                    Fg_AddMem(fg, buf + frameSize*frame,
                              frameSize, frame, mem);
                if (result != FG_OK) {
                    throw std::runtime_error("Failed to add frame buffer");
                }
            }
        }
        catch (...) {
            for (frameindex_t frame = 0; frame < numFrames; ++frame) {
                Fg_DelMem(fg, mem, frame);
            }
            Fg_FreeMemHead(fg, mem);
            delete[] buf;
            return nullptr;
        }
    }
    return mem;
}

画像取得#

Framegrabber APIには、3つの異なる集録モデルと組み合わせることができる2つの画像データ配信モードが用意されています。

画像データは、同期モードまたは非同期モードで配信できます。同期モードでは、アプリケーションによって集録ループを提供する必要があります。非同期モードでは、新しい画像データが利用可能になるたびに呼び出されるコールバック関数を登録できます。Framegrabber APIは、非同期モード用の別のスレッドで画像集録ループを提供します。一部のGUIフレームワークでは、Framegrabber APIのスレッドコンテキストをGUIスレッドコンテキストに同期させることが複雑になる場合があり、フレームワークによって提供されるスレッドコンテキストで集録ループを実行する方が理にかなっていることがあります。

非同期モードのコールバック関数の登録#

typedef int (* Fg_ApcFunc_t)(
    frameindex_t frame,
    void * data);

int Fg_registerApcHandlerEx(
    Fg_Struct * fg,
    unsigned int dma,
    Fg_ApcFunc_t func,
    void * data,
    unsigned int timeout,
    unsigned int flags);

int Fg_unregisterApcHandler(
    Fg_Struct * fg,
    unsigned int dma);

情報

Framegrabber APIバージョン5.9では、関数 Fg_registerApcHandlerEx() および Fg_unregisterApcHandler() が追加され、ブロッキング集録モデルを使用する場合の動作が ACQ_BLOCK が変更されました。次のセクションを参照してください Plain Cにおける非同期モード用のコールバック関数の登録 (旧インターフェース用)。

関数 Fg_registerApcHandlerEx() を使用して、集録を開始する前に非同期モードを設定できます。

を使用して、 Fg_registerApcHandlerEx()型の関数 Fg_ApcFunc_t 画像データが受信されたときに呼び出されるように登録できます。この関数は、指定されたフレームグラバーとDMAチャネルに対して登録され、呼び出し時に2つのパラメータが渡されます。コールバック関数の最初のパラメータは、フレーム番号( ACQ_STANDARD および ACQ_SELECT)またはバッファ番号( ACQ_BLOCK)です。2つ目のパラメータは、 Fg_registerApcHandlerEx() の呼び出し時に指定されたポインタであり、コンテキスト構造体やクラスへのポインタ(例えば、画像処理を実装するクラスインスタンスの this ポインタなど)として使用できます。

コールバック関数は、任意のフレームグラバー上の各DMAチャネルに対して1つのみ登録できます。

コールバック関数は、Framegrabber APIが提供する取り込みループから呼び出されます。これは、コールバック関数が取り込みループのスレッドコンテキストで呼び出されることを意味します。また、コールバック関数が処理を完了して戻るまでにかかる時間が取り込みループの一般的な管理オーバーヘッドに追加され、この時間内に複数の画像が受信される可能性があることも意味します。その間に画像が受信された場合、コールバック関数は戻った直後に再び呼び出されます。

画像取り込みの処理は、 timeout および flags への呼び出しにおけるパラメータを通じて制御できます Fg_registerApcHandlerEx()。 flagsパラメータでは、新しい画像の到着を取り込みループが待機するタイムアウト時間が秒単位で指定されます。 | (ビット単位のOR)演算子と組み合わせて、次の値およびその組み合わせを使用できます。

フラグ 説明
FG_APC_DEFAULTS 取り込みループにおけるデフォルトの処理
FG_APC_BATCH_FRAMES 複数の画像が受信された場合、コールバック関数の単一の呼び出しで最新の画像のみが配信される場合があります。
FG_APC_DELIVER_ERRORS 負の frameindex_t 値としてエラーをコールバック関数に配信します。
FG_APC_IGNORE_TIMEOUTS 画像タイムアウトを無視して処理を継続します。
FG_APC_IGNORE_APCFUNC_RETURN コールバックの戻り値を無視して処理を継続します。
FG_APC_IGNORE_STOP 取り込みの停止を無視して処理を継続します。
FG_APC_HIGH_PRIORITY 取り込みループを実装するスレッドの優先度を上げます。この値を使用するには、オペレーティングシステムの特権昇格が必要です。
FG_APC_OLD_ACQ_BLOCK_BEHAVIOR ACQ_BLOCKで Fg_getLastPicNumberBlockingEx() を使用します。c

取り込みループのデフォルトの処理は次のとおりです。

  • すべての単一画像がコールバック関数に配信されます
  • エラー値はコールバック関数に配信されません
  • 画像のタイムアウトによって取り込みループが終了します
  • コールバック関数からゼロ以外の戻り値が返されると、取り込みループが終了します
  • 取り込みの停止によって取り込みループが終了します
  • 取り込みループはデフォルトの優先度を持つスレッドで実行されます
  • 関数 Fg_getLastPicNumberBlockingEx() が呼び出され、その結果がコールバック関数に配信されます

情報

取り込みループを終了すると、コールバック関数の登録が自動的に解除されます。取り込みが停止されたときに常に取り込みループを終了することが論理的であるように思えるかもしれませんが、必ずしもそうとは限りません。例えば、アプリケーションが、取得するフレーム数を有限にしてFg_AcquireExを呼び出すことで、一定数の画像のバーストで取り込みを実行する必要がある場合を考えてみます。フレーム数が取得された後、取り込みはドライバによって自動的に停止されます。取り込みループを実行したままにし、別のスレッドから取り込みバーストを開始すると便利です。

情報

設定 FG_APC_HIGH_PRIORITY は、プロセスがスレッドの優先度を変更するために必要な特権を持っている場合にのみ可能です。使用しているオペレーティングシステムの特権と権利管理に関するドキュメントを参照してください。Microsoft Windowsを使用するアプリケーションの場合、関数 SetThreadPriority が使用されます。Linuxでは、関数 pthread_setschedparam が使用されます。

次の例は、画像取り込みの処理に必要な情報を保持する単純な構造体を使用してコールバック関数を登録する方法を示しています。

struct ApcUserCallbackData
{
    Fg_Struct * fg;
    dma_mem * mem;
    unsigned int dma;
    unsigned int timeoutInSeconds;
    int mode;
};

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // process new image ...
    } else {
        // handle error ...
    }

    return 0;
}

void SetupApcUserCallback(ApcUserCallbackData * context)
{
    // register callback function
    int result =
        Fg_registerApcHandlerEx(
            context->fg,
            context->dma,
            &ApcUserCallback,
            context,
            context->timeoutInSeconds,
            FG_APC_DELIVER_ERRORS | FG_APC_IGNORE_TIMEOUTS);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

コンテキスト構造体の割り当てと管理はこの例には示されていません。ポインタは、コールバック関数が登録されている間、有効である必要があります。解決策の1つは、すべてをC++クラス内にまとめておくことです。C++クラスのコンテキストでコールバック関数を使用するには、静的関数を使用してコールバックハンドラを登録し、 this pointerは、クラスポインタにキャストしてそれに応じて使用できるコンテキストデータポインタとして使用する必要があります。

コールバック関数が不要になった後は、以下を呼び出すことで登録を解除できます。 Fg_unregisterApcHandler() 同じフレームグラバーハンドルとDMAチャネルを使用します。

Fg_unregisterApcHandler(context->fg, context->dma);

取り込みの開始#

フレームグラバーからアプリケーションMemoryへの画像データの転送を有効にするには、アプレットでの取り込みを開始する必要があります。これにより、画像データを転送するフレームバッファがフレームグラバーに通知され、新しい画像のデータの転送が正常に完了するたびにドライバへ割り込みを送信できるようになります。ほとんどの場合、フレームグラバー側で取り込みを開始した後に、カメラ側でも取り込みを開始し、カメラのトリガーを開始する必要があります。

カメラの制御に関する詳細については、The Camera Control Library siso_genicamまたはThe Camera Link Serial Interface Library clsersisを参照してください。カメラのトリガーはこのドキュメントの範囲外ですが、アプレットのドキュメントには、ソフトウェアまたはハードウェア信号を介してフレームグラバーでカメラをトリガーするためのアプリケーションのオプションに関する詳細情報が記載されています。

int Fg_Acquire(
    Fg_Struct * fg,
    unsigned int dma,
    frameindex_t frames);

int Fg_stopAcquire(
    Fg_Struct * fg,
    unsigned int dma);

関数 Fg_Acquire() および Fg_stopAcquire() は、Memory管理関数との組み合わせでのみ使用でき、 Fg_AllocMem() および Fg_FreeMem() 標準取り込みモデルの使用に制限されています ACQ_STANDARD。これらの関数の使用は推奨されておらず、ドキュメント化もされません。代わりに、関数 Fg_AcquireEx() および Fg_stopAcquireEx() を使用する必要があります。

高度なまたは柔軟な Memory 管理を使用した画像取得#
int Fg_AcquireEx(
    Fg_Struct * fg,
    unsigned int dma,
    frameindex_t frames,
    int flags,
    dma_mem * mem);

int Fg_stopAcquireEx(
    Fg_Struct * fg,
    unsigned int dma,
    dma_mem * mem,
    int flags);

関数 Fg_AcquireEx() を呼び出して、フレームグラバー上の単一のDMAチャネルで画像取り込みを開始できます。この呼び出しにより、DMAチャネルが dma Memoryハンドルに結び付けられ、 mem したがって、画像データを受信するために割り当てられたMemoryが使用されます。

取り込みは、パラメータ frames で指定されたフレーム数に達するまで実行されます。 GRAB_INFINITE が次に渡される場合: frames、取得は無期限に実行されます。パラメータ flagsでは、取得モデルを選択できます。詳細については、 取得モデル のセクションを参照してください。

モデル 説明
ACQ_STANDARD フレームバッファ保護なしの連続取得
ACQ_BLOCK フレームバッファブロッキング付きの連続取得
ACQ_SELECT 手動フレームバッファ処理による完全アプリケーション制御の取得

の呼び出しで取得するフレーム数を指定する場合 Fg_AcquireEx()では、Framegrabber SDKが予期されるフレーム数を検出すると、取得が自動的に停止します。場合によっては、これが最後のフレームの処理時に予期しない動作につながることがあります。これを回避するには、取得モデルに加えて、 ACQ_NO_AUTOSTOP をパラメータ flagsで指定できます。 ACQ_NO_AUTOSTOP を使用する場合、要求されたフレーム数に達するとドライバはフレームの取得を停止しますが、Framegrabber SDKの残りの部分とフレームグラバーは、 Fg_stopAcquireEx() が呼び出されるまで取得モードのままになります。

取得を停止し、使用されているアプレットの実行状態をリセットするには、関数 Fg_stopAcquireEx() を呼び出す必要があります。パラメータ flagsを介して、停止モードを選択できます。

モード 説明
STOP_ASYNC 取得を直ちに停止
STOP_SYNC_TO_APC 非同期モードでの取得停止をコールバック関数に同期させます。
コールバックの完了を待つ時間(ミリ秒)は、パラメータ FG_APC_STOP_TIMEOUT を使用して設定できます。
STOP_SYNC 取得の停止をドライバと同期させます。
次の画像の転送完了を待つ時間(秒)は、パラメータ FG_STOP_TIMEOUT を使用して設定できます。
STOP_ASYNC_FALLBACK STOP_SYNC と組み合わせて使用できます。
停止を同期できなかった場合、STOP_ASYNC にフォールバックします。

同期モードの取得ループの作成#

同期モードでは、アプリケーションが新しい画像の受信を処理する必要があります。これは通常、特定の DMA チャンネルでの新しい画像の転送を待つ Framegrabber API が提供する関数のいずれかを呼び出す取得ループの形式で行われます。使用する関数を理解するには、詳細について Acquisition Models セクションを参照してください。各モデルのサンプル取得ループについては、対応するサブセクションに記載されています。

frameindex_t Fg_getLastPicNumberBlocking(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout);

関数 Fg_getLastPicNumberBlocking() は、関数 Fg_Acquire() との組み合わせでのみ使用でき、標準取得モデル ACQ_STANDARDに制限されています。この関数の使用は推奨されておらず、ドキュメントには記載されません。代わりに、関数 Fg_getLastPicNumberBlockingEx() または Fg_getImageEx() を使用する必要があります。

高度なまたは柔軟な Memory 管理を使用した画像の待機#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);

frameindex_t Fg_getImageEx(
    Fg_Struct * fg,
    int strategy,
    frameindex_t frame,
    unsigned int dma,
    unsigned int timeout,
    dma_mem * mem);

関数 Fg_getLastPicNumberBlockingEx() は、パラメータ frame で指定されたパラメータ timeout で指定された秒数以内に、指定されたDMAチャネルで到着することを待機します dma。最初のフレームの番号は0ではなく1です。この関数は、成功した場合は0より大きいフレーム番号を返し、失敗した場合は負のエラーコードを返します。

情報

返されるフレーム番号は、要求されたフレーム番号よりも大きくなる可能性があります。関数は常に利用可能な最新のフレーム番号を返すためです。つまり、関数を2回呼び出す間に複数のフレームが到着している可能性があり、アプリケーションは最新のフレームのみを処理するか、すべてのフレームを処理するかを判断する必要があります。

次の例は、簡単な取得ループを示しています ACQ_STANDARD:

const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        // process new images ...

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

関数 Fg_getImageEx() ははるかに複雑です。関数の動作と成功時のリターンコードの意味は、パラメータ strategy および timeout および使用中の取得モデルによって異なります。エラーが発生した場合、結果は常に負のエラーコードになります。さまざまな戦略の簡単な説明については以下で説明しますが、一般的に、この関数の使用は ブロッキング取得モデルセクションで説明されているユースケースに限定する必要があります。この関数をそれ以外の目的で使用することは推奨されず、本書の文脈ではこれ以上詳細には説明しません。

SEL_NEW_IMAGE: この関数ではタイムアウトを指定する必要があり、少なくとも1つの新しい画像が到着するのを待ちます。 ACQ_STANDARD および ACQ_SELECT では、最新の画像のフレーム番号が返されます。 ACQ_BLOCKでは、この関数は最新の画像のフレームバッファをブロックし、追加画像のフレームバッファのブロックを解除して、ブロックされた画像のバッファ番号を返します。

SEL_NEXT_IMAGE: ACQ_STANDARDでは、タイムアウトが指定されていない場合、受信した最新画像のバッファ番号が返されます。タイムアウトが指定されている場合、この関数は、前回の関数の呼び出しで受信した最後の画像の次、または関数が前回呼び出されなかった場合はフレーム番号1の次のフレームを待ちます。受信した最新の画像のフレーム番号が返されます。 ACQ_BLOCKでは、この関数は、まだブロックまたはブロック解除されていない、最初に受信した画像のフレームバッファをブロックし、ブロックされた画像のバッファ番号を返します。これ以上画像をブロックできず、タイムアウトが指定されている場合、関数はブロック操作を実行する前に、少なくとも1つの新しい画像が到着するのを待ちます。

SEL_ACT_IMAGE: ACQ_STANDARDでは、この関数の動作は、 SEL_NEXT_IMAGE が指定されている場合と同じになります。 ACQ_BLOCKでは、この関数は最新の画像のフレームバッファをブロックし、追加画像のフレームバッファのブロックを解除して、ブロックされた画像のバッファ番号を返します。これ以上画像をブロックできず、タイムアウトが指定されている場合、関数はブロック操作を実行する前に、少なくとも1つの新しい画像が到着するのを待ちます。

SEL_LAST_IMAGE: この関数は、この関数または Fg_getLastPicNumberBlockingEx()によって最後に返された値を返します。これは、前回の関数の呼び出し方法に応じて、最後のフレーム番号またはバッファ番号のいずれかになります。

SEL_NUMBER: この関数は、 Fg_getLastPicNumberBlockingEx().

次の例は、簡単な取得ループを示しています ACQ_BLOCK を使用して SEL_NEXT_IMAGE の動作を模倣します(取得されたすべての画像が処理されます)。

const int timeoutInSeconds = 10;

while (true) {
    // get new image
    const frameindex_t buffer =
        Fg_getImageEx(fg, SEL_NEXT_IMAGE, 0, dma, timeoutInSeconds, mem);

    if (buffer > 0) {
        // process new image ...
    } else {
        // handle error ...
    }
}

ドライバー画像取り込みタイムアウト FG_TIMEOUT#

関数 Fg_getImageEx() または Fg_getLastPicNumberBlockingEx()を呼び出す際、または非同期モード用のコールバック関数を設定する際に画像待機時間を指定するだけでなく、ドライバは画像転送割り込みの処理のコンテキストで画像取得も追跡します。パラメータ FG_TIMEOUT。もし FG_TIMEOUT が次のように設定されている場合、自動的に無効になります: FG_TIMEOUT_INFINITE で指定された秒数の間に画像データが受信されない場合、ドライバは画像取得を停止します FG_TIMEOUT_INFINITE です。 INT_MAX - 1) の場合、2つの画像を受信する際の時間間隔に関係なく、ドライバは取得を停止しません。

パラメータ FG_TIMEOUT の値は、取得の開始時にドライバに転送されます。取得開始後のパラメータへの変更は、取得を停止して再度開始するまでドライバには考慮されません。

ドライバが取得を停止した後、画像を待ち続けている関数呼び出しは FG_TIMEOUT_ERR を返し、取得停止後に画像を待つために呼び出された関数は FG_TRANSFER_NOT_ACTIVE.

情報

を返します。 FG_TIMEOUT です。 行いません FG_TIMEOUT_INFINITEではありませんが、ほとんどの場合1,000,000秒に設定されています(これは約277時間46分に相当します)。パラメータを明示的に設定することをお勧めします FG_TIMEOUT を FG_TIMEOUT_INFINITE 画像取得の開始前。

次の例は、ドライバーの画像取得タイムアウトを無効にする方法を示しています。

Fg_setParameterWithType(fg, FG_TIMEOUT, FG_TIMEOUT_INFINITE, dma);

フレームおよび取り込み情報#

int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

frameindex_t Fg_getStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

受信した各フレームについて、次の関数を呼び出すことで情報を取得できます Fg_getParameterEx():

パラメーター 説明 タイプ
FG_TRANSFER_LEN 転送された実際のバイト数 size_t
FG_TIMESTAMP_LONG 高解像度の画像Timestamp uint64_t
FG_TIMESTAMP_LONG_FREQUENCY 高解像度Timestamp周波数 uint64_t
FG_TIMESTAMP ミリ秒単位の画像のTimestamp uint32_t
FG_IMAGE_TAG イメージタグ uint32_t
FG_IMAGE_NUMBER フレーム番号 uint64_t

情報

フレーム番号情報は、Framegrabber SDKのバージョン5.9で追加されました。

各フレームの情報は無期限に保持されるわけではなく、対応するバッファが後続の転送のためにキューに入れられていない場合にのみ有効です。使用する取り込みモデルに応じて、関数にはフレーム番号またはバッファ番号が必要です。詳細はAcquisition Modelsのセクションを参照してください。

次の例は、指定されたフレームの Timestamp を要求する方法を示しています。

// get time stamp frequency
uint64_t frequency = 0;
Fg_getParameterEx(fg, FG_TIMESTAMP_LONG_FREQUENCY, &frequency, 0, nullptr, 0);

// ...

// get frame time stamp
uint64_t timestamp = 0
int result =
    Fg_getParameterEx(fg, FG_TIMESTAMP_LONG, &timestamp, dma, mem, frame);
if (result == FG_OK) {
    // this will probably be 'seconds since booting the computer' ...
    // it makes more sense when you calculate the difference
    // between timestamps of two frames
    double seconds =
        static_cast<double>(timestamp)/static_cast<double>(frequency);

    // ...
}

フレームバッファへのポインタを取得するには、関数 Fg_getImagePtrEx() を呼び出すことができます。各フレームのポインタは無期限に保持されるわけではなく、対応するバッファが後続の転送のためにキューに入れられていない場合にのみ有効です。使用する取り込みモデルに応じて、関数にはフレーム番号またはバッファ番号が必要です。セクション 取得モデル を参照してください。

次の例は、指定されたフレームのフレームバッファポインタを要求する方法を示しています。

// get a pointer to the frame buffer for the newest image
void * buffer = Fg_getImagePtrEx(fg, frame, dma, mem);

// get the actual number of bytes transferred
size_t length = 0;
int result =
    Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, frame);

if ((buffer != nullptr) && (result == FG_OK) && (length > 0)) {
        // process image data ...
}

関数 Fg_getStatusEx() を呼び出して次の一般的なステータス情報を要求することができ、その際パラメータ frame はこれらに対して無視されます。

Status 説明
NUMBER_OF_GRABBED_IMAGES 転送されたフレームの総数
NUMBER_OF_LAST_IMAGE によって報告された最後のフレーム番号 Fg_getLastPicNumberBlockingEx()
NUMBER_OF_NEXT_IMAGE 最後に報告されたフレームの次のフレーム番号
GRAB_ACTIVE 0:DMAチャネルがアクティブではありません
1:DMAチャネルがアクティブです

次の例は、DMAチャネルの Acquisition Status を要求する方法を示しています。

frameindex_t active =
    Fg_getStatusEx(fg, GRAB_ACTIVE, 0, dma, mem);
if (active == 1) {
    // the DMA channel is active ...
} else if (active == 0) {
    // the DMA channel is inactive ...
} else {
    // handle error ...
}

取得モデル#

Framegrabber APIには、3つの異なる取得モデルが用意されており、 Fg_AcquireEx():標準、ブロッキング、セレクティブ。これら3つの取り込みモデルはすべて、章で説明されているメモリモデルに基づいています Memory管理 このモデルでは、画像の取り込みに少なくとも2つのフレームバッファを使用します。

このセクションの例では、仮想メモリ内で連続する4つのフレームバッファで構成されるメモリバッファを使用します。

Memory Buffer Model

フレーム番号とバッファ番号#

Framegrabber API全体を通じてフレーム番号とバッファ番号が使用されており、どちらも型は frameindex_t.

です。フレーム番号は、 [1; FRAMEINDEX_MAX]の範囲内で厳密に単調増加する自然数であり、取得の開始以降に取得された画像の数を表しますが、フレーム番号に使用される型 frameindex_t は符号付き型であり、API内で負の Error Codes とフレーム番号の両方を返すために使用されます。特に32ビットアプリケーションでは、フレーム番号のオーバーフローを正しく処理するように注意する必要があります。 FRAMEINDEX_MAX に達すると、画像カウントは1に戻ります!(64ビットアプリケーションでは、非常に高いフレームレートであっても、画像カウンタのオーバーフローは数十万年後にならないと発生しません。)

対照的に、バッファ番号は画像データが存在するフレームバッファを指し、N個のバッファの場合、範囲は [1; N]です。ここで使用する例では、バッファ番号は1〜4の間であり、以下を指します FB0 … FB3 したがって、対応が行われます。

標準アクイジションモデル (ACQ_STANDARD)#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    dma_mem * mem);

標準的な画像取り込みモデルは、 ACQ_STANDARD を flags の呼び出しで渡すことによって選択されます Fg_AcquireEx()。すべてのフレームバッファには、画像データを取り込むドライバと、画像データを処理するアプリケーションの両方から常にアクセス可能です。

取り込みが開始されると、ドライバは最初のフレームバッファから始めて、画像データ転送用のフレームバッファをフレームグラバーに少なくとも1つキューイングします FB0。画像がコンピュータのMemoryに完全に転送されると、転送完了がソフトウェアに通知され、ドライバはさらに1つのフレームバッファをキューイングします。フレームグラバーは、次の画像のデータ転送を、キュー内の次のバッファ(この例では FB1.

)に対して続行します。(キューイングされるフレームバッファの数は、使用するフレームグラバー、ドライバのバージョン、Windowsレジストリの設定、Linuxドライバのパラメータなど、さまざまな要因によって異なります。ただし、標準的な取り込みモードでは、キューイングは常に線形的に行われ、最後のフレームバッファがキューイングされた後は再度 FB0 から開始されます。キューイングされるバッファの数は、コンピュータで達成できる最大フレームレートに影響を与える可能性がありますが、この影響は秒間約10,000フレームを超える場合にのみ測定可能です。)

ドライバは一貫した循環方式でフレームバッファを使用するため、関係性を用いてフレーム番号をバッファ番号に単純に変換できます bufferNumber = 1 + ((frameNumber - 1) % numberOfBuffers)。関数 Fg_getImagePtrEx() を使用すると、フレーム番号またはバッファ番号のいずれかのフレームバッファへのポインタを取得できます。

標準的な取り込みモデルでは、画像取り込みが画像処理を「オーバーラン」しないようにすることは、完全にアプリケーションの責任となります。これを確実に行うには、画像ソースのトリガーを画像処理と組み合わせてアプリケーションから制御するか、コンピュータシステムのフレームレートとパフォーマンスに合わせてバッファ数を慎重に調整するか、画像をスキップできるようにする必要があります。

前の画像の処理中にアプリケーションが単一の画像のみをトリガーするシナリオでは、処理中の画像データ用と画像データ転送用の2つのバッファで十分です。(アプリケーションが画像の処理が完全に完了した後にのみトリガーが生成されるようにする場合、実際には処理に1つのバッファで十分です。ただし、これはFramegrabber APIではサポートされておらず、どのような場合でもアプリケーションは少なくとも2つのバッファを割り当てる必要があります。)

アプリケーション側からの制御なしで画像が連続的に生成されるシナリオでは、画像ソースとドライバ内のバッファ処理の両方がフリーランニングと見なすことができます。次の例では、 FB0 および FB1 には有効な画像データが含まれています。 FB0 はアプリケーションによって処理されており、 FB1 は処理待ちの状態です。ドライバは少なくとも FB2 をキューイングしており、現在画像データが転送中です。この状況は、たとえすでにキューイングされている可能性があるとしても、 FB3 がまだ使用されていないため安全です。

Memory Buffer Model Safe

処理が完了した Fg_getLastPicNumberBlockingEx() の次のフレーム番号に対して関数 FB0 を呼び出すと、 FB1への転送がその間に完了していない場合、このケースでは単一の新しいフレーム( FB2 に転送された画像のフレーム番号)が返されます。

画像処理が画像取り込みよりも遅い場合、アプリケーションは次の処理に進んでいる可能性があります FB1. しかし、以下の例ではその間にさらに2つの画像が転送されており、 FB2 および FB3, そしてドライバーは以下で再開しています: FB0. 画像転送が完了すると、ドライバーは以下を使用します: FB1, そのためフレームグラバーが現在処理中のデータを上書きする可能性があります。このシナリオが安全であると言えるのは、以下が行われている間、画像ソースによって画像データが生成されていないことをアプリケーションが確実に確認できる場合のみです。 FB1 がまだ処理中です。

Memory Buffer Model Unsafe

処理が完了した Fg_getLastPicNumberBlockingEx() の次のフレーム番号に対して関数 FB0 が終了すると、2つの新しいフレームが返されます(以下に転送された画像のフレーム番号: FB3への転送がその間に完了していない場合、このケースでは単一の新しいフレーム( FB0 に転送された画像のフレーム番号)が返されます。

次の例では、すべてのフレームを処理するために、セクション「アクイジションループの記述」で示したアクイジションループの構造を拡張しています。

const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        for (frameindex_t frame = nextFrame; frame <= newestFrame; ++frame) {
                // get a pointer to the frame buffer for the newest image
                void * ptr =
                    Fg_getImagePtrEx(fg, frame, dma, mem);

            // get the actual number of bytes transferred
            size_t length = 0;
            int result =
                Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length,
                                  dma, mem, frame);

            if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
                    // process image data ...
            }
        }

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

アプリケーションが画像をスキップでき、受信した最新のフレームのみを処理する必要がある場合、取得ループから内側のforループを外し、代わりに以下のみを処理するようにします。 newestFrame.

関数 Fg_getImageEx() は、標準の取得モデルと組み合わせて使用しないでください。

非同期モードでは、Framegrabber APIが以下を呼び出します: Fg_getLastPicNumberBlockingEx() 新しい画像を待機するため、そしてフラグが設定されている場合は最新の画像に対してコールバック関数を1回呼び出し、設定されていない場合は受信した画像ごとに1回、複数回呼び出します。 FG_APC_BATCH_FRAMES が設定されていた場合、または設定されていなかった場合は複数回、受信した画像ごとに1回呼び出されます。コールバックは画像のフレーム番号を受け取ります。

非同期モードでフレームを処理するには、コールバック関数内でインナーループの内容を使用できます(ApcCallbackDataは、セクション「非同期モードのコールバック関数の登録」で説明されている構造です)。

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // get a pointer to the frame buffer for the newest image
        void * ptr =
            Fg_getImagePtrEx(context->fg, frame, context->dma, context->mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(context->fg, FG_TRANSFER_LEN, &length,
                              context->dma, context->mem, frame);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }
    } else {
        // handle error ...
    }

    return 0;
}

このようにして、コールバック関数は、以下が渡されたときに最新の画像のみを処理する場合と、 FG_APC_BATCH_FRAMES が以下に渡された場合、 flags を Fg_registerApcHandlerEx(), すべての画像を処理する場合の両方で使用できます。以下の場合、コールバック関数は新しい画像ごとに1回ずつ、複数回呼び出されます。 FG_APC_BATCH_FRAMES が渡されなかった場合。

ブロッキングアクイジションモデル (ACQ_BLOCK)#
frameindex_t Fg_getImageEx(
    Fg_Struct * fg,
    int strategy,
    frameindex_t frame,
    unsigned int dma,
    unsigned int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t buffer);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

frameindex_t Fg_getStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);
int Fg_setStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

情報

ブロッキング取得モデルで非同期モードを使用する場合の動作は、 ACQ_BLOCK Framegrabber APIのバージョン5.9で変更されました。

ブロッキング取得モデルは、以下を渡すことで選択されます: ACQ_BLOCK を flags の呼び出しで渡すことによって選択されます Fg_AcquireEx(). 各フレームバッファは、画像データ取得のためにドライバーが排他的にアクセスするか、あるいはアプリケーションが画像データを処理するためにキューに登録されるかブロックされます。フレームバッファの使用は、ブロックされている限り常に安全ですが、画像データ転送用の一意な未ブロックバッファがドライバーから利用できなくなる状況が発生した場合、画像が失われる可能性があります。

取り込みが開始されると、ドライバは最初のフレームバッファから始めて、画像データ転送用のフレームバッファをフレームグラバーに少なくとも1つキューイングします FB0画像がコンピュータのMemoryに完全に転送されると、転送完了がソフトウェアに通知され、フレームバッファがアプリケーション用にキューイングされます。アプリケーションが明示的または暗黙的にブロック解除するまで、ドライバーはそのバッファを使用しません。1つ以上のブロック解除されたフレームバッファが利用可能である限り、ドライバーはフレームグラバーに追加のフレームバッファをキューイングします。利用可能なブロック解除されたフレームバッファがなくなると、次と呼ばれる特別なフレームバッファが使用されます。 ダミーバッファ 画像アクイジションを常に実行し続けるために、フレームグラバーにキューイングされます。フレームグラバーは、次の画像のデータ転送をキュー内の次のバッファへ継続します。この例では、それは次のようになります。 FB1.

(サブセクション「標準アクイジションモデル」で述べたように、フレームグラバーにキューイングされるフレームバッファの数はさまざまな要因によって異なります。)

ダミーフレームバッファは無限に大きいと見なすことができ、任意のサイズのデータを吸収できますが、画像の処理という観点では意味のある方法ではありません。このため、ダミーバッファはアプリケーションからアクセスできず、ダミーバッファに転送された画像はすべて失われます。フレームが転送されるたびに次のバッファのキューイングが自動的に行われるため、ドライバーがキューイングに使用できる未ブロックのフレームバッファがない場合、少なくとも1つの画像が自動的に失われることを意味します。これは、データソースが停止され、フレームバッファが再び利用可能になってから初めて再起動された場合でも当てはまります!

同期モードでは、関数 Fg_getImageEx() 新しく取得された画像のフレームバッファを要求してブロックするには、を呼び出す必要があります。この関数は、ブロックされたフレームバッファのバッファ番号を返します。ブロッキング取得モデルには、以下のストラテジーが関連します。

ストラテジー 説明
SEL_NEXT_IMAGE 次のフレームのバッファ番号を返します。
このストラテジーは、転送された順序に従って1つずつ、各シングルフレームを処理するために使用されます。
SEL_ACT_IMAGE 最新のフレームのバッファ番号を返します。
このストラテジーは、画像処理がAcquisition Frame Rateよりも遅い場合にフレームをスキップできるようにするために使用されます。

上記のリストは完全なものではなく、ブロッキング取得モデルに関連するストラテジーのみが含まれています。

もし SEL_NEXT_IMAGE が使用されている場合、次のフレームバッファのみがブロックされ、他のすべてのバッファはアプリケーションが後で要求できるようにキューに残ります。もし SEL_ACT_IMAGE が使用されている場合、最新のフレームバッファのみがブロックされ、アプリケーション用にキューに入れられている他のすべてのフレームバッファはキューから削除され、暗黙的にブロック解除されます。

関数を呼び出すとき Fg_getImageEx() このモデルを使用する場合は、常に 0 を渡す必要があります frame。この関数を使用して特定のフレーム番号を待機したり、フレーム番号をバッファ番号に変換したりすることはできません。フレームバッファのフレーム番号を取得するには、関数 Fg_getParameterEx() を呼び出して渡すことができます FG_IMAGE_NUMBER パラメータ内で param、型変数のポインタ frameindex_t フレーム番号用、およびパラメータ内のバッファ番号用 buffer.

関数 Fg_getStatusEx() を呼び出して、ブロッキング取得モデルに関連する次のステータス情報を要求することができます。

Status 説明
NUMBER_OF_LOST_IMAGES 失われたフレームの数
NUMBER_OF_BLOCKED_IMAGES 現在ブロックされているフレームの数
NUMBER_OF_IMAGES_IN_PROGRESS 経由で利用可能なフレームの数 Fg_getImageEx()
BUFFER_STATUS 0: フレームバッファはブロックされていません
1: フレームバッファはブロックされています

関数 Fg_setStatusEx() 以前の呼び出しによって要求およびブロックされたフレームバッファのブロックを解除するために呼び出すことができます Fg_getImageEx():

Status 説明
FG_UNBLOCK 単一のフレームバッファのブロックを解除します
FG_UNBLOCK_ALL 現在ブロックされているすべてのバッファのブロックを解除します

FG_UNBLOCK_ALL また、まだ要求されずブロックされていない、アプリケーション用にキューに残っているバッファも削除されます。

関数を使用する場合 Fg_AcquireEx() 取得する画像の数を指定するには、正常に配信された画像だけでなく、失われた画像も考慮されます。これにより、予期しない結果が生じる可能性があります FG_TIMEOUT_ERR または FG_TRANSFER_NOT_ACTIVE 呼び出すときの結果 Fg_getImageEx() また、取得ループ内で配信された画像のみをカウントします。

前の画像の処理中にアプリケーションが単一の画像のみをトリガーするシナリオでは、処理される画像データ用に1つ、画像データを転送するために1つの計2つのバッファがあれば十分です。(バッファロックが行われるため、アプリケーションが画像の完全な処理後にのみトリガーが生成されるようにした場合でも、すべてのケースで少なくとも2つのバッファが必要です。)

アプリケーション側からの制御なしで画像が連続的に生成されるシナリオでは、画像ソースはフリーランニングとみなすことができます。ただし、ドライバーは、ブロックされていないバッファがまだ利用可能である場合にのみ、画像をアプリケーションに配信できます。次の例では、 FB0 および FB1 には有効な画像データが含まれています。 FB0 はアプリケーションによって処理されており、 FB1 は処理待ちの状態です。ドライバは少なくとも FB2 をキューイングしており、現在画像データが転送中です。この状況は、たとえすでにキューイングされている可能性があるとしても、 FB3 がまだ使用されていないため安全です。

Memory Buffer Model Safe

画像処理が画像取得よりも遅い場合、アプリケーションの処理が完了している可能性があります FB0, ブロックを解除して処理に進みました FB1. しかし、以下の例ではその間にさらに2つの画像が転送されており、 FB2 および FB3, そしてドライバーは以下で再開しています: FB0. 画像転送が完了したときに、アプリケーションの処理が完了していない場合 FB1 かつロックが解除されていない場合、ドライバーはキューイングに使用できる空きバッファを持たなくなります。ダミーバッファがキューに入れられ、取得時に少なくとも1枚の画像が失われますが、まだブロック解除されていないフレームバッファのデータ整合性は維持されます。

Memory Buffer Model Unsafe

次の例では、すべてのフレームを処理するために、セクション「アクイジションループの記述」で示したアクイジションループの構造を拡張しています。

const int timeoutInSeconds = 10;
while (true) {
    // get new image
    frameindex_t buffer =
        Fg_getImageEx(fg, SEL_NEXT_IMAGE, 0, dma, timeoutInSeconds, mem);

    if (buffer > 0)
        // get the frame number (if needed)
        uint64_t frame = 0;
        Fg_getParameterEx(fg, FG_IMAGE_NUMBER, &frame, dma, mem, buffer);

        // get a pointer to the frame buffer for the newest image
        void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // unblock frame buffer
        Fg_setStatusEx(fg, FG_UNBLOCK, buffer, dma, mem);
    } else {
        // handle error ...
    }
}

関数 Fg_getLastPicNumberBlockingEx() ブロッキング取得モデルと組み合わせて使用しないでください。

非同期モードでは、Framegrabber APIが以下を呼び出します: Fg_getImageEx() を使用して SEL_ACT_IMAGE フラグが設定されている場合は FG_APC_BATCH_FRAMES を使用し、設定されていない場合は SEL_NEXT_IMAGE を使用します。コールバック関数は、画像のバッファ番号を受け取ります。c

非同期モードでフレームを処理するには、コールバック関数内でif文を使用できます(ApcUserCallbackDataは、非同期モード用コールバック関数の登録セクションで説明されている構造体です):

int ApcUserCallback(frameindex_t buffer, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (buffer > 0) {
        // get the frame number (if needed)
        uint64_t frame = 0;
        Fg_getParameterEx(fg, FG_IMAGE_NUMBER, &frame, dma, mem, buffer);

        // get a pointer to the frame buffer for the newest image
        void * ptr =
            Fg_getImagePtrEx(context->fg, buffer, context->dma, context->mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(context->fg, FG_TRANSFER_LEN, &length,
                              context->dma, context->mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // unblock frame buffer
        Fg_setStatusEx(fg, FG_UNBLOCK, buffer, dma, mem);
    } else {
        // handle error ...
    }

    return 0;
}

このようにして、コールバック関数は、以下が渡されたときに最新の画像のみを処理する場合と、 FG_APC_BATCH_FRAMES が以下に渡された場合、 flags を Fg_registerApcHandlerEx(), すべての画像を処理する場合の両方で使用できます。以下の場合、コールバック関数は新しい画像ごとに1回ずつ、複数回呼び出されます。 FG_APC_BATCH_FRAMES が渡されなかった場合。

選択的取得モデル ACQ_SELECT#
frameindex_t Fg_getLastPicNumberBlockingEx(
    Fg_Struct * fg,
    frameindex_t frame,
    unsigned int dma,
    int timeout,
    dma_mem * mem);
int Fg_getParameterEx(
    Fg_Struct * fg,
    int param,
    void * value,
    unsigned int dma,
    dma_mem * mem,
    frameindex_t frame);

void * Fg_getImagePtrEx(
    Fg_Struct * fg,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);
int Fg_setStatusEx(
    Fg_Struct * fg,
    int status,
    frameindex_t buffer,
    unsigned int dma,
    dma_mem * mem);

情報

セレクティブアクイジションモデル ACQ_SELECT は、Framegrabber SDKバージョン5.9で追加されました。

セレクティブアクイジションモデルは、 ACQ_SELECT を flags の呼び出しで渡すことによって選択されます Fg_AcquireEx()を渡すことで選択されます。アプリケーションは、ドライバーによるフレームバッファの使用を完全に制御できます。

フレームバッファは、フレームグラバーでのキューイングに対して明示的に選択される必要があり、ドライバーは選択された正確な順序でフレームバッファをキューに入れます。取り込みが開始されると、ドライバーは、最初に選択されたフレームバッファを起点として、フレームバッファが1つでも選択されている場合にのみ、画像データ転送のためにフレームグラバー内のフレームバッファをキューに入れます。画像がコンピュータメモリに完全に転送されると、転送が完了したことがソフトウェアに通知され、フレームバッファは選択されているとはみなされなくなり、明示的に再度選択されるまでドライバーはそれを使用しなくなります。ドライバーは、利用可能な場合はさらに1つ以上のフレームバッファをキューに入れます。利用可能なフレームバッファがない場合、フレームバッファはキューに入りません。フレームグラバーは、次の画像のデータ転送をキュー内の次のバッファに続行します。フレームグラバー内のキューが空になると、内部バッファオーバーフローが発生し、画像が失われる可能性があります。

(サブセクション「標準アクイジションモデル」で述べたように、フレームグラバーにキューイングされるフレームバッファの数はさまざまな要因によって異なります。)

アプリケーションがフレームバッファの使用を完全に制御するため、バッファ番号の追跡もアプリケーションの責任となります。フレームバッファが常に同じ順序で選択されない限り、フレーム番号をバッファ番号に単純に変換する方法はありません。また、変換を実行するためのAPI関数もありません。

関数 Fg_setStatusEx() を呼び出して、 FG_SELECT_BUFFER を使用してバッファ番号を渡し、フレームバッファを選択できます。

話を単純にするため、以下の例では、取り込み開始後に4つのバッファすべてが FB0 … FB3 通常の順序で選択されると仮定します。さらに、画像が転送された後、それが処理され、バッファが順番に再度選択されます。このようにして、バッファのシーケンスは常に同じままであり、関係を使用してフレーム番号をバッファ番号に単純に変換できます。 bufferNumber = 1 + ((frameNumber - 1) % numberOfBuffers).

アプリケーション側からの制御なしで画像が連続して生成されるシナリオでは、画像ソースはフリーランニングとみなすことができます。ただし、ドライバーは、選択されたバッファが利用可能である限りにおいてのみ、アプリケーションに画像を配信できます。次の例では、 FB0 および FB1 有効な画像データを含んでおり、選択されていません。 FB0 はアプリケーションによって処理されており、 FB1 は処理待ちの状態です。ドライバは少なくとも FB2 をキューイングしており、現在画像データが転送中です。この状況は、たとえすでにキューイングされている可能性があるとしても、 FB3 がまだ使用されていないため安全です。

Memory Buffer Model Safe

処理が完了した Fg_getLastPicNumberBlockingEx() の次のフレーム番号に対して関数 FB0 を呼び出すと、 FB1への転送がその間に完了していない場合、このケースでは単一の新しいフレーム( FB2 に転送された画像のフレーム番号)が返されます。

画像処理が画像取得よりも遅い場合、アプリケーションの処理が完了している可能性があります FB0, を選択し、の処理に進みました FB1. しかし、以下の例ではその間にさらに2つの画像が転送されており、 FB2 および FB3, そしてドライバーは以下で再開しています: FB0. 画像転送が完了したときに、アプリケーションの処理が完了していない場合 FB1 を選択すると、ドライバーにはキューイングに使用できる空きバッファがなくなります。それ以上画像が到着しない限り、この状況は、 ACQ_BLOCKで発生するような暗黙的な画像の損失を引き起こしません。ただし、別の画像を受信するとすぐに、フレームグラバー内の内部メモリバッファがオーバーフロー状態になり、データ損失が発生する可能性があります。

Memory Buffer Model Unsafe

次の例では、すべてのフレームを処理するために、セクション「アクイジションループの記述」で示したアクイジションループの構造を拡張しています。

const frameindex_t numberOfBuffers = 4;
const int timeoutInSeconds = 10;

frameindex_t nextFrame = 1;
while (true) {
    // get new image
    const frameindex_t newestFrame =
        Fg_getLastPicNumberBlockingEx(fg, nextFrame, dma,
                                      timeoutInSeconds, mem);

    if (newestFrame > 0) {
        for (frameindex_t frame = nextFrame; frame <= newestFrame; ++frame) {
            // get the buffer number
            frameindex_t buffer = 1 + ((frame - 1) % numberOfBuffers);

            // get a pointer to the frame buffer for the newest image
            void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

            // get the actual number of bytes transferred
            size_t length = 0;
            int result =
                Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length,
                                  dma, mem, buffer);

            if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
                // process image data ...
            }

            // select frame buffer
            Fg_setStatusEx(fg, FG_SELECT_BUFFER, buffer, dma, mem);
        }

        nextFrame = (newestFrame < FRAMEINDEX_MAX) ? newestFrame + 1 : 1;
    } else {
        // handle error ...
    }
}

アプリケーションが画像をスキップでき、受信した最新のフレームのみを処理する必要がある場合は、 Fg_setStatusEx() を FG_SELECT_BUFFER とともに使用して、スキップされたバッファを選択する必要があります。そうしないと、アプリケーションに使用されないバッファが残ることになります。

関数 Fg_getImageEx() は、Selective Acquisitionモデルと組み合わせて使用​​することはできません。

非同期モードでは、Framegrabber APIが以下を呼び出します: Fg_getLastPicNumberBlockingEx() 新しい画像を待機するため、そしてフラグが設定されている場合は最新の画像に対してコールバック関数を1回呼び出し、設定されていない場合は受信した画像ごとに1回、複数回呼び出します。 FG_APC_BATCH_FRAMES が設定されていた場合、または設定されていなかった場合は複数回、受信した画像ごとに1回呼び出されます。コールバックは画像のフレーム番号を受け取ります。

非同期モードでフレームを処理するには、コールバック関数内で内部ループの内容を使用できます(ApcUserCallbackDataは、非同期モード用コールバック関数の登録セクションで説明されている構造体です):

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // get the buffer number
        frameindex_t buffer = 1 + ((frame - 1) % numberOfBuffers);

        // get a pointer to the frame buffer for the newest image
        void * ptr = Fg_getImagePtrEx(fg, buffer, dma, mem);

        // get the actual number of bytes transferred
        size_t length = 0;
        int result =
            Fg_getParameterEx(fg, FG_TRANSFER_LEN, &length, dma, mem, buffer);

        if ((ptr != nullptr) && (result == FG_OK) && (length > 0)) {
            // process image data ...
        }

        // select frame buffer
        Fg_setStatusEx(fg, FG_SELECT_BUFFER, buffer, dma, mem);
    } else {
        // handle error ...
    }

    return 0;
}

このようにして、コールバック関数は、以下が渡されたときに最新の画像のみを処理する場合と、 FG_APC_BATCH_FRAMES が以下に渡された場合、 flags を Fg_registerApcHandlerEx(), すべての画像を処理する場合の両方で使用できます。以下の場合、コールバック関数は新しい画像ごとに1回ずつ、複数回呼び出されます。 FG_APC_BATCH_FRAMES が渡されなかった場合。

フレームグラバーへのデータ転送#

制限事項

このセクションでは、VisualAppletsオペレーターを使用するアプリケーション向けの新しいAPIについて説明します。 DmaFromPCこのAPIには、次の制限があります。

  • これは暫定的な機能プレビューです。つまり、将来のバージョンのFramegrabber SDKでは、関数名や機能が変更される可能性があります。
  • これは、VisualAppletsオペレーターが含まれるアプレットでのみ機能します。 DmaFromPC通常のDMAチャネルにはAPIを使用しないでください。 DmaToPC または、Framegrabber SDKに付属するAdvanced Acquisition Appletsを使用してください。オペレーター DmaFromPC は、VisualAppletsバージョン3.4.0以降で使用できます。
  • 現在、Windowsでのみ実装されています。

VisualAppletsオペレーターを使用すると DmaFromPC、PCからフレームグラバーにデータを転送できます。アプリケーションの例としては、画像データのコプロセッシングや、フレームグラバーでの複雑な画像処理のための追加パラメータの提供などが挙げられますが、これらに限定されません。

Memoryの割り当て#

データを転送するバッファは、高度なメモリ管理に記載されている関数を使用して割り当てく必要があります(例):

const size_t bufferSize = 1024 * 1024;
const size_t numBuffers = 16;
const size_t totalSize = bufferSize * numBuffers;

dma_mem * mem = Fg_AllocMemEx(fg, totalSize, numBuffers);
if (mem != nullptr) {
    // use memory, send buffers ...

    Fg_FreeMem(fg, mem);
}

または、フレキシブルメモリ管理に記載されている関数を使用できます(例):

dma_mem * mem = Fg_AllocMemHead(fg, totalSize, numBuffers);
for (int i = 0; i < numBuffers; i++) {
    auto buffer = new uint8_t[bufferSize];
    Fg_AddMem(fg, buffer, bufferSize, i, mem);
}

バッファのサイズはすべて同じですが、1回ごとの転送のバイト数は個別に指定されます。データ転送のサイズは、オペレーターのParallelismの倍数である必要があり DmaFromPc、その値は32であり、上限はバッファのサイズです。

データ転送の開始#

 int Fg_startBufferQueue(
    Fg_Struct * fg,
    uint32_t dma,
    dma_mem * mem);

int Fg_stopBufferQueue(
    Fg_Struct * fg,
    uint32_t dma,
    int32_t flags);

フレームグラバーへのデータ転送を開始するには、関数 Fg_startBufferQueue()を呼び出します。この呼び出しによりDMAチャネルが結び付けられ dma Memoryハンドルに結び付けられ、 mem 、データ転送用に割り当てられたメモリが使用されます。

パラメータ dma 関数への Fg_startBufferQueue() は、VisualAppletsオペレーターを使用してPCに画像を転送するための通常のDMAチャネルの数によって決まります DmaToPC これはVisualAppletsデザインに存在します。VisualAppletsオペレーターのDMAチャネル DmaFromPC は常に最後のDMAチャネルになります。

すべてのデータの転送が完了したら、 Fg_stopBufferQueue() を呼び出すことで、バッファキューが停止し、DMAチャネルと使用されているメモリハンドル間の結び付きが解除されます。

データ転送のためのバッファのキューイング#

int Fg_queueBuffer(
    Fg_Struct * fg,
    frameindex_t buffer,
    uint64_t numBytesToTransfer,
    uint32_t dma,
    dma_mem * mem);

フレームグラバーへ転送するデータがバッファに書き込まれ、バッファの転送準備が整ったら、次を呼び出すことでバッファをバッファキューに入れることができます。 Fg_queueBuffer()キューに入れた各バッファについて、転送するバイト数を指定する必要があります。

最大16個のバッファをバッファキューに入れることができます。キュー内の次のバッファは、ドライバーによって自動的にフレームグラバーに転送されます。これにより、必要に応じてフレームグラバーへの連続したデータストリームを確保できます。

パラメータ mem は、バッファキューが開始される前にバッファがキューに入れられる場合にのみ必要です。 Fg_startBufferQueue() が呼び出された後、パラメータ mem はオプションであり、 NULL.

バッファ転送の完了待ち#

int Fg_waitForBuffers(
    Fg_Struct * fg,
    uint32_t dma,
    uint64_t timeout,
    void * /* reserved */,
    size_t /* reserved */);

関数 Fg_waitForBuffers() は、パラメータで指定された秒数以内に、少なくとも1つのバッファが完全に転送されるのを待機します timeout で指定された秒数以内に、指定されたDMAチャネルで到着することを待機します dma。この関数は、成功した場合は完全に転送されたバッファの数を返し、失敗した場合は負のエラーコードを返します。

を使用してキューに入れられたバッファのみを再利用でき Fg_queueBuffer() 、バッファの転送が完了したら新しいデータを埋めることができます。

VisualAppletsオペレーターのデータ転送モデル DmaFromPC は非常に似ています 選択的取得モデル。つまり、アプリケーションがバッファの使用を完全に制御するため、バッファ番号の追跡もアプリケーションの責任となります。バッファが常に同じ順序で選択されない限り、転送Counterをバッファ番号に変換する単純な方法はありません。また、この変換を実行するAPI関数もありません。

アプレットイベント#

Framegrabber SDKのインストールに含まれるアプレットは、フレームグラバーでの画像取り込みや処理に関連するさまざまなイベントについて、アプリケーションに通知することができます。このようなイベントの例としては、カメラから画像の最初または最後のピクセルを受信したときに生成されるフレーム開始(start of frame)またはフレーム終了(end of frame)イベント、あるいはトリガー入力信号ののエッジが検出されたときに生成されるトリガー入力立ち上がり(trigger input rising)やトリガー入力立ち下がり(trigger input falling)イベントがあります。VisualAppletsのユーザーは、設計内でイベントオペレーターを使用して、アプリケーションに必要なイベントを生成できます。

各イベントソースには一意の名前があり、イベントマスクと呼ばれる符号なし64ビット整数の一方のビットによって識別されます。このようにして、例えば複数のイベントソースの複数のイベントマスクに対してバイナリOR演算子を使用することにより、複数のビットを設定して複数のイベントソースをグループ化することができます | 。ただし、これはどのアプレットも最大64個のイベントソースしかサポートできないことを意味します。

イベントは、同期モードまたは非同期モードで配信できます。同期モードでは、アプリケーションによってイベントループを提供する必要があります。非同期モードでは、1つまたは複数のイベントが発生するたびに呼び出されるコールバック関数を登録できます。リソースの競合を引き起こす可能性があるため、両方のアプローチを1つのアプリケーション内で混用して使用しないでください。

イベントソースはコンピュータシステムに高い割り込み負荷をかける可能性があるため、各イベントソースを明示的に有効にする必要があり、必要な場合にのみアクティブ化する必要があります。

イベントが発生するたびに、イベントソースの割り込みを受信した時刻が記録されます。タイムスタンプに加えて、一部のイベントソースはイベントごとにイベントペイロードと呼ばれる追加データを生成できます。ペイロードを持つイベントは、複数のイベントソースに対して複数のビットを設定してグループ化することはできません。使用するアプレットのドキュメントを参照して、アプレット内のイベントソースが追加データを生成するかどうか、およびそのデータの解釈方法を確認してください。

イベント情報#

uint64_t Fg_getEventMask(
    Fg_Struct * fg,
    const char * name);

int Fg_getEventPayload(
    Fg_Struct * fg,
    uint64_t mask);

int Fg_getEventCount(
    Fg_Struct * fg);

const char * Fg_getEventName(
    Fg_Struct * fg,
    uint64_t mask);

イベントソースの名前が分かっている場合は、関数を呼び出すことで対応するビットを要求できます。 Fg_getEventMask()。イベント名が認識されない場合、関数は0を返します。

特定のイベントのペイロードサイズは、次の関数を呼び出して要求できます Fg_getEventPayload()。イベントマスクが単一の有効なイベントソースに対応している場合は0以上の値が返され、そうでない場合は負のエラーコードが返されます。

すべてのイベントソースを反復処理するには、関数 Fg_getEventCount() を呼び出して、アプレットがサポートするイベントソースの数を要求できます。また、関数 Fg_getEventName() を使用してイベントソースの名前を取得できます。これを次の例に示します。

int numEvents = Fg_getEventCount(fg);
for (int event = 0; event < numEvents; ++event) {
    // get the event mask for each event
    const uint64_t eventMask = (1 << event);

    const char * eventName = Fg_getEventName(fg, eventMask);
    if (eventName != nullptr) {
        std::cout << "Event " << event << " is " << eventName << std::endl;
    }
}

非同期イベント処理のためのコールバック関数の登録#

typedef int (* Fg_EventFunc_t)(
    uint64_t events,
    void * data,
    const struct fg_event_info * info);

int Fg_registerEventCallback(
    Fg_Struct * fg,
    uint64_t mask,
    Fg_EventFunc_t handler,
    void * data,
    unsigned int flags,
    struct fg_event_info * info);

int Fg_unregisterEventCallback(
    Fg_Struct * fg,
    uint64_t mask);

情報

Framegrabber SDKのバージョン5.9では、型 struct fg_event_data が削除され、関数 Fg_unregisterEventCallback() が追加されました。セクションを参照してください Plain Cにおける非同期イベント処理用のコールバック関数の登録解除 (旧インターフェース用)。

を使用して、 Fg_registerEventCallback()型の関数 Fg_EventFunc_t を登録すると、1つ以上のイベントソースのグループからイベントを受信したときにコールバックされるように設定できます。この関数は、特定のフレームグラバーとイベントマスクに対して登録され、呼び出される際に3つのパラメータが渡されます。コールバック関数の最初のパラメータは、イベントを受信したすべてのイベントソースのイベントマスクです。2番目のパラメータは、 Fg_registerEventCallback() の呼び出し時に指定されたポインタであり、コンテキスト構造体やクラスへのポインタ(例えば、画像処理を実装するクラスインスタンスの this の呼び出し時に渡されたポインターであり、画像処理を実装するクラスインスタンスのポインターです。3番目のパラメータは、 struct fg_event_info へのポインターであり、アプリケーション側で割り当てて Fg_registerEventCallback() の呼び出し時に渡す必要があり、イベントに関する情報を格納するために使用されます。

任意のフレームグラバーにおいて、同じイベントグループに対して登録できるコールバック関数は1つのみです。

コールバック関数は、Framegrabber APIによって提供されるイベントループから呼び出されます。これは、コールバック関数がイベントループのスレッドコンテキスト内で呼び出されることを意味します。また、コールバック関数が戻るまでにかかる時間がイベントループの一般的な管理オーバーヘッドに追加されること、およびその時間内に複数のイベントを受信している可能性があることも意味します。その時間内にイベントを受信した場合、コールバック関数は戻った直後に再び呼び出されます。

パラメータ flags の呼び出しで渡すことによって選択されます Fg_registerEventCallback()を介して、アプリケーションは、コールバック関数が呼び出されるたびに単一のイベントのみ配信されるようにするか、保留中のすべてのイベントがグループ化されるようにするかを選択できます。パラメータに FG_EVENT_DEFAULT_FLAGS を渡したときのデフォルトの動作は、 flags コールバック関数が呼び出されるたびに1つのイベントを配信することです。 FG_EVENT_BATCHED を渡すと、保留中のすべてのイベントがグループ化されます。

コールバック関数が不要になった後は、以下を呼び出すことで登録を解除できます。 Fg_unregisterEventCallback().

次の例は、画像取り込みの処理に必要な情報を保持する単純な構造体を使用してコールバック関数を登録する方法を示しています。

struct EventUserCallbackData
{
    Fg_Struct * fg;
    fg_event_info info;
    uint64_t mask;
};

int EventUserCallback(uint64_t events, void * data,
                      const struct fg_event_info * info)
{
    auto context = reinterpret_cast<EventUserCallbackData *>(data);

    // process events

    return 0;
}

void SetupEventUserCallback(EventUserCallbackData * context)
{
    // register callback function
    int result = Fg_registerEventCallback(
        context->fg, context->mask, &EventUserCallback, context,
        FG_EVENT_DEFAULT_FLAGS, &context->info);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

コンテキスト構造体の割り当てと管理はこの例には示されていません。ポインタは、コールバック関数が登録されている間、有効である必要があります。解決策の1つは、すべてをC++クラス内にまとめておくことです。C++クラスのコンテキストでコールバック関数を使用するには、静的関数を使用してコールバックハンドラを登録し、 this pointerは、クラスポインタにキャストしてそれに応じて使用できるコンテキストデータポインタとして使用する必要があります。

同期的なイベントの待ち受け#

uint64_t Fg_eventWait(
    Fg_Struct * fg,
    uint64_t mask,
    unsigned int timeout,
    unsigned int flags,
    struct fg_event_info * info);

アプリケーションは、 Fg_eventWait()を呼び出すことで、イベントソースのグループからのイベントを同期的に待機できます。 flags パラメータを使用すると、関数が呼び出されるたびに単一のイベントのみが返されるようにするか、保留中のすべてのイベントがグループ化されるようにするかを選択できます。 FG_EVENT_DEFAULT_FLAGS を渡したときのデフォルトの動作は、 flags を渡したときのデフォルトの動作は、関数が呼び出されるたびに最大1つのイベントを返すことです。 FG_EVENT_BATCHED を渡すと、保留中のすべてのイベントがグループ化されます。関数は、パラメータで指定されたイベントソースのいずれかでイベントを受信するまで待機します。 mask、またはパラメータで指定された秒数 timeout が経過しました。タイムアウトが発生するまでにイベントが受信されなかった場合、関数は 0 を返します。それ以外の場合は、受信されたイベントまたはイベントグループを含むマスクを返します。

イベントのアクティブ化#

int Fg_activateEvents(
    Fg_Struct * fg,
    uint64_t mask,
    int enable);

イベントソースがイベントを送信できるようになる前に、有効化する必要があります。を呼び出すことで、 Fg_activateEvents() イベントソースのグループを有効化または無効化できます。パラメータに 1 が渡された場合 enable、パラメータで渡されたイベントソースのグループ mask が有効になります。パラメータに 0 が渡された場合 enableは、無効化されます。アプリケーションで使用されなくなったすべてのイベントソースは、無効にする必要があります。

イベントソースは有効化された後いつでもイベントを発生させる可能性があるため、イベントソースを有効化するのは、次を使用してコールバックが登録された後、または Fg_registerEventCallback()、次を使用してイベントを待機している別のスレッドの準備が整った後でのみ行うことをお勧めします。 Fg_eventWait().

複数プロセスからのフレームグラバーの使用サポート#

アプリケーションによっては、異なるプロセスから単一のフレームグラバーへのアクセスが必要になる場合があります。簡単な例としては、別のプロセス(画像取得プロセスなど)のアクティビティを監視するプロセスがあります。別の例としては、最大 4 台のカメラが接続されたフレームグラバーのカメラをそれぞれ 1 台ずつ使用する、個別の画像取得プロセスが挙げられます。

Framegrabber API は、マスター/スレーブモードにより、このようなシナリオを部分的にサポートしています。マスター/スレーブプロセスを使用する場合は、その制限を理解することが重要です。また、2 つ以上のプロセスを同期させる必要があるときにアプリケーション開発者が直面する一般的な課題を理解することも重要です。Framegrabber API は複数のプロセスからのフレームグラバーの使用をサポートしていますが、フレームグラバーの初期化時にプロセスの起動を同期させるための非常に基本的な機能を超えるプロセス間同期はサポートしていません。汎用のプロセス間通信および同期には、他のオペレーティングシステムの機能またはサポートライブラリを使用する必要があります。

マスター/スレーブモードの特有の制限の1つは、2つのプロセスがフレームgrabber上の同じPropertyを制御しようとした場合、後から実行されたプロセスが「勝者」となり、最初のプロセスの動作を上書きすることです。最初のプロセスは上書きされたことさへ気づかず、フレームgrabberの状態について誤った前提を持つ可能性があります。(プロセス間通信を使用してプロセス間で状態を同期するための実験的機能が存在しますが、このアプローチには独自の制約があり、パラメータおよび取得同期の実験的サポートセクションで説明します。)

一般的な推奨事項は、プロセスが固有のタスクを引き受け(アプレットのパラメータと Property に関してタスクが重複しない)、他のプロセスの存在を意識する必要がないようにプロセスを設計することです。例外の 1 つとして、アプレットの読み取り専用 Property にのみアクセスするか、プロセス間通信手段を介して他のプロセスから情報を収集する監視プロセスがあります。

もう 1 つの制限として、マスタープロセスのみがフレームグラバーを完全に初期化しますが、基本的な初期化は各プロセスで行う必要があるという点があります。この基本的な初期化は、画像取得やカメラ検出をすでに開始している以前のプロセスと競合する可能性があります。

初期化中のプロセスの同期#

int Fg_InitLibrariesEx(
    const char * path,
    unsigned int flags,
    const char * id,
    unsigned int timeout);

void Fg_AbortInitLibraries();

void Fg_InitLibrariesStartNextSlave();
Fg_Struct * Fg_InitEx(
    const char * applet,
    unsigned int board,
    int flags);

Fg_Struct * Fg_InitConfigEx(
    const char * config,
    unsigned int board,
    int flags);

複数のプロセスを同期する場合、Frameグラバー API が提供する同期ポイントは、 Fg_InitLibrariesEx() の呼び出しです。と同様に、 Fg_InitLibraries()呼び出しへの最初のパラメータは使用されず、アプリケーションは常に nullptr.

を渡す必要があります。同期するプロセスはグループを形成し、同期ではグループ内のプロセスのみが考慮されます。同期対象のプロセスグループは、パラメータ idによって識別されます。このようにして、複雑なアプリケーションに複数の独立した同期グループを持たせることができます。グループを識別する文字列は空にせず、使用しているオペレーティングシステムのファイル名で使用可能な文字のみで構成する必要があります。アプリケーションで使用される識別子を次で開始することは siso- 推奨されません。プレフィックス siso- は Framegrabber API による使用のために予約されていると見なす必要があります。

同期動作は、パラメータを設定することで構成できます。 flags次の値とマクロをパラメータで使用できます。 flags:

フラグ 説明
FG_INIT_LIBRARIES_SINGLE デフォルトの初期化、同期なし
FG_INIT_LIBRARIES_MASTER マスター初期化、スレーブ同期の準備
FG_INIT_LIBRARIES_SLAVE スレーブ初期化、マスターの待機
FG_INIT_LIBRARIES_SEQUENTIAL 厳密なシーケンシャル起動
FG_INIT_LIBRARIES_AUTOSTART_ON_INIT フレームgrabberの初期化時に次のスレーブを開始
FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY(n) スレーブ優先度の設定
FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES(n) スレーブ数の設定

を使用して、 FG_INIT_LIBRARIES_SINGLE は、次を呼び出すことと同じです。 Fg_InitLibraries().

を使用して、 FG_INIT_LIBRARIES_SEQUENTIAL は、マスタープロセスから優先度が最も高いスレーブプロセスのみを起動します。2 番目に優先度が高いスレーブプロセスは、最も優先度が高いスレーブプロセスから起動する必要があり、以下同様となります。これにより、プロセスの初期化の厳密な順序が保証されます。もし FG_INIT_LIBRARIES_SEQUENTIAL は同期グループ内で使用されるため、マスタープロセスを含むすべてのプロセスで指定する必要があります。マクロ FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY() は、 FG_INIT_LIBRARIES_SEQUENTIAL を使用する場合にすべてのスレーブプロセスで使用する必要があり、スレーブプロセスの優先度を定義します。最高優先度は1、最低優先度は63です。グループ内の各プロセスには一意の優先度が必要であり、優先度は隙間が生じないように割り当てる必要があります(プロセス2がプロセス3の起動を求めていてもプロセス3が存在しない場合、誰もプロセス4を起動しません)。マクロ FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES() は、 FG_INIT_LIBRARIES_SEQUENTIAL を使用する場合にマスタープロセスで使用する必要があり、スレーブプロセスの数を定義します。許可される最小値は1、最大値は63です。

の呼び出しにおける最後のパラメータ Fg_InitLibrariesEx() は、エラーがアプリケーションに報告されるまでにプロセスがスケジューリングされるのを待機する時間をミリ秒単位で指定します。

通常マスタープロセスと呼ばれるグループの最初のプロセスは、 Fg_InitLibrariesEx() が呼び出されたときにグループを確立します。通常スレーブプロセスと呼ばれる後続のすべてのプロセスは、スケジューリングされるのを待つために、対応する Fg_InitLibrariesEx() の呼び出しで待機することを選択できます。1つ以上のスレーブの起動は、マスタープロセスでの Fg_InitLibrariesStartNextSlave() の呼び出しによってトリガーされます。関数 Fg_InitLibrariesStartNextSlave() は、プロセスが Fg_Init(), Fg_InitEx(), Fg_InitConfig() または Fg_InitConfigEx().

の呼び出しを介してフレームグラバーを初期化するときに自動的に呼び出すことができます。 Fg_InitLibraries() 関数は通常の状況下では失敗しないはずですが、同期を使用する場合の Fg_InitLibrariesEx() については同じことが言えません。待機時間を適切に指定し、それに応じてエラーを処理してください。

マルチスレッドアプリケーションでは、 Fg_InitLibrariesEx() の呼び出しでの待機は、 Fg_AbortInitLibraries()を呼び出すことで別のスレッドから中断できます。これにより、中断された呼び出しによってエラーが報告されます。

マスタープロセスでは Fg_Init() または Fg_InitConfig() の呼び出しを使用してフレームグラバーを初期化できますが、すべてのスレーブプロセスは Fg_InitEx() または Fg_InitConfigEx() を呼び出して FG_INIT_FLAG_SLAVE パラメータ内で flagsを渡す必要があります。それぞれ Fg_InitEx() または Fg_InitConfigEx() を FG_INIT_FLAG_DEFAULT は、次を呼び出すことと同じです。 Fg_Init() または Fg_InitConfig()と共に呼び出します。

次の例は、マスタープロセスが2つのスレーブプロセスを使用して厳密に順次的なスケジューリングのために同期グループを設定する方法を示しています。マスターは Fg_InitLibrariesStartNextSlave() さらなる初期化の後に最初のスレーブプロセスを開始するには:

const char * syncGroupId = "example";

int result =
    Fg_InitLibrariesEx(
        nullptr,
        FG_INIT_LIBRARIES_MASTER
            | FG_INIT_LIBRARIES_SEQUENTIAL
            | FG_INIT_LIBRARIES_SET_NUMBER_OF_SLAVES(2),
        syncGroupId,
        0);

if (result == FG_OK) {
    const char * applet = "Acq_SingleCXP12Area";

    Fg_Struct * fg = Fg_Init(applet, 0);
    if (fg != nullptr) {
        // further initialization ...

        Fg_InitLibrariesStartNextSlave();

        // use frame grabber ...
    }

    Fg_FreeLibraries();
}

この例のスレーブプロセスは、呼び出しで指定される優先度を除いて、すべて同一です。 Fg_InitLibrariesEx()ここでは最初のスレーブプロセスのみを示しています。スレーブプロセスは, FG_INIT_LIBRARIES_AUTOSTART_ON_INIT を使用して、次のスレーブプロセスを暗黙的に開始します。呼び出し: Fg_InitEx() が呼び出されます:

const char * syncGroupId = "example";

int result =
    Fg_InitLibrariesEx(
        nullptr,
        FG_INIT_LIBRARIES_SLAVE
            | FG_INIT_LIBRARIES_SEQUENTIAL
            | FG_INIT_LIBRARIES_AUTOSTART_ON_INIT
            | FG_INIT_LIBRARIES_SET_SLAVE_PRIORITY(1),
        syncGroupId,
        10000);

if (result == FG_OK) {
    const char * applet = "Acq_SingleCXP12Area";

    Fg_Struct * fg = Fg_InitEx(applet, 0, FG_INIT_FLAG_SLAVE);
    if (fg != nullptr) {
        // use frame grabber ...
    }

    Fg_FreeLibraries();
}

スレーブプロセスがマスタープロセスよりも前に開始された場合、マスタープロセスが開始されるのを Fg_InitLibrariesEx() の呼び出しで待機します。マスタープロセスが Fg_InitLibrariesStartNextSlave() を呼び出すと、スレーブプロセスが実行スケジュールに登録され、 Fg_InitLibrariesEx() は FG_OKの呼び出しが完了します。マスタープロセスが開始されない場合、またはスレーブの待機時間が切れる前に初期化が完了しない場合、スレーブは実行スケジュールに登録されず、 Fg_InitLibrariesEx() の呼び出しはタイムアウトエラーを返します。

Framegrabber SDKと共にインストールされるツール microDisplay X は、マスター/スレーブ同期をサポートしており、スレーブプロセスはグループID siso-microdisplay-masterを使用して microDisplay X と同期できます。フラグ FG_INIT_LIBRARIES_SEQUENTIAL は microDisplay X ではサポートされていません。

パラメータおよび取り込み同期の実験的サポート#

情報

パラメータおよび取り込みの同期に対する実験的サポートは、Framegrabber SDK バージョン 5.9 で追加されました。

Framegrabber API は、プロセス同期グループ全体で、すべてのパラメータ変更と取り込みの状態を同期するための実験的サポートを提供します。パラメータおよび取り込みの同期を有効にするには, FG_INIT_FLAG_PARAM_SYNC をパラメータ flags の呼び出しで渡すことによって選択されます Fg_InitEx() または Fg_InitConfigEx() に追加する必要があります(グループ内のすべてのプロセスに対して)。

ただし、パラメータおよび取り込みの同期を使用する際には、いくつか考慮すべき点があります。

まず、Framegrabber API が提供する同期は、オペレーティングシステムが提供するプロセス間通信メカニズムを使用しています。パラメータの取得および設定はプロセス内でローカルに行われなくなり、複数のプロセス間で同期させる必要があるため、これらの操作のレイテンシとジッターが増加します。ほとんどのアプリケーションでは、これらのデメリットは問題になりません。ただし、アプリケーションがリアルタイムオペレーティングシステムを使用しており、1つ以上のパラメータの取得または設定がリアルタイムクリティカルとみなされる場合は、パラメータおよび取り込みの同期を有効にすべきではありません。 FG_INIT_FLAG_PARAM_SYNC が明示的に使用されない場合、パラメータおよび取り込みの同期は有効にならず、この実験的機能は、Framegrabber API の以前のバージョンと比較してパフォーマンスに影響を与えません。

2つ目に、同期を使用する場合、取り込みを制御できるのはマスタープロセスまたはスレーブプロセスのいずれか一方のみであり、両方同時に制御することはできません。同期グループ内において、マスタープロセスでの取り込みを1つ以上のスレーブプロセスでの取り込みと混在させることはできません。ほとんどの場合、取り込みは1つ以上のスレーブプロセスで行うべきであり、 FG_INIT_FLAG_ACQUISITION_SLAVE をパラメータ flags の呼び出しで渡すことによって選択されます Fg_InitEx() または Fg_InitConfigEx() に追加する必要があります(マスタープロセスに対して)。

不均一メモリアクセス(NUMA)のサポート#

int Fg_NumaPinThread(
    Fg_Struct * fg);

void * Fg_NumaAllocDmaBuffer(
    Fg_Struct * fg,
    size_t size);

int Fg_NumaFreeDmaBuffer(
    Fg_Struct * fg,
    void * ptr);

不均一メモリアクセス(NUMA)を使用するマルチプロセッサコンピュータでは、各物理プロセッサが独自にMemoryと周辺バスを持っています。プロセスが実行中の物理プロセッサ上のリソースのみにアクセスしている限り、アクセス速度はシングルプロセッサコンピュータと同等で、対称型マルチプロセッシング(SMP)を使用するマルチプロセッサコンピュータよりもかなり高速です。ただし、ある物理プロセッサで実行中のプロセスが、別の物理プロセッサに属するリソースにアクセスしようとする場合、データが2つの物理プロセッサ間で移動する必要があり、アクセス速度が低下します。詳細については、Wikipediaの不均一メモリアクセスに関する記事を参照してください。

NUMA コンピューター上で実行されるアプリケーションをサポートするには、フレームグラバーにアクセスするすべてのスレッドを、デバイスがローカルに接続されている物理プロセッサーに固定(ピン留め)する必要があります。これを行うには、次を呼び出します。 Fg_NumaPinThread() パラメーターにアクセスしたり、フレームグラバーでの取り込みを制御したりする各スレッドのコンテキストで実行します。

さらに、メモリも同じ物理プロセッサー上にローカルに割り当てる必要があります。アプリケーションが Framegrabber API が提供する割り当て関数を使用する場合、これは自動的に行われます。ただし、アプリケーションが次を使用する場合、 Fg_AllocMemHead() および Fg_AddMem()、NUMA 対応のメモリ割り当てを使用してメモリを割り当てる必要があります。Framegrabber API は次の関数を提供します。 Fg_NumaAllocDmaBuffer() および Fg_NumaFreeDmaBuffer() フレームグラバーがローカルに接続されている同じ物理プロセッサー上でメモリを割り当ておよび解放します。

アプリケーションがメモリの割り当てに他の NUMA 対応関数を使用する場合、関数 Fg_getIntSystemInformationForBoardIndex() を使用して呼び出すことができます INFO_DRIVERGROUPAFFINITY ドライバー IRQ グループアフィニティを提供し、関数 Fg_getInt64SystemInformationForBoardIndex() を使用して呼び出すことができます INFO_DRIVERAFFINITYMASK を使用して、デバイスのドライバー IRQ プロセッサーアフィニティマスクを提供します。

一部の NUMA コンピューターには、他にも制限がある場合があります。たとえば、一部の NUMA コンピューターは周辺バスへのアクセスを分散するように設計されており、単一のデバイスが帯域幅のすべてまたは大部分を使用することを許可していません。これはほとんどのサーバーアプリケーションには有益ですが、画像取り込みおよび処理アプリケーションの場合、この戦略によりフレームグラバーデバイスで使用できる帯域幅が制限される可能性があります。

Plain Cを使用する際の考慮事項#

アプリケーションがプレーン C コンパイラの使用に制限されている場合、利便性や型安全性のために Framegrabber API が提供する C++ ラッパーの一部を使用できません。この章では、C++ ラッパーによって使用される根底にある機能の使用方法をトピックごとに説明します。

Plain Cにおけるシステム情報#

int Fg_getSystemInformation(
    Fg_Struct * fg,
    enum Fg_Info_Selector info,
    enum FgProperty property,
    int arg,
    void * buffer,
    unsigned int * size);

セクション 一般的なシステム情報 および ボード固有のシステム情報 章の システム情報 では、システム全般または特定のフレームグラバーに関するさまざまな情報を取得するための関数群が説明されています。これら2つの章の関数はすべて、関数のC++ラッパーです。 Fg_getSystemInformation().

関数 Fg_getSystemInformation() 要求された情報を常に文字列として返し、関数に渡されたバッファーに格納します。十分なサイズのバッファーを割り当てるには、パラメーターに使用される変数を初期化することでバッファーのサイズを要求できます。 size を 0 に設定して渡す NULL を渡したときのデフォルトの動作は、 buffer 呼び出し時に指定します。要求された情報が数値型である場合、情報を正常に要求した後に文字列を変換する必要があります。

セクションで説明されているように、システム全般に関する情報を取得するには、 一般的なシステム情報、関数 Fg_getSystemInformation() を呼び出す必要があります NULL パラメーターに渡される fg およびパラメーターに 0 arg.

たとえば、コンピューターにインストールされているフレームグラバーの数は、次のように要求できます。

int numBoards = 0;
char buffer[256];
unsigned int size = sizeof(buffer);
int result =
    Fg_getSystemInformation(NULL, INFO_NR_OF_BOARDS, PROP_ID_VALUE,
                            0, buffer, &size);
if (result == FG_OK) {
    numBoards = atoi(buffer);
    std::cout << "Number of boards: " << numBoards << std::endl;
}

セクションで説明されているように、特定のフレームグラバーに関する情報を取得するには、 ボード固有のシステム情報、関数 Fg_getSystemInformation() は、パラメーターに渡されたフレームグラバーへのハンドルを予期するか、 fgまたは、パラメーターに渡されたボードインデックス arg.

たとえば、次のコードはボードの種類と名前を要求します。

const int boardIndex = 0;

char buffer[256];
unsigned int size = sizeof(buffer);

int boardType = 0;
std::string boardName;
int result =
    Fg_getSystemInformation(NULL, INFO_BOARDTYPE, PROP_ID_VALUE,
                            boardIndex, buffer, &size);
if (result == FG_OK) {
    boardType = atoi(buffer);

    size = sizeof(buffer);
    result =
        Fg_getSystemInformation(NULL, INFO_BOARDNAME, PROP_ID_VALUE,
                                boardIndex, buffer, &size);
}
if (result == FG_OK) {
    boardName = buffer;

    std::cout << "Board #" << boardIndex
              << " is a " << boardName
              << " (type " << std::hex << boardType
              << std::dec << ")" << std::endl;
}

入力に追加の引数を必要とする情報を要求する場合、バッファーは双方向で機能します。追加の引数は、呼び出し前に文字列としてバッファーに格納する必要があります。呼び出し中、バッファーで渡された引数が使用され、要求された情報がバッファーに書き込まれるため上書きされます。

Plain Cにおけるパラメータ値へのアクセス#

int Fg_getParameterWithType(
    Fg_Struct * fg,
    int id,
    void * value,
    unsigned int dma,
    enum FgParamTypes type);

int Fg_freeParameterStringWithType(
    Fg_Struct * fg,
    int id,
    void * value,
    unsigned int dma,
    enum FgParamTypes type);
int Fg_setParameterWithType(
    Fg_Struct * fg,
    int id,
    const void * value,
    unsigned int dma,
    enum FgParamTypes type);

セクション パラメータ値へのアクセス 章の アプレットパラメータの操作では、最も一般的な型のPropertyを要求するためのC++ラッパーについて説明しています。プレーンCからPropertyにアクセスする場合、またはC++ラッパーが存在しない型のPropertyにアクセスするには、関数 Fg_getParameterWithType() および Fg_setParameterWithType() を使用できます。呼び出しには一致する型の変数が必要であり、対応する FgParamTypes 値はパラメータで渡す必要があります type を呼び出しで使用します。型値についてはセクション パラメータタイプ で説明されており、特定のPropertyの型を確認するにはアプレットのマニュアルを参照する必要があります。

たとえば、次のコードではアプレットの最初のDMAチャネルの幅を1024に設定します。

const int dma = 0;
const int width = 1024;
int result = FG_INVALID_PARAMETER;
int paramId = Fg_getParameterIdByName(fg, "FG_WIDTH");
if (paramId > 0) {
    result =
        Fg_setParameterWithType(fg, paramId, &width, dma,
                                FG_PARAM_TYPE_INT32_T);
}

を呼び出す際の特殊なケースの1つは Fg_getParameterWithType() であり、これは文字列パラメータを表します。十分なサイズのバッファを割り当てるために必要な文字列の長さは、 FG_PARAM_TYPE_CHAR_PTR を呼び出して要求できますが、 Fg_getParameterPropertyEx()これは動的パラメータにアクセスする最も安全な方法ではありません。より良いアプローチは、代わりに FG_PARAM_TYPE_CHAR_PTR を使用して FG_PARAM_TYPE_CHAR_PTR_PTR の型のパラメータを要求することです。この要求により適切なサイズのバッファが割り当てられ、 Fg_freeParameterStringWithType() 値が不要になった後に呼び出すことで解放できます。

次の例は、 FG_PARAM_TYPE_CHAR_PTR_PTRの使用方法を示しています(ただし、 paramId が FG_PARAM_TYPE_CHAR_PTR:

const char * val = NULL;
int result =
    Fg_getParameterWithType(fg, paramId, &val, dma,
                            FG_PARAM_TYPE_CHAR_PTR_PTR);
if (result == FG_OK) {
    // use the string value stored in val ...

    Fg_freeParameterStringWithType(fg, paramId, val, dma,
                                   FG_PARAM_TYPE_CHAR_PTR_PTR);
}

型のパラメータであると仮定します)。 Fg_freeParameterStringWithType() の呼び出しは、 char *を受け取りますが、実際には char **.

フィールドパラメータへのアクセス#
struct FieldParameterAccess {
    enum FgParamTypes vtype;
    unsigned int index;
    unsigned int count;
    union {
        int32_t * p_int32_t;
        uint32_t * p_uint32_t;
        int64_t * p_int64_t;
        uint64_t * p_uint64_t;
        double * p_double;
    };
};

ではありません。フィールドパラメータは、同じ型の2つ以上の値の配列を表すパラメータです。典型的な例は、ピクセル値の再マップに使用できるルックアップテーブルです。フィールドパラメータの型は FG_PARAM_TYPE_STRUCT_FIELDPARAMINT, FG_PARAM_TYPE_STRUCT_FIELDPARAMINT64 または FG_PARAM_TYPE_STRUCT_FIELDPARAMDOUBLE.

にすることができます。 PROP_ID_FIELD_SIZE セクションで説明されているように パラメータPropertyへのアクセス 章の アプレットパラメータの操作。必要に応じてセクション Plain CにおけるパラメータPropertyへのアクセス も参照してください。

を要求することで決定できます。必要に応じて、「Accessing Parameter Properties in Plain C」セクションも参照してください。フィールドパラメータの配列内の値を要求または変更するには、 Fg_getParameterWithType() および Fg_setParameterWithType() 関数を呼び出す必要があります。その際、 struct FieldParameterAccess および FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS のインスタンスを使用し、 typeパラメータで渡す必要があります。 vtype のメンバー struct FieldParameterAccess の enum FgParamTypes は、フィールドパラメータ自体の型ではなく、フィールド内の単一の値の型に対応する値に設定する必要があります。メンバー index および count 関数呼び出しにおいて、フィールドパラメータの配列に対するオフセットと、要求または提供されるアイテム数を指定します。最後に、フィールド内の単一の値の型に対応する共用体内のポインタを、入力時に変更する値を格納した事前に割り当てられたバッファで初期化する必要があります。 Fg_setParameterWithType() が呼び出されたとき、または Fg_getParameterWithType() が呼び出された後に配列に現在格納されている値となります。

次の例では、以下を仮定して、ルックアップテーブル内の最初の256個の値を要求します。 paramId が FG_PARAM_TYPE_STRUCT_FIELDPARAMINT であり、フィールド自体が少なくとも256個の FG_PARAM_TYPE_INT32_T:

int32_t field[256];
struct FieldParameterAccess fpa;
fpa.vtype = FG_PARAM_TYPE_INT32_T;
fpa.index = 0;
fpa.count = 256;
fpa.p_int32_t = &field;
int result =
    Fg_getParameterWithType(fg, paramId, &fpa, dma,
                            FG_PARAM_TYPE_STRUCT_FIELDPARAMACCESS);
if (result == FG_OK) {
    // work with the values in field ...
}

Plain CにおけるパラメータPropertyへのアクセス#

int Fg_getParameterProperty(
    Fg_Struct * fg,
    int id,
    enum FgProperty property,
    void * buffer,
    int * size);

int Fg_getParameterPropertyEx(
    Fg_Struct * fg,
    int id,
    enum FgProperty property,
    int dma,
    void * buffer,
    int * size);

セクション パラメータPropertyへのアクセス 章の アプレットパラメータの操作では、最も一般的な型のProperty属性を要求するためのC++ラッパーについて説明しています。プレーンCからProperty属性にアクセスする場合、またはC++ラッパーが存在しない型のProperty属性にアクセスするには、関数 Fg_getParameterPropertyEx() を使用できます。関数 Fg_getParameterProperty() の使用は推奨されません。この関数呼び出しは暗黙的にDMAチャネル0を使用しますが、パラメータPropertyはチャネルによって異なる場合があるためです。

関数 Fg_getParameterPropertyEx() は、1つのケースを除き、要求された情報を関数に渡されるバッファに格納される文字列として返します。十分なサイズのバッファを割り当てるには、パラメータに使用される変数を初期化することでバッファサイズを要求できます。 size を 0 に設定して渡す NULL を渡したときのデフォルトの動作は、 buffer 呼び出し時に指定します。要求された情報が数値型である場合、情報を正常に要求した後に文字列を変換する必要があります。

paramId が次の型のパラメーターであると仮定して、パラメーターの最小値を取得する方法を次の例に示します。 FG_PARAM_TYPE_INT32_T:

char buffer[256];
int size = sizeof(buffer);

int32_t minVal = 0;
int result =
    Fg_getParameterPropertyEx(fg, paramId, PROP_ID_MIN, dma, buffer, &size);
if (result == FG_OK) {
    minVal = atoi(buffer);

    // work with the property ...
}
列挙値のPropertyへのアクセス#
struct FgPropertyEnumValues {
    int32_t value;
    char name[1];
};

#define FG_PROP_GET_NEXT_ENUM_VALUE(pev) ...

列挙型パラメータのProperty PROP_ID_ENUM_VALUES を要求する場合、 Fg_getParameterPropertyEx() の呼び出しはPropertyを文字列としては返しません。代わりに、バッファは struct FgPropertyEnumValuesを使用してFillされます。マクロ FG_PROP_GET_NEXT_ENUM_VALUE() を使用して、バッファ内の要素を反復処理できます。便宜上、Property PROP_ID_IS_ENUM は列挙型パラメータに必要なバッファのサイズを返します。

次の例は、paramIdが列挙型パラメータであると仮定して、パラメータの列挙値Propertyを取得して出力する方法を示しています。

const int defBufferSize = 256;

int size = defBufferSize;
char * buffer = malloc(size);

int result =
    Fg_getParameterPropertyEx(fg, paramId, PROP_ID_IS_ENUM,
                              dma, buffer, &size);
if (result == FG_OK) {
    int newSize = atoi(buffer);
    if (newSize > 0) {
        free(buffer);
        size = newSize;
        buffer = malloc(size);

        result =
            Fg_getParameterPropertyEx(fg, paramId, PROP_ID_ENUM_VALUES,
                                      dma, buffer, &size);
    } else {
        result = FG_INVALID_TYPE;
    }
}
if (result == FG_OK) {
    struct FgPropertyEnumValues * pev;
    for (pev = (struct FgPropertyEnumValues *)buffer;
         pev != NULL;
         pev = FG_PROP_GET_NEXT_ENUM_VALUE(pev)) {
            printf("%s is %d\n", pev->name, pev->value);
    }
}
free(buffer);

Plain Cにおける非同期モード用のコールバック関数の登録#

struct FgApcControl {
    unsigned int version;
    Fg_ApcFunc_t func;
    void *data;
    unsigned int timeout;
    unsigned int flags;
};

int Fg_registerApcHandler(
    Fg_Struct * fg,
    unsigned int dma,
    struct FgApcControl * control,
    enum FgApcControlFlags flags);

関数 Fg_registerApcHandler() を使用して、集録を開始する前に非同期モードを設定できます。

コールバック関数は、セクションで説明されているのと同様に動作します。 非同期モードのコールバック関数の登録 章の 画像取得。関数を呼び出してコールバック関数を登録する場合 Fg_registerCallbackHandler() 取得ループを制御するパラメータは struct FgApcControlのインスタンスで渡されますが、C++ラッパー関数 Fg_registerApcHandlerEx() を呼び出す場合は、これらが関数のパラメータとして渡されます。

コールバック関数を登録する際にフラグが渡される場所は2つあります。関数 flags のパラメータ Fg_registerApcHandler() は取得ループを制御せず、使用されません。アプリケーションはこのパラメータに常に0を渡す必要があります。代わりに、取得ループを制御するフラグはメンバ flags のメンバー struct FgApcControl.

次の例は、画像取り込みの処理に必要な情報を保持する単純な構造体を使用してコールバック関数を登録する方法を示しています。

struct ApcUserCallbackData
{
    Fg_Struct * fg;
    dma_mem * mem;
    unsigned int dma;
    unsigned int timeoutInSeconds;
    int mode;
};

int ApcUserCallback(frameindex_t frame, void * data)
{
    auto context = reinterpret_cast<ApcUserCallbackData *>(data);

    if (frame > 0) {
        // process new image ...
    } else {
        // handle error ...
    }

    return 0;
}

void SetupApcUserCallback(ApcUserCallbackData * context)
{
    // register callback function
    FgApcControl control;
    control.version = 0;
    control.func = &ApcUserCallback;
    control.data = context;
    control.timeout = context->timeoutInSeconds;
    control.flags = FG_APC_DELIVER_ERRORS | FG_APC_IGNORE_TIMEOUTS;

    int result = Fg_registerApcHandler(
        context->fg, context->dma, &control, 0);
    if (result != FG_OK) {
        throw std::runtime_error("Failed to register callback function");
    }
}

コンテキスト構造体の割り当てと管理はこの例には示されていません。ポインタは、コールバック関数が登録されている間、有効である必要があります。解決策の1つは、すべてをC++クラス内にまとめておくことです。C++クラスのコンテキストでコールバック関数を使用するには、静的関数を使用してコールバックハンドラを登録し、 this pointerは、クラスポインタにキャストしてそれに応じて使用できるコンテキストデータポインタとして使用する必要があります。

コールバック関数が不要になった後は、以下を呼び出すことで登録を解除できます。 Fg_registerApcHandler() で渡されます。 NULL を渡したときのデフォルトの動作は、 func:

int result = Fg_registerApcHandler(context->fg, context->dma, NULL, 0);

Plain Cにおける非同期イベント処理用のコールバック関数の登録解除#

int Fg_registerEventCallback(
    Fg_Struct * fg,
    uint64_t mask,
    Fg_EventFunc_t handler,
    void * data,
    unsigned int flags,
    struct fg_event_info * info);

を使用して、 Fg_registerEventCallback()型の関数 Fg_EventFunc_t セクションで説明されているように、1つ以上のイベントソースからのイベントを受信したときにコールバックが呼び出されるように登録できます。 非同期イベント処理のためのコールバック関数の登録 章の 画像取得.

コールバック関数が不要になった後は、以下を呼び出すことで登録を解除できます。 Fg_registerEventCallback()同じイベントグループのマスクを渡します。 FG_EVENT_DEFAULT_FLAGS を渡したときのデフォルトの動作は、 flags および NULL パラメータへ handler, data および info:

// unregister event handler
Fg_registerEventCallback(fg, mask, NULL, NULL, FG_EVENT_DEFAULT_FLAGS, NULL);

  1. グループコードはビットフィールドであり、各ビットはライセンスの単一機能に対応します。このコンテキストにおけるスーパーセットとは、アプレットグループコードのすべてのビットに対して、フレームグラバーグループコードでもそのビットが設定されている必要があることを意味します。このコンテキストにおけるサブセットとは、アプレットグループコードのすべてのビットに対して、フレームグラバーグループコードでもそのビットが設定されている必要があることを意味します。アプレットが、フレームグラバー上のライセンスによってアクティベートされていない機能を使用する場合、アプレットをFramegrabber SDKでロードすることはできません。 ↩↩

  2. パラメータの値は、次の範囲内の任意の値に設定できます: [PROP_ID_MIN; PROP_ID_MAX] 次のステップサイズで: PROP_ID_STEP 線形関係に従って PROP_ID_VALUE = PROP_ID_MIN + n*PROP_ID_STEPここで、nの範囲は [0; (PROP_ID_MAX-PROP_ID_MIN)/PROP_ID_STEP[. ↩↩↩

  3. 旧バージョンのFramegrabber APIでは、使用する取り込みモデルに関係なく、取り込みループ内で Fg_getLastPicNumberBlockingEx() が使用されていました。 ACQ_BLOCK を使用する場合、新しいデフォルトの動作として呼び出されます Fg_getImageEx() を SEL_ACT_IMAGE いつ FG_APC_BATCH_IMAGES が設定され、 SEL_NEXT_IMAGE そうでない場合は設定されます。これは、 ACQ_BLOCKにおいて、デフォルトの動作を使用している場合、コールバックハンドラーが受け取るのはフレーム番号ではなくバッファ番号であることを意味します。 ACQ_BLOCKを使用している場合、特定のフレーム番号に対するバッファ番号を安全に特定する方法がないため、 FG_APC_OLD_ACQ_BLOCK_BEHAVIOR の使用および Fg_getImageEx() コールバックハンドラーからの処理は推奨されず、アプリケーションコードの互換性を維持することが絶対に不可欠である場合にのみ使用してください。 ↩↩