第三方驱动程序、库和示例#
NumPy#
Python 示例中使用了 NumPy 来处理 pypylon 返回的原始分量数据。
OpenCV#
OpenCV 可用于处理从 Stereo mini 相机获取的强度图像。强度分量提供了一个 RGBA8 图像,可以将其转换为适合 OpenCV 处理的格式。
示例:将强度分量转换为 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 用于 ShowPointCloud 示例中,以可视化来自 Stereo mini 相机的 3D 点云。其中的距离分量 Coord3D_ABC32f 格式直接提供 XYZ 坐标。
示例:从距离和强度数据构建 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 数据结构中。
Download from PCL website.
有关详细信息,请参阅 C++ 程序员指南。
ROS 2#
Stereo mini 相机可以通过使用 pypylon 作为桥接并发布 sensor_msgs/Image 主题来集成到 ROS 2 中。
所需的软件包:
在此方法中,从 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()