4. 深度相机点云获取
任务目标
本案例使用Intel RealSense深度相机(以D435i为例)完成以下闭环:获取彩色图像与对齐后的深度图像,并基于相机内参将深度图转换为彩色点云(XYZRGB),最终以PLY格式保存,供后续机器人抓取位姿估计使用。
环境依赖
- Python 3.8+
- pyrealsense2(RealSense SDK)
- OpenCV(
opencv-python) - NumPy
- Open3D(用于点云保存与可视化验证)
安装命令:pip install pyrealsense2 opencv-python numpy open3d
关键完整代码
import pyrealsense2 as rs
import numpy as np
import cv2
import open3d as o3d
# 1. 配置相机流:彩色1280x720@30fps,深度1280x720@30fps
pipeline = rs.pipeline()
config = rs.config()
config.enable_stream(rs.stream.color, 1280, 720, rs.format.bgr8, 30)
config.enable_stream(rs.stream.depth, 1280, 720, rs.format.z16, 30)
# 2. 启动相机并获取对齐后的深度帧
profile = pipeline.start(config)
align = rs.align(rs.stream.color) # 将深度图对齐到彩色图坐标系
try:
# 等待稳定帧(跳过前5帧)
for _ in range(5):
pipeline.wait_for_frames()
frames = pipeline.wait_for_frames()
aligned_frames = align.process(frames)
color_frame = aligned_frames.get_color_frame()
depth_frame = aligned_frames.get_depth_frame()
if not color_frame or not depth_frame:
raise RuntimeError("无法获取对齐后的彩色/深度帧")
# 3. 转换为numpy数组
color_image = np.asanyarray(color_frame.get_data()) # BGR
depth_image = np.asanyarray(depth_frame.get_data()) # 单位:毫米
# 4. 获取相机内参(基于彩色流)
intr = profile.get_stream(rs.stream.color).as_video_stream_profile().get_intrinsics()
fx, fy = intr.fx, intr.fy
cx, cy = intr.ppx, intr.ppy
# 5. 生成点云(仅保留深度有效点)
h, w = depth_image.shape
K = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]])
# 构建像素坐标网格
u, v = np.meshgrid(np.arange(w), np.arange(h))
z = depth_image.astype(np.float64) / 1000.0 # 毫米转米
# 反投影:p_cam = K^{-1} * [u, v, 1]^T * z
ones = np.ones_like(u)
pixels = np.stack([u, v, ones], axis=-1).reshape(-1, 3) # (N,3)
K_inv = np.linalg.inv(K)
cam_coords = (K_inv @ pixels.T).T * z.reshape(-1, 1) # (N,3)
# 提取颜色(BGR转RGB)
colors = color_image.reshape(-1, 3)[:, ::-1] # 转为RGB
# 过滤深度为0的无效点
valid = z.reshape(-1) > 0
points = cam_coords[valid]
point_colors = colors[valid]
# 6. 构建Open3D点云并保存为PLY
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
pcd.colors = o3d.utility.Vector3dVector(point_colors.astype(np.float64) / 255.0)
o3d.io.write_point_cloud("scene_pointcloud.ply", pcd)
print(f"点云生成完成:{len(points)} 个点,已保存为 scene_pointcloud.ply")
# 7. 可视化验证(可选)
o3d.visualization.draw_geometries([pcd])
finally:
pipeline.stop()
运行与验证
- 运行:将代码保存为
capture_pointcloud.py,连接RealSense相机后执行python capture_pointcloud.py。 - 预期输出:终端打印点云点数,当前目录生成
scene_pointcloud.ply文件,并弹出Open3D可视化窗口显示彩色3D点云。 - 通过条件:
- 点云文件存在且非空(文件大小通常大于1MB);
- 可视化窗口中场景物体轮廓清晰、颜色与真实场景一致;
- 点云中物体边缘无明显错位(验证深度对齐正确)。
常见问题
- 无相机连接:检查USB 3.0接口及驱动,运行
rs-enumerate-devices确认设备可见。 - 深度图全零:相机启动初期或光照过强导致,增加预热帧数或调整相机位置。
- 点云噪声大:可对深度图应用中值滤波(
cv2.medianBlur)后再反投影。