メインコンテンツまでスキップ
バージョン: v24.05

画像の表示

このチュートリアルでは、ion-kitを使用してデバイスから画像データを取得し、OpenCVを使って表示する方法を学びます。

必要なもの

  • ionpy
  • numpy
  • OpenCV
pip3 install -U pip
pip3 install opencv-python
pip3 install numpy
pip3 install ion-python==1.8.10

チュートリアル

デバイス情報の取得

ionpyを使用して画像を表示するには、デバイスの以下の情報を取得する必要があります。

  • 高さ
  • PixelFormat

前回のチュートリアルまたはarv-tool-0.8がこれらの値を取得するのに役立ちます。

パイプラインの構築

最初に、ion-kitのpythonバインディングであるionpyのモジュールをロードします。

from ionpy import Node, Builder, Buffer, PortMap, Port, Param, Type, TypeCode
なぜ動作しないのか

Pythonユーザーの場合、C/C++ランタイムライブラリがない可能性があります。ionpyのモジュールをロードするのに問題がある場合は、Microsoft公式ウェブページの記事からライブラリをインストールできます。

イントロで学んだように、画像のI/Oと処理のためにパイプラインを構築して実行します。

このチュートリアルでは、U3Vカメラから画像を取得する唯一のビルディングブロックを持つ非常に単純なパイプラインを構築します。

次のionpy APIでパイプラインを設定します。

# パイプラインのセットアップ
builder = Builder()
builder.set_target('host')
builder.with_bb_module('ion-bb')

set_targetは、ビルダーによって構築されたパイプラインが実行されるハードウェアを指定します。

ion-bb.dllで定義されたBBを使用するためには、with_bb_module関数でモジュールをロードする必要があります。

使用するBBはimage_io_u3v_cameraN_u8x2で、これは各ピクセルデータの深度が8ビットで、2次元のU3Vカメラ向けに設計されています。例えば、Mono8です。

ピクセルフォーマットがMono10またはMono12の場合、各ピクセルデータの深度が16ビットであるため、image_io_u3v_cameraN_u16x2が必要です。

ピクセルフォーマットがRGB8の場合、深度が8で次元が3(幅と高さに加えてカラーチャネルがある)であるため、image_io_u3v_cameraN_u8x3を使用します。

BBの名前ビット深度次元PixelFormatの例
image_io_u3v_cameraN_u8x282Mono8
image_io_u3v_cameraN_u8x383RGB8, BGR8
image_io_u3v_cameraN_u16x2162Mono10, Mono12

BBに設定するために静的な入力値を設定するには、次のようにParamを定義する必要があります。

# パラメータの設定
num_devices = Param('num_devices', str(num_device))
frame_sync = Param('frame_sync', 'true')
realtime_display_mode = Param('realtime_display_mode', 'true')
Paramのキー値のタイプ説明
num_devicesIntegerプログラムで使用するデバイスの数
frame_syncBooleanデバイスの数が1より多い場合、デバイス間のフレームカウントを同期します
realtime_display_modeBooleanフレームドロップを許可しますが、遅延はありません

これで、ノードにポートとパラメータを持つBBをパイプラインに追加できます。

# パイプラインにノードを追加
node = builder.add(bb_name)\
.set_param([num_devices, frame_sync, realtime_display_mode, ])
output_p = node.get_port('output')

これが私たちのパイプラインの唯一のBBであるため、ノードの出力ポートはパイプラインの出力ポートになります。そして、それをoutput_pと名前を付けます。

私たちのBBとポートを持つパイプラインは次のようになります:

tutorial1-pipeline

ポートから出力データを取得するために、出力のためのバッファを準備し、ポートを出力用のバッファにバインドします。

# 出力ポート用のHalideバッファを作成
output_size = (height, width, )
if pixelformat == "RGB8":
output_size += (3,)
output_data = np.full(output_size, fill_value=0, dtype=data_type)
output = []
output.append(Buffer(array= output_data))

# I/Oポートの設定
output_p.bind(output)

ここでのoutput_sizeは2D画像用に設計されています。ピクセルフォーマットがRGB8の場合、色チャネルを追加するために(width, height, 3)を設定する必要があります。

パイプラインの実行

パイプラインは実行の準備ができています。run()を呼び出すたびに、バッファoutputは出力画像を受け取ります。

builder.run()

OpenCVで表示

出力ポートがバッファoutputにバインドされている間、出力データ(つまり画像データ)はnumpy配列(output_data)に格納されます。

OpenCVはnumpy配列を扱うことができるため、cv2.imshow("img", output_data)を使用して出力画像を表示できます。

ただし、ピクセルフォーマットの深度がnumpy配列の深度(例:Mono10またはMono12)と一致しない場合は、データをいくつかのビットシフトで調整する必要があります。そうしないと、取得した画像がはるかに暗く見える可能性があります。

coef = pow(2, num_bit_shift)
output_data *= coef
cv2.imshow("img", output_data)

連続した画像を取得するには、cv2.waitKeyEx(1)を使用してwhileループを設定できます。これにより、プログラムが1ミリ秒間保持され、ユーザー入力があると-1以外の値が返されます。以下のコードは、ユーザーが任意のキーを入力するまで無限にループします。

coef = pow(2, num_bit_shift)
user_input = -1

while(user_input == -1):
# ビルダーの実行
builder.run()
output_data *= coef

cv2.imshow("img", output_data)
user_input = cv2.waitKeyEx(1)

whileループの後に画像を表示したウィンドウを破棄することを忘れないでください。

cv2.destroyAllWindows()

スクリプトを実行するとデバイスが取得した画像がウィンドウに表示されます。

ヒント

もしお使いのLinux デスクトップがGNOMEである場合、以下の警告が表示されることがありますが、プログラムのパフォーマンスや機能に影響を及ぼすものではありません。

Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.

or

qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "/home/<username>/.local/lib/python3.10/site-packages/cv2/qt/plugins"
カメラインスタンスが正確に解放されるのは

カメラインスタンスの寿命はビルディングブロックインスタンスによって制限されています。つまり、プログラムが終了するとともに自動的に破棄されます。正確なタイミングを観察するには、ユーザーはWindowsコマンドラインでset ION_LOG_LEVEL=debug、またはUnixターミナルでexport ION_LOG_LEVEL=debugを設定します。ユーザーは、ターミナルで以下の行が表示された場合、aravis経由でカメラにアクセスできます:

[2024-02-14 08:17:19.560] [ion] [info]  Device/USB 0::Command : AcquisitionStart
[2024-02-14 08:17:27.789] [ion] [debug] U3V::release_instance() :: is called
[2024-02-14 08:17:27.790] [ion] [debug] U3V::dispose() :: is called
[2024-02-14 08:17:27.791] [ion] [debug] U3V::dispose() :: AcquisitionStop
[2024-02-14 08:17:28.035] [ion] [debug] U3V::dispose() :: g_object_unref took 244 ms
[2024-02-14 08:17:28.109] [ion] [debug] U3V::dispose() :: g_object_unref took 72 ms
[2024-02-14 08:17:28.110] [ion] [debug] U3V::dispose() :: Instance is deleted
[2024-02-14 08:17:28.111] [ion] [debug] U3V::release_instance() :: is finished

上記のデバッグ情報から、ユーザーはカメラインスタンスの解放にかかる時間を知ることができます。 詳細ははデバッグのヒントを参照してください。

完全なコード

このチュートリアルで使用される完全なコードはこちらです。