使用Python计算结果
功能描述
该步骤可通过 Python 运行用户自定义的脚本,并将计算结果输出到 Mech-Vision。
该步骤特点如下:
-
支持多线程使用;
-
可实时加载 Python 脚本;
-
在 C++ 和 Python 端互相传输数据时,支持多种数据类型的转化;
-
支持将 Python 端的日志重定向到 Mech-Vision 中。
安装和使用
安装方法
Mech-Vision 中内置了 Python 3.6.8,该步骤将使用软件内置的环境。若在使用过程中出现缺少 Python 库的情况,需要将所缺少的 Python 库安装在 Mech-Vision 内置的 Python 环境中。安装方法如下:
-
打开命令提示符。
-
在命令行中使用“cd”命令,将路径切换至 Mech-Vision 的 Python 目录下。
-
执行“python -m pip install Python 库的名称”命令,下载安装对应的 Python 库。
Mech-Vision 中已内置了 NumPy 和 OpenCV 两个常用的 Python 库。 |
使用方法
准备好 Python 脚本后,该步骤的使用方法如下(关于各参数的解释可参考 参数说明 ):
-
设置输入/输出端口数据类型。根据前后步骤的输入/输出端口数据类型,或根据实际需求,填写输入端口和输出端口的数据类型。
-
设置 Python 脚本路径。在脚本路径处选择需要加载的脚本的路径。
-
设置调用函数的名称。当选择脚本路径后,该步骤将自动获取该脚本内的函数名称,然后需在调用函数名称处的下拉栏中选择需要调用的脚本函数名称。
-
运行步骤。
|
从Mech-Vision 1.8.0起,“使用Python计算结果”步骤程序运行方式由串行改为并行(与 Python 中的 threading 模块效果一致)。在脚本内调用个别不支持并行运行的相机 API(例如枚举相机)时,需在该 API 调用处加锁。 |
参数说明
- 输入端口
-
参数解释:该参数用于设置该步骤输入端口的数据类型,输入的数据类型将会变为对应顺序的参数传入所调用的函数。
默认值:空。
- 输出端口
-
参数解释:该参数用于设置该步骤输出端口的数据类型,函数返回的各数据会按照对应顺序返回给该步骤,并且会按照对应数据类型进行解析。
默认值:空。
目前支持的数据类型如下表所示:
端口类型 |
示例 |
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]] (每组数据中,前两个数值分别表示坐标的 X、Y 值,第三个数值表示角度。) |
NumberList |
[1.1, 2, 999.9, -22] |
StringList |
['string_1', 'string_2', 'string_3'] |
Image |
图像数据 |
Cloud(XYZ) |
点云数据 |
Cloud(XYZ-Normal) |
带法向的点云数据 |
Cloud(XYZ-RGB) |
彩色点云数据 |
Size3DList |
[[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工程如下图所示,可通过双击各输出端口对应的数据流来查看输出结果。
通过两个“使用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))