타사 드라이버, 라이브러리 및 샘플#
NumPy#
Python 샘플에서는 pypylon이 반환하는 로우 컴포넌트 데이터를 처리하기 위해 NumPy가 사용됩니다.
OpenCV#
OpenCV를 사용하여 Stereo mini 카메라에서 가져온 강도(intensity) 이미지를 처리할 수 있습니다. 강도 컴포넌트는 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 포인트 클라우드를 시각화하는 데 사용됩니다. 범위(range) 컴포넌트는 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 포인트 클라우드 처리에 사용할 수 있습니다. Coord3D_ABC32f 형식의 Stereo mini 카메라 범위 데이터를 PCL 데이터 구조에 입력할 수 있습니다.
Download from PCL website.
자세한 내용은 C++ Programmer's Guide를 참조하십시오.
ROS 2#
Stereo mini 카메라는 pypylon 을(를) 브리지로 사용하고 sensor_msgs/Image 토픽을 발행(publishing)하여 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()