2、深度数据获取:使用OpenCV和librealsense读取Intel RealSense深度流
好,咱们正式开始动手了。
上一章我们聊了深度相机的基本原理,这一章直接进入实操——怎么把RealSense的深度数据真正拿到手里。说白了,就是让你的电脑和相机“对上话”,然后把深度图、点云这些宝贝数据存下来。
2.1 环境准备:装好librealsense和OpenCV
我习惯先把环境搭利索了再写代码。不然调试到一半发现缺库,那感觉,嗯,你懂的。
第一步:安装librealsense SDK
Intel官方提供了很完善的SDK,叫librealsense。我个人建议直接从GitHub clone源码编译,这样能保证拿到最新的特性。当然,如果你图省事,用包管理器也行。
# Ubuntu / Debian 系
sudo apt-get install librealsense2-dev librealsense2-dkms
# macOS (Homebrew)
brew install librealsense
# Windows
# 直接下载 Intel.RealSense.SDK.exe 安装包
第二步:安装OpenCV
OpenCV负责图像处理和可视化。我一般用4.5以上的版本,对深度数据支持更好。
pip install opencv-python opencv-contrib-python
realsense 组里。我曾经在这卡了半小时,后来发现就是少了个 sudo usermod -aG realsense $USER。
2.2 初始化相机:配置分辨率与帧率
相机连上之后,第一件事就是配置参数。分辨率、帧率、深度范围,这些都得提前想好。
为什么会这样?因为不同的应用场景对参数要求完全不同。比如做手势识别,VGA分辨率(640×480)就够用,帧率可以跑到60fps;但如果你要做三维重建,那最好上1280×720,帧率降到30fps,保证点云密度。
import pyrealsense2 as rs
import numpy as np
import cv2
# 创建管道
pipeline = rs.pipeline()
config = rs.config()
# 配置深度流和彩色流
config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
# 启动管道
profile = pipeline.start(config)
这里有个细节:rs.format.z16 表示深度数据以16位无符号整数存储,每个像素的值代表毫米单位的距离。说白了,值越大,离相机越远。
2.3 获取帧数据:深度图与彩色图
配置好了,接下来就是循环读取数据。RealSense的API设计得很直观:每次调用 wait_for_frames() 就会返回一帧数据。
try:
while True:
# 等待一帧数据
frames = pipeline.wait_for_frames()
# 获取深度帧和彩色帧
depth_frame = frames.get_depth_frame()
color_frame = frames.get_color_frame()
if not depth_frame or not color_frame:
continue
# 转为numpy数组
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# 显示
cv2.imshow('Depth', depth_image)
cv2.imshow('Color', color_image)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
pipeline.stop()
cv2.destroyAllWindows()
你想想看,就这么几行代码,深度数据就源源不断地流进来了。是不是挺爽的?
wait_for_frames() 是阻塞的。如果你的主循环里还有其他任务(比如UI更新),建议用多线程或者异步方式处理。我曾经在实时交互项目里忘了这茬,结果界面卡得跟幻灯片似的。
2.4 深度图可视化与保存
原始深度图看起来是灰蒙蒙的,因为它是16位单通道数据。直接显示的话,近处亮、远处暗,但细节不明显。我习惯做一下归一化,让视觉效果更舒服。
# 深度图归一化到0-255
depth_colormap = cv2.applyColorMap(
cv2.convertScaleAbs(depth_image, alpha=0.03),
cv2.COLORMAP_JET
)
# 保存深度图
cv2.imwrite('depth_raw.png', depth_image) # 原始16位
cv2.imwrite('depth_colormap.png', depth_colormap) # 伪彩色
cv2.imwrite('color.png', color_image) # 彩色图
这里 alpha=0.03 是个经验值。它把深度值从毫米范围映射到0-255。如果你的场景距离范围不同,可以调整这个系数。比如近距离扫描,alpha可以设大一点。
2.5 点云生成与保存
深度图是二维的,点云才是三维的。RealSense SDK内置了点云生成功能,非常方便。
# 创建点云对象
pc = rs.pointcloud()
# 将深度帧转换为点云
points = pc.calculate(depth_frame)
# 获取顶点和纹理坐标
vertices = np.asanyarray(points.get_vertices()).view(np.float32).reshape(-1, 3)
tex_coords = np.asanyarray(points.get_texture_coordinates()).view(np.float32).reshape(-1, 2)
# 保存为PLY格式
points.export_to_ply('output.ply', color_frame)
保存成PLY格式后,你可以用MeshLab、CloudCompare或者Blender打开查看。我个人习惯用PLY,因为它同时支持顶点颜色,彩色点云看起来更直观。
texture_coordinates 的精度。默认是float32,如果你对精度要求不高,可以转成float16,文件大小直接减半。
2.6 知识体系总览
下面这张图概括了本章的核心流程。从硬件初始化到数据获取,再到保存,每一步都有对应的API和注意事项。
2.7 常见问题与调试技巧
最后分享几个我实际项目中遇到的坑,希望能帮你省点时间。
| 问题 | 现象 | 解决方案 |
|---|---|---|
| 相机无法启动 | pipeline.start() 抛出异常 | 检查USB接口是否为3.0,RealSense需要高带宽 |
| 深度图全黑 | 所有像素值为0 | 可能是距离太近(<0.3m)或太远(>10m),调整深度范围 |
| 点云文件巨大 | 一个PLY文件几百MB | 降低分辨率,或者用体素滤波下采样 |
| 彩色和深度不对齐 | 边缘出现重影 | 使用 rs.align 进行对齐处理 |
嗯,这一章的内容就到这里。代码不多,但每一步都是实打实的操作。你把这些跑通了,后面做手势识别、三维重建就有了坚实的基础。