跳转到内容
STAGING SERVER
DEVELOPMENT SERVER

Python 程序员指南#

本主题提供针对 Basler blaze 和 Smart blaze 相机的特定信息,并非旨在全面概述 pypylon。

Basler pylon 的官方 Python 语言绑定是 pypylon 项目。pypylon 是托管在 GitHub 上的开源项目。要使用 Basler 3D 相机,必须使用 4.0 或更高版本。

作为官方 python 包装器的替代方案,可以通过 Python Harvester 库操作相机。Harvesters 是一个专为简化计算机视觉应用中的图像采集过程而设计的 Python 库。它能够通过 GenTL Producer 进行图像采集。

信息

本主题中的所有信息均适用于所有 blaze 和 Smart blaze 相机型号。为简便起见,下文统一使用“blaze”指代所有型号。

pypylon#

安装 pypylon#

Python 编程示例#

pylon Supplementary Package for blaze 包含一些 Python 编程示例,演示了如何使用 Python 和 pypylon 访问 blaze 相机。

To open the folder containing the programming samples for blaze cameras, press the Win key, go to the Basler folder, and choose blaze Samples. A File Explorer window opens. The Python programming samples are located in the Python folder.

The Python samples are located in the /opt/pylon/share/pylon/Samples/blaze/Python/pypylon folder.

信息

在构建示例之前,请将包含示例的文件夹复制到您具有写权限的任意位置。

每个示例都附带一个 README.md 文件,其中提供了有关示例功能以及运行示例所需条件的信息。

使用 pypylon 访问 blaze 相机#

查看 SimpleGrab/simple_grab.py 或使用以下代码片段:

from pypylon import pylon

dc = pylon.DeviceInfo()
dc.SetDeviceClass("BaslerGTC/Basler/GenTL_Producer_for_Basler_blaze_101_cameras")
camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice(dc))
camera.Open()

camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)

while camera.IsGrabbing():
    grabResult = camera.RetrieveResult(1000, pylon.TimeoutHandling_ThrowException)

    if grabResult.GrabSucceeded():
        pylonDataContainer = grabResult.GetDataContainer()

        for componentIndex in range(pylonDataContainer.DataComponentCount):

            pylonDataComponent = pylonDataContainer.GetDataComponent(componentIndex)
            if pylonDataComponent.ComponentType == pylon.ComponentType_Intensity:
                intensity = pylonDataComponent.Array
                _2d_intensity = intensity.reshape(pylonDataComponent.Height, pylonDataComponent.Width)

            pylonDataComponent.Release()

    grabResult.Release()

camera.StopGrabbing()

Harvester#

安装 Harvester#

在命令行中,执行以下命令:

pip3 install harvesters

Python Harvester 编程示例#

pylon Supplementary Package for blaze 包含一些 Python 编程示例,演示了如何使用 Python 和 Harvester 访问 blaze 相机。

To open the folder containing the programming samples for blaze cameras, press the Win key, go to the Basler folder, and choose blaze Samples. A File Explorer window opens. The Python programming samples are located in the Python folder.

The Python Harvester samples are located in the /opt/pylon/share/pylon/Samples/blaze/Python/Harvester folder.

信息

在构建示例之前,请将包含示例的文件夹复制到您具有写权限的任意位置。

每个示例都附带一个 README.md 文件,其中提供了有关示例功能以及运行示例所需条件的信息。

Linux

如果您已将 pylon Software Suite 和 pylon Supplementary Package for blaze 安装到 /opt/pylon 以外的位置,则必须调整 Harvester 加载 blaze 相机 GenTL Producer 的路径。

在示例代码中,搜索以下内容 /opt/pylon/lib/gentlproducer/gtl 并调整路径。

使用 Harvester 访问 blaze 相机#

执行以下步骤,使用 Harvester 查找所有可用的 blaze 相机:

  1. 导入 Harvester 模块。
    from harvesters.core import Harvester
    
  2. 实例化一个 Harvester 对象。
    h = Harvester()
    
  3. 加载适用于 blaze 相机的 GenTL Producer。

    h.add_file(r"C:\Program Files\Basler\pylon\Runtime\x64\ProducerBaslerBlazePylon.cti")
    
    h.add_file("/opt/pylon/lib/gentlproducer/gtl/ProducerBaslerBlazePylon.cti")
    
  4. 更新可用设备列表。

    h.update()
    

  5. 获取有关可用设备的信息。
    h.device_info_list
    

要连接到相机,请使用 h.create() 函数。

以下语句可连接到第一个可用的 blaze 相机:

ia = h.create(0)

如果需要打开特定的相机,可以通过通过以下对象提供的 Property 进行指定: device_info_list Harvester 类对象的 Property。

示例:

ia = h.create(serial_number='9032635')

请注意,指定符必须唯一标识您要打开的设备。如果有多台相机符合条件,则无法打开任何设备。

要断开与相机的连接,请执行以下命令:

ia.destroy()

访问相机参数#

可以通过图像采集器的 remote_device Property 访问相机参数。远程设备的 node_map Property 提供了对所有相机参数的访问权限。

示例:

