プログラマーズガイド

StApi Python (stapipy)の構造

StApiは3つの主な機能(カメラ制御のためのトランスポート層)で構成されていますが、 このstapipyパッケージはトランスポート層(StApi TL)と画像処理(StApi IP)に対してのみPythonバインディングを提供します。

カメラの設定変更や画像データ、イベントデータ等を取得する機能が提供されます。カメラとの通信にはGenTLモジュールが使用されます。 SDK付属のGenTLモジュールはUSB3VisionおよびGigEVisionに対応しています。CoaXPress用取り込みボードメーカー製のGenTLモジュールを使用することで CoaXPressカメラも利用できます。カメラの設定変更にはGenApiが使用されます。画像処理機能やGUI機能が不要であれば、 この機能(下図の水色線枠内)だけを使用してアプリケーションを開発できます。

モジュール

主な用途

System

ctiファイル(GenTL用ライブラリファイル)の情報取得に使用されます。

Interface

インターフェースに関する設定や接続されているカメラの情報取得などに使用されます。

Device

カメラの設定に使用されます。

Data Stream

画像データ等のストリーミングの設定に使用されます。

Stream Buffer

ストリーミングに使用されているバッファの情報取得に使用されます。

対応環境

StApi Python(stapipy)はPython wheel(.whl)の形で配布します。 このモジュールはStApi(Sentech SDK)のインストールを必要とし、以下のPythonをサポートします。

  • Python 3.8.x, 3.9.x, 3.10.x 64bit/32bit (Windows OS)

  • Python 3.8.x, 3.9.x, 3.10.x 64bit (Linux OS)

  • Python 3.8.x, 3.9.x, 3.10.x ARM64 (Linux OS)

警告

  • StApi Pythonを使用するためにSentech SDKのインストールが必要になります。Sentech SDKがインストールされていることを確認してください。

  • stapipyを使用するアプリケーションを実行するには、Sentech SDKが提供する環境変数を設定する必要があります。

StApi (Sentech SDK)のインストール

Sentech SDKのドキュメントに参照ください。

stapipyのインストール

stapipyをインストールする際、pip コマンドを実行ください。例:

pip install stapipy-1.2.2-xxx-yyy-zzz.whl

xxx-yyyは下記のようなPythonのバージョンとABIです。

  • cp38-cp38 : Python 3.8.x

  • cp39-cp39 : Python 3.9.x

  • cp310-cp310 : Python 3.10.x

zzzは下記のようなPythonのプラットフォームです。

  • linux_aarch64 : Linux ARM64

  • linux_x86_64 : Linux 64 bit

  • win32 : Windows 32 bit

  • win_amd64 : Windows 64 bit

エラー処理

StApiで例外が発生する際、stapipyはその例外を伝播して stapipy.PyStError を出送します。

画像データの取得までの流れ

  1. stapipyをインポート。

    import stapipy as st
    
  2. StApiライブラリの初期化します。stapipy.initialize() を呼び出します。

    StApiライブラリを使い終わった後は stapipy.terminate() を呼び出して終了処理を行います。 stapipy.terminate() を呼び出した後ではstapipy関連の関数やインスタンスなどをアクセスしないようにご注意ください。

    st.initialize()
    
  3. システム(GenTLモジュール)をオープンし、 stapipy.PyStSystem を取得します。 stapipy.create_system() を呼び出します。

    st_system = st.create_system()
    
  4. デバイス(カメラ)をオープンし、PyStDevice のインスタンスを取得します。stapipy.PyStSystem.create_first_device() を呼び出します。

    下記のコードは最初見つけたカメラをオープンします。

    st_device = st_system.create_first_device()
    
  5. データストリームをオープンし、PyStDataStream のインスタンスを取得します。stapipy.PyStDevice.create_datastream() を呼び出します。

    st_datastream = st_device.create_datastream()
    
  6. ホスト側画像データの取得を開始します。stapipy.PyStDataStream.start_acquisition() を呼び出します。

    下記のコードは100枚画像を取得します。

st_datastream.start_acquisition(100)
  1. カメラ側画像データの出力を開始します。stapipy.PyStDevice.acquisition_start() を呼び出します。

    st_device.acquisition_start()
    
  2. 画像データが入ったバッファ:py:class:stapipy.PyStStreamBuffer の取得と、使用済バッファのキューへの挿入を繰り返し行います。

    バッファをキューに戻すには、stapipy.PyStStreamBuffer のインスタンスを解放する必要があります。 インスタンスを None にするか、stapipy.PyStStreamBuffer.release() を呼び出すか、 コンテキストマネージャ(with)を使うことです。

    下記のコードはコンテキストマネージャを使用したバッファの取得と再キューイングの例を示します。

    while st_datastream.is_grabbing:
        with st_datastream.retrieve_buffer() as st_buffer:
            if st_buffer.info.is_image_present:
                st_image = st_buffer.get_image()
                print("BlockID={0} Size={1} x {2} First Byte={3}".format(
                      st_buffer.info.frame_id,
                      st_image.width,
                      st_image.height,
                      st_image.get_image_data()[0]))
            else:
                print("Image data does not exist.")
    
  3. カメラ側画像データの出力を停止します。stapipy.PyStDevice.acquisition_stop() を呼び出します。

    st_device.acquisition_stop()
    
  4. ホスト側画像データの取得を停止します。stapipy.PyStDataStream.stop_acquisition() を呼び出します。

    st_datastream.stop_acquisition()
    

