跳至內容
測試伺服器
開發伺服器

第三方驅動程式、程式庫與範例#

本頁面提供有關第三方函式庫的資訊,以及用於操作 BaslerStereo mini 攝影機的範例程式碼。

NumPy#

Python 範例中使用 NumPy 來處理 pypylon 所回傳的原始元件資料。

pip install numpy

OpenCV#

OpenCV 可用於處理從Stereo mini 相機擷取的強度影像。強度元件會提供一張 RGBA8 影像,該影像可轉換為適合 OpenCV 處理的格式。

pip install opencv-python

範例:將亮度分量轉換為 OpenCV 影像

import cv2
import numpy as np
from pypylon import pylon

# ... camera setup (see Python Programmer's Guide) ...

data_container = grab_result.GetDataContainer()
for i in range(data_container.DataComponentCount):
    component = data_container.GetDataComponentByIndex(i)
    try:
        if component.ComponentType == pylon.ComponentType_Intensity:
            raw = component.GetData()
            h, w = component.Height, component.Width
            # Stereo mini intensity is RGBA8
            rgba = np.frombuffer(raw, dtype=np.uint8).reshape(h, w, 4)
            bgr = cv2.cvtColor(rgba, cv2.COLOR_RGBA2BGR)
            cv2.imshow("Intensity", bgr)
            cv2.waitKey(1)
    finally:
        component.Release()

如需詳細資訊,請參閱OpenCV。

Open3D#

Open3D 應用於 顯示點雲圖 範例,用於視覺化來自Stereo mini 相機的 3D 點雲。其中的距離分量在 Coord3D_ABC32f 此格式提供直接的 XYZ 座標。

pip install open3d

範例:根據距離與強度資料建立 Open3D 點雲

import numpy as np
import open3d as o3d
from pypylon import pylon

# ... camera setup with ComponentSelector Range, PixelFormat Coord3D_ABC32f ...

data_container = grab_result.GetDataContainer()
xyz = None
colors = None

for i in range(data_container.DataComponentCount):
    component = data_container.GetDataComponentByIndex(i)
    try:
        if component.ComponentType == pylon.ComponentType_Range:
            h, w = component.Height, component.Width
            raw = component.GetData()
            pts = np.frombuffer(raw, dtype=np.float32).reshape(h * w, 3)
            valid = np.isfinite(pts).all(axis=1)
            xyz = pts[valid]
        elif component.ComponentType == pylon.ComponentType_Intensity:
            h, w = component.Height, component.Width
            raw = component.GetData()
            rgba = np.frombuffer(raw, dtype=np.uint8).reshape(h * w, 4)
            colors = rgba[..., :3].astype(np.float64) / 255.0
    finally:
        component.Release()

if xyz is not None and colors is not None:
    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(xyz)
    pcd.colors = o3d.utility.Vector3dVector(colors[:len(xyz)])
    o3d.visualization.draw_geometries([pcd])

如需詳細資訊,請參閱Open3D。

Point Cloud Library (PCL)#

PCL 可用於進階的 3D 點雲處理。來自Stereo mini 相機的距離資料在 Coord3D_ABC32f 此格式可匯入 PCL 資料結構中。

sudo apt-get install libpcl-dev

Download from PCL website.

如需詳細資訊,請參閱《C++ 程式設計師指南》。

ROS 2#

Stereo mini 可透過以下方式將相機整合至 ROS 2: pypylon 作為橋樑與出版 sensor_msgs/Image 主題。

必備套件:

pip install pypylon numpy
sudo apt install ros-humble-rclpy ros-humble-sensor-msgs

在此方法中,會從Stereo mini 的資料元件中讀取影像資料(Intensity, Range) 並發佈至 ROS 主題,例如:

  • /stereo_mini/intensity_rgba8 (編碼 rgba8)
  • /stereo_mini/range_c16_mm (編碼 mono16)

最簡單的橋接範例:

import numpy as np
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from pypylon import pylon


class StereoMiniBridge(Node):
    def __init__(self):
        super().__init__("stereo_mini_bridge")
        self.pub_intensity = self.create_publisher(Image, "/stereo_mini/intensity_rgba8", 10)

        di = pylon.DeviceInfo()
        di.SetDeviceClass("BaslerGTC/Basler/TLModel_keep")
        self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice(di))
        self.camera.Open()

        self.camera.ComponentSelector.Value = "Intensity"
        self.camera.ComponentEnable.Value = True
        try:
            self.camera.PixelFormat.Value = "RGBA8"
        except Exception:
            self.camera.PixelFormat.Value = "RGBA8packed"

        self.camera.StartGrabbing()
        self.timer = self.create_timer(0.03, self.tick)

    def tick(self):
        grab = self.camera.RetrieveResult(3000, pylon.TimeoutHandling_ThrowException)
        try:
            if not grab.GrabSucceeded():
                return
            dc = grab.GetDataContainer()
            for i in range(dc.DataComponentCount):
                c = dc.GetDataComponentByIndex(i)
                try:
                    if c.ComponentType == pylon.ComponentType_Intensity:
                        h, w = c.Height, c.Width
                        rgba = np.frombuffer(c.GetData(), dtype=np.uint8).reshape(h, w, 4)
                        msg = Image()
                        msg.header.stamp = self.get_clock().now().to_msg()
                        msg.header.frame_id = "stereo_mini"
                        msg.height = h
                        msg.width = w
                        msg.encoding = "rgba8"
                        msg.is_bigendian = 0
                        msg.step = w * 4
                        msg.data = rgba.tobytes()
                        self.pub_intensity.publish(msg)
                finally:
                    c.Release()
        finally:
            grab.Release()


def main():
    rclpy.init()
    node = StereoMiniBridge()
    rclpy.spin(node)


if __name__ == "__main__":
    main()