# Get a parameter.
operatingMode = ia.remote_device.node_map.OperatingMode.value
# Set a parameter.
ia.remote_device.node_map.OperatingMode.value = 'ShortRange'

要获取所有可用相机参数的列表,请使用以下命令:

dir(ia.remote_device.node_map)

有关如何设置和获取 blaze 相机参数的更多示例,请参阅 SimpleGrab 示例。

采集数据#

信息

由于 Harvester 不支持 GenICam GenDC 流式传输格式,因此在采集数据之前,您必须始终禁用 GenDC 流式传输格式。要禁用 GenDC 流式传输格式,请使用以下命令:

ia.remote_device.node_map.GenDCStreamingMode.value = "Off"

从 blaze 相机抓取的 Buffer 可以包含多个组件。其中包括 Range、Intensity 和 Confidence 组件。

以下代码片段启用了所有可用组件,并配置了 Range 组件的 Pixel Format,以便以点云的形式提供深度数据。在点云中,系统会为每个传感器像素分配一个 x、y、z 坐标三元组。

ia.remote_device.node_map.ComponentSelector.value = "Range"
ia.remote_device.node_map.ComponentEnable.value = True
ia.remote_device.node_map.PixelFormat.value = "Coord3D_ABC32f"

ia.remote_device.node_map.ComponentSelector.value = "Intensity"
ia.remote_device.node_map.ComponentEnable.value = True
ia.remote_device.node_map.PixelFormat.value = "Mono16"

ia.remote_device.node_map.ComponentSelector.value = "Confidence"
ia.remote_device.node_map.ComponentEnable.value = True
ia.remote_device.node_map.PixelFormat.value = "Confidence16"

如果您想使用深度图(Depth Map)代替点云,请按下述方式配置 Range 组件:

ia.remote_device.node_map.ComponentSelector.value = "Range"
ia.remote_device.node_map.ComponentEnable.value = True
ia.remote_device.node_map.PixelFormat.value = "Coord3D_C16"

要开始采集,请调用图像采集器的 start() 函数:

ia.start()

典型的抓取循环如下所示:

ia.start()
while True:
    with ia.fetch() as buffer:
        # Do something with the buffer.
ia.stop()

信息

缓冲区仅在 with 语句内部有效,并且在您离开作用域时会被销毁。如果您想在 with 作用域之外使用缓冲区,则必须使用 np.copy() 来进行深拷贝。

以下代码片段演示了如何访问缓冲区的组件:

with ia.fetch() as buffer:
      depth = buffer.payload.components[0]
      intensity = buffer.payload.components[1]
      confidence = buffer.payload.components[2]

Harvester 将组件作为一维 NumPy 数组返回。

为了便于后续处理,将 1D 数组重塑为 2D 或 3D 数组可能会很有用:

depth_arr = depth.data.reshape(pointcloud.height, pointcloud.width,
                              int(pointcloud.num_components_per_pixel))

intenstiy_arr = intensity.data.reshape(intensity.height, intensity.width)

confidence_arr = confidence.data.reshape(confidence.height, confidence.width)

num_components_per_pixel 取决于 Range 组件的 Pixel Format。如果 Pixel Format 等于 Coord3D_ABC32f,则 Range 组件表示为点云,即每个像素有 3 个浮点值。结果是一个存储每个像素的 x、y 和 z 坐标的三维数组。

如果 Pixel Format 等于 Coord3D_C16,则 Range 组件表示为 16 位灰度图像,即每个像素有一个 16 位整数值。

有关如何将深度图的灰度值转换为毫米的更多详细信息,请参阅 Processing Measurement Results 主题。

完成数据采集后,调用 stop() 函数:

ia.stop()

作为实现如上所示采集循环的替代方案,Harvester 可以提供一个后台线程来执行采集循环,并通过发出回调通知应用程序。此方法在 SimpleGrab_Callback sample 中进行了说明。

调试应用程序并控制 GigE Vision Heartbeat#

像 blaze 相机这样的 GigE Vision 相机要求应用程序通过定期向相机发送特殊的网络数据包来定期访问相机。如果相机未收到这些心跳信号,它会认为连接已断开,并不再接受来自应用程序的任何命令。

当您运行应用程序时,用于 blaze 相机的 GenTL Producer 通常会生成这些心跳。如果您在应用程序中设置断点并触发了断点,调试器将暂停所有线程,包括发送心跳的线程。因此,在调试应用程序并单步执行代码时,不会向相机发送心跳。结果是,相机检测到心跳超时并关闭了连接。心跳超时的默认值为 3000 ms。

为了解决此问题,您必须在开发期间增加心跳超时时间。您可以通过设置名为 GEV_HEARTBEAT_TIMEOUT 的环境变量并指定所需的超时时间(以毫秒为单位)来完成此操作。

或者,您可以在应用程序中设置心跳超时时间,如下所示:

ia.device.node_map.HeartbeatTimeout.value=600000

信息

如果您将心跳超时时间增加到一个较大的值,并且在未正确关闭设备的情况下停止应用程序,您将无法再次打开相机,并将收到一条错误消息,指出设备当前正在使用中。如果您使用调试器停止应用程序或应用程序意外终止,则可能会发生这种情况。要再次打开相机,您必须等待超时时间过去或断开相机的网线。