完全なコードは以下の通りです。

 1import stapipy as st
 2
 3st.initialize()
 4st_system = st.create_system()
 5st_device = st_system.create_first_device()
 6st_datastream = st_device.create_datastream()
 7st_datastream.start_acquisition(100)
 8st_device.acquisition_start()
 9while st_datastream.is_grabbing:
10   with st_datastream.retrieve_buffer() as st_buffer:
11       if st_buffer.info.is_image_present:
12           st_image = st_buffer.get_image()
13           print("BlockID={0} Size={1} x {2} First Byte={3}".format(
14                 st_buffer.info.frame_id,
15                 st_image.width,
16                 st_image.height,
17                 st_image.get_image_data()[0]))
18       else:
19           print("Image data does not exist.")
20st_device.acquisition_stop()
21st_datastream.stop_acquisition()

GenApiノードのアクセス

stapipyには各GenTLモジュールインスタンス(stapipy.PyStSystem, stapipy.PyStInterface, stapipy.PyStDataStream, stapipy.PyStStreamBuffer)に port プロパティーがあります。 stapipy.PyStDevice の場合は、ローカルとリモートポートアクセスがあり、 stapipy.PyStDevice.local_portstapipy.PyStDevice.remote_port になります。 ポートクラスの stapipy.PyStPort.nodemap プロパティーで stapipy.PyNodeMap のインスタンスを取得し、GenApiのノードマップのアクセスができます。

GenApiのノードマップからGenApiのノードを取得する場合は stapipy.PyNodeMap.get_node() を呼び出して、stapipy.PyNode を取得し、GenApiのノードをアクセスできます。

次のコードの6行目と7行目は、リモートデバイスのGenApiノードマップを取得し、「Width」という名前のノードを取得する方法を示します。

1import stapipy as st
2
3st.initialize()
4st_system = st.create_system()
5st_device = st_system.create_first_device()
6st_nodemap_remote = st_device.remote_port.nodemap
7width_node = st_nodemap_remote.get_node("Width")
8print("Width:", width_node.value)
9print("Interface type:", width_node.principal_interface_type)

単純な使い方では、 stapipy.PyNode.value を使うことで、ノードの特定のインターフェースにアクセスすることなくノード値を直接読み書きすることが可能です。 包括的な使用法のために、ノードの特定のインターフェースにアクセスすることが必要かもしれません。

プロパティー stapipy.PyNode.principal_interface_type でノードのインタフェースタイプ(stapipy.EGCInterfaceType)を取得できます。

次の表は、インターフェイスの種類に対応するクラスの一覧を示します。

インタフェースタイプ

クラス

IInteger

stapipy.PyIInteger

IBoolean

stapipy.PyIBoolean

ICommand

stapipy.PyICommand

IFloat

stapipy.PyIFloat

IString

stapipy.PyIString

IRegister

stapipy.PyIRegister

ICategory

stapipy.PyICategory

IEnumeration

stapipy.PyIEnumeration

IEnumEntry

stapipy.PyIEnumEntry

IPort

stapipy.PyIPort

さまざまなユースケースに対応するために、ノードの指定されたインタフェースにアクセスする方法は2つあります。

  • stapipy.PyNode からインターフェース型のクラスインスタンスを作成すること。

    クラスが正しくなければ、例外 ValueError が発生します。

    この方法はコードの可読性を向上させるために推奨されます。

    width = st.PyIInteger(width_node)
    print("Width min:{0}, max:{1}".format(width.min, width.max))
    
  • stapipy.PyNode.get() を呼び出すこと。

    ノードのインターフェースタイプに応じて、クラスインスタンスの1つが返されます。

    この方法を使用すれば、コードを短くできます。

    width = width_node.get()
    print("Width min:{0}, max:{1}".format(width.min, width.max))
    

取得画像データからNumPy配列を取得する方法

Pythonの科学計算および画像処理パッケージには、ほとんどNumPy配列を使用しています。 PyStImageからNumPy配列を取得する簡単な例については、サンプルプログラム grab_opencv.py (画像変換にはOpenCVを利用されます) と grab_ip_opencv.py (画像変換にはStApi IPを利用されます) を参照してください。