Pythonを使用して結果を計算
機能
Pythonを介してカスタマイズのスクリプトを実行し、計算結果をMech-Visionに出力します。
このステップの特徴は以下の通りです。
-
マルチスレッドでの使用をサポートします。
-
Pythonスクリプトをリアルタイムに読み込むことができます。
-
C++側とPython側でデータを転送する際に、複数のデータ型変換をサポートします。
-
Python側からのログをMech-Visionにリダイレクトすることに対応します。
入力と出力
-
入力: 入力ポート パラメータに入力されるデータ型によって決定されます。ポートの名前変更はサポートされていません。
-
出力: 出力ポート パラメータに入力されるデータ型によって決定されます。ポートの名前変更はサポートされていません。
このステップの入出力ポートのデータ型は、前後のステップの入出力ポートのデータ型に基づいて決定することができます。 |
インストールと使用
インストール方法
Mech-VisionにはPython 3.9.13、およびNumPyとOpenCVという2つのよく使用されるPythonライブラリが内蔵されています。「Pythonを使用して結果を計算」ステップを実行する際は、ソフトウェア内蔵のPython環境が使用されます。使用中に Python ライブラリが不足している場合は、欠落しているライブラリをMech-Visionに内蔵された Python 環境にインストールする必要があります。インストール方法は以下の通りです。
-
Mech-VisionのPythonインストールディレクトリに移動します。
-
Pythonインストールディレクトリ内の空白部分でShiftキーを押しながら右クリックし、PowerShellウィンドウをここで開く を選択して、Powershellコマンドラインツールを開きます。
-
Powershellコマンドラインツールで「python -m pip install xxx」と入力してコマンドを実行します("xxx"はインストールしたいPythonライブラリの名前です)。これで、対応するPythonライブラリがダウンロードされ、インストールされます。
使用方法
Pythonスクリプトを準備したら、このステップを以下のように使用します(各パラメータの説明は、 パラメータ説明 をご参照ください)。
-
入出力ポートのデータ型を設定します。入力ポート と 出力ポート のデータ型は、前後のステップの入出力ポートのデータ型に従って、または必要に応じて入力してください。
-
Pythonスクリプトのパスを設定します。読み込むスクリプトのパスを スクリプトファイルのパス で選択します。
-
呼び出される関数の名前を設定します。スクリプトパスを選択すると、このステップではスクリプト内の関数名が自動的に取得されます。次に、呼び出される関数名 のドロップダウンリストで必要なスクリプト関数名を選択する必要があります。
-
ステップを実行します。
|
Mech-Vision 1.8.0バージョンから、「Pythonを使用して結果を計算」ステップのプログラム実行方式が直列から並列に変更されました(Pythonのthreadingモジュールと同様の効果があります)。スクリプト内で並列実行をサポートしていない特定のカメラAPI(例:カメラの列挙)を呼び出す場合は、そのAPIの呼び出し箇所にロックを追加する必要があります。 |
使用上の注意事項
このステップでPythonスクリプトを作成し、実行する場合、以下の点に注意する必要があります。
サードパーティライブラリの使用を推奨
Mech-VisionでPythonスクリプトを実行することと、Python環境でPythonスクリプトを実行することは異なるため、一部のPythonライブラリがインストールされていない、またはインストールしても動作しない場合がありますので、サードパーティ製ライブラリの使用を推奨します。
NumPyライブラリの使用に注意
Pythonがサポートするデータ型のうち、より複雑な型はNumPyライブラリを介して中間フォーマットとして使用されるデータ型です。NumPyの配列型であるパラメータ型があるにもかかわらず、NumPyにインポートされていない場合、エラーが発生します。したがって、スクリプトの先頭に import numpy を追加する必要があります。
スクリプト作成際にデータ型の次元に注意
Pythonスクリプトを作成には、ステップポートの基本データ型のデータ次元に注意を払う必要があります。
-
デフォルトのデータ次元は0: Image; Cloud(XYZ); Cloud(XYZ-Normal)。
-
デフォルトのデータ次元は1: NumberList; BoolList; IndexList; StringList。
-
デフォルトのデータ次元は2: PoseList; Pose2DList; Size3DList。
データ型の後に[]記号を追加して、データ次元の追加を示します。 例えば、NumberListは1次元の値のリスト、NumberList[]は2次元の値のリストを表します。 |
パラメータ説明
- 入力ポート
-
パラメータ説明:このパラメータは、ステップの入力ポートのデータ型を設定するために使用されます。入力データ型は、対応する順序で呼び出された関数にパラメータとして渡されます。
初期値:なし。
- 出力ポート
-
パラメータ説明:このパラメータは、ステップの出力ポートのデータ型を設定するために使用されます。関数が返すデータは、対応する順序でステップに返され、対応するデータ型に従って解析されることになります。
初期値:なし。
現在対応しているデータ型は以下の通りです。
ステップのポートタイプ | Pythonで使用されるデータ型 | 入力データの例 |
---|---|---|
PoseList |
リスト |
[[10, 20, 30, 0.951, 0.255, 0.168, 0.045]], [10, 20, 30, 0.951, 0.255, 0.168, 0.045]]
|
Pose2DList |
リスト |
[[0, 0, 0]], [2, 0, 120]]
|
NumberList |
リスト |
[1.1, 2, 999.9, -22] |
StringList |
文字列 |
['string_1', 'string_2', 'string_3'] |
Image |
8ビット符号なし整数/64ビット浮動小数点数 |
画像 |
Cloud(XYZ) |
配列 |
点群 |
Cloud(XYZ-Normal) |
配列 |
法線ベクトル付きの点群 |
Cloud(XYZ-RGB) |
配列 |
カラー点群 |
Size3DList |
64ビット浮動小数点数 |
[[2.5, 5, 0.001]], [6, 5, 0.02]]
|
IndexList |
整数 |
[45, 10, 90] |
BoolList |
ブール型 |
[True, False, True] |
- スクリプトファイルのパス
-
パラメータ説明:このパラメータは、読み込むスクリプトのファイルパスを選択するために使用されます。
初期値:なし。
- 呼び出される関数名
-
パラメータ説明:このパラメータは、呼び出されるスクリプト関数の名前を設定するために使用されます。
初期値:なし。
Pythonのサンプルコード
このステップのポートタイプを理解しやすく、Pythonスクリプトを使用してこのステップを実行するために、以下ではPythonのサンプルコードを紹介します。
クイックスタート
Pythonスクリプトによる同じ型データを出力
以下のサンプルでは、 同じ型データを出力 する関数を定義しています。 Pythonを使用して結果を計算 ステップの使用方法を参照して、この関数を呼び出すことができます。
def get_doublelist():
return [1.1,22,3.3]
このサンプルに対応するMech-Visionプロジェクトを下図に示します。出力ポートのデータフローをダブルクリックして、出力結果を確認できます。
Pythonスクリプトによる複数型のデータを出力
以下のサンプルでは、 複数型のデータを出力 する関数を定義しています。 Pythonを使用して結果を計算 ステップの使用方法を参照して、この関数を呼び出すことができます。
def example_of_basic_portTypes():
numList = [1.1, 2, 999.9, -22]
indexList = [45, 10, 90]
boolList = [True, False, True]
strList = ['string_1', 'string_2', 'string_3']
poseList = [[10, 20, 30, 0.951, 0.255, 0.168, 0.045], [10, 20, 30, 0.951, 0.255, 0.168, 0.045]]
pose2dList = [[0, 0, 0], [2, 0, 0.785]]
size3dList = [[2.5, 5, 0.001], [6, 5, 0.02]]
return numList, indexList, boolList, strList, poseList, pose2dList, size3dList
このサンプルに対応するMech-Visionプロジェクトを下図に示します。各出力ポートのデータフローをダブルクリックして、出力結果を確認できます。
2つの「Pythonを使用して結果を計算」ステップによるデータ処理
サンプル1は数値リストを出力する関数を定義し、サンプル2は各数値リスト内の値に対して合計演算を実行する関数を定義します。
Pythonを使用して結果を計算 ステップの使用方法を参照して、このステップで以下のサンプルコードを呼び出し、ステップをつないで入力の数値リストに対して合計演算を実行することができます。
サンプルコード1:
def get_numberlist_1():
return [[1, 2, 3],[4,5,6]]
サンプルコード2:
def cal_number_list(nums_list):
sums = [align="center"]
for nums in nums_list:
sum = 0
for num in nums:
sum += num
sums.append(sum)
return [sums]
このサンプルに対応するMech-Visionプロジェクトを下図に示します。各出力ポートのデータフローをダブルクリックして、出力結果を確認できます。
複数の「Pythonを使用して結果を計算」ステップによるデータ処理
サンプル1は数値リストを出力する関数を定義し、サンプル2はブール値リストを出力する関数を定義します。サンプル3は数値リストに「9999」を追加し、ブール値リストに「False」を追加し、新しい数値リストおよびブール値リストを出力するために使用されます。
Pythonを使用して結果を計算 ステップの使用方法を参照して、このステップで以下のサンプルを呼び出して、複数の入力データに対して処理を行うことができます。
サンプルコード1:
def get_doublelist():
return [1.1,22,3.3]
サンプルコード2:
def get_bool_list():
return [[True,False],[True,True],[False,False]]
サンプルコード3:
def print_multi_values(numberList, boolList):
numberList.append(9999)
boolList.append(False)
return numberList, boolList
このサンプルに対応するMech-Visionプロジェクトを下図に示します。各出力ポートのデータフローをダブルクリックして、出力結果を確認できます。
実際応用に適応可能なサンプルコード
プロジェクト実行中の異常データを保存
実際の応用シーンでは、プロジェクト実行中に様々な問題が発生することがあります。Mech-Visionプロジェクト内のデータ保存機能とカスタマイズされたPythonスクリプトにより、異常データを保存し、問題のトラブルシューティングやビジョンシステムの安定性向上を実現しています。
詳細は以下の通りです。
-
データ保存 機能を有効にします。
Mech-Visionのプロジェクトアシスタントで データとパラメータを保存 を有効にすると、プロジェクトでエラーポップアップが発生した場合、生データが プロジェクトフォルダ/data/error_data パスに保存されます。
-
Pythonスクリプトを作成します。
「3D位置姿勢推定」の出力位置姿勢が空かどうかを判定するPythonサンプルコードを例に説明します。詳細は以下の通りです。
def abnormal_output_detection(outputs): if len(outputs) == 0: raise Exception("NO RESULT!!!") else: pass
-
Pythonを使用して結果を計算 ステップの使用方法を参照して、「Pythonを使用して結果を計算」ステップで上記のサンプルを呼び出して、このステップを「3D位置姿勢推定」の後につなぎます。
プロジェクト実行後、「3D位置姿勢推定」の出力位置姿勢が空の場合、ポップアップウィンドウが表示され、異常データが プロジェクトフォルダ/data/error_data パスに保存されます。
入力点群のZ値に基づいて疑似カラー点群を生成
プロジェクトの出力点群にテクスチャ情報がない場合、出力点群をより可視化表示するために、カスタマイズされたPythonスクリプトを使って、入力点群のZ値に基づいて擬似カラー点群を生成することができます。
主な処理流れは次の通りです。Z値を0~255の範囲にマッピングしてグレースケール値を取得します。その後、OpenCVを使用してグレースケール値をカラー値にマッピングして、擬似カラー点群を取得します。
Pythonのサンプルコードは以下の通りです。
import math
import cv2
import numpy as np
def generate_color_point_could_by_depth(point_cloud):
x = point_cloud[:, 0]
y = point_cloud[:, 1]
z = point_cloud[:, 2]
z_min = np.min(z)
z_max = np.max(z)
if math.isclose(z_max - z_min, 0):
return np.column_stack((x, y, z, np.full(z.shape, 0xFFFFFFFF, np.uint32).view(np.float32)))
color = 255 * (z - z_min) / (z_max - z_min)
color = cv2.applyColorMap(color.astype(np.uint8), cv2.COLORMAP_JET)
color = np.squeeze(color).astype(np.uint32)
color = (0xFF000000 | (color[:, 0] << 16) | (color[:, 1] << 8) | color[:, 2]).view(np.float32)
return np.column_stack((x, y, z, color))