Astra Pro深度相机折腾记
最近在闲鱼花了45元淘了台深度相机,折腾出一套3D目标检测系统:用YOLOv8识别物体,结合深度信息生成3D边界框,Open3D可视化点云。踩了不少坑,在此记录一下。
缘起:一台从闲鱼来的相机
前段时间在闲鱼上刷到了一台 ASTRA Pro 深度相机,价格美丽,卖家说是公司项目结束后的闲置设备。想着最近在尝试点云重建的研究,于是果断入手了。收到货后发现品相不错,就开始了我的深度相机折腾之旅。
什么是深度相机?
简单来说,深度相机不仅能拍摄普通的彩色图像,还能获取场景中每个像素点的距离信息。这就像给普通相机加上了"透视眼",能够感知到三维空间的深度信息。
ASTRA Pro 是奥比中光(Orbbec)出品的一款深度相机,主要特点:
- 支持 RGB 彩色图像和深度图像同时输出
- 基于结构光技术,在室内环境下表现不错
- 支持 OpenNI2 接口,开发起来相对友好
搭建开发环境
首先需要安装一堆依赖库:
# 主要依赖
pip install opencv-python
pip install numpy
pip install open3d
pip install ultralytics
pip install PyYAML
然后是 OpenNI2 的安装,这个稍微麻烦一些,需要根据系统版本下载对应的驱动。
1. 驱动安装
- 下载地址:Orbbec Camera Driver for Windows
- 官网入口:www.orbbec3d.com(需点击"更多"按钮)
- 安装后必须重启电脑
- 验证:在设备管理器中查看
Orbbec/ORBBEC Depth Sensor
2. OpenNI SDK配置
- 下载SDK:Orbbec OpenNI SDK
- 安装步骤:
- 解压压缩包
- 复制
Win64-Release
文件夹内容到C:\Program Files\Orbbec\OpenNI
- 测试工具:运行
OpenNI\tools\NiViewer\NiViewer.exe
3. 环境变量设置
临时设置(当前会话有效)
$Env:OPENNI2_REDIST64="C:/Program Files/Orbbec/OpenNI/sdk/libs"
永久设置(需要重启终端)
[Environment]::SetEnvironmentVariable("OPENNI2_REDIST64", "C:/Program Files/Orbbec/OpenNI/sdk/libs", "Machine")
代码架构设计
整个程序的核心思路是:
- 同时获取 RGB 图像和深度图像
- 用 YOLOv8 检测 RGB 图像中的物体
- 结合深度信息生成 3D 边界框
- 用 Open3D 实现点云和 3D 边界框的可视化
配置文件管理
为了方便调试,我把相机参数都写在了 YAML 配置文件里:
Camera:
width: 640
height: 480
fps: 30
fx: 570.3
fy: 570.3
cx: 320.0
cy: 240.0
DepthMapFactor: 1000.0
Viewer:
point_size: 4.0
background_color: [0, 0, 0]
这样调参数的时候就不用重新编译了,改完配置文件重启程序就行。
核心功能实现
1. 双摄像头同步
最开始遇到的问题是 RGB 摄像头和深度摄像头的同步问题。深度相机内置的 RGB 模块质量一般,所以我另外接了一个 USB 摄像头。
# 初始化深度流
depth_stream = dev.create_depth_stream()
depth_stream.set_video_mode(...)
depth_stream.start()
# 初始化 RGB 摄像头
cap = cv2.VideoCapture(1) # 注意索引号
2. YOLO 目标检测
用的是 YOLOv8n 模型,轻量级,在我的笔记本上跑起来还算流畅:
model = YOLO('yolov8n.pt')
results = model(rgb_frame, conf=0.4, iou=0.7)

3. 3D 边界框生成
这部分是最有趣的,通过深度信息把 2D 检测框转换成 3D 边界框:
def get_3d_bbox_from_2d(x1, y1, x2, y2, depth, fx, fy, cx, cy):
# 获取边界框区域的深度值
mask = depth[y1:y2, x1:x2]
valid_depths = mask[mask > 0]
# 计算深度范围
zmin, zmax = np.percentile(valid_depths, [10, 90])
# 投影到3D空间
# ... 详细计算过程
4. 目标跟踪
为了让检测结果更稳定,加了个简单的基于 IoU 的目标跟踪:
def track_boxes(prev_boxes, new_boxes, iou_threshold=0.5):
# 计算新旧边界框的重叠度
# 关联最匹配的边界框
# 对于消失的目标,逐渐降低置信度
这样就避免了检测框在连续帧间剧烈跳动的问题。
实际效果
点云与3D边界框可视化
生成的点云效果还是很不错的,同时检测到的物体会用不同颜色的 3D 边界框标出来,并且显示距离信息:

深度图可视化
深度图用热力图的形式展示,近的地方是红色,远的地方是浅黄色:
遇到的坑
1. 相机内参标定
最开始直接用了网上找的参数,结果投影出来的 3D 点云完全变形了。后来老老实实用棋盘格标定了一遍,效果好了很多。
2. 坐标系转换
OpenCV、Open3D 和深度相机的坐标系都不太一样,需要做坐标转换。我用了一个变换矩阵:
COORD_TRANSFORM = np.array([
[1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, 1]
])
3. 性能优化
最开始程序跑起来很卡,后来发现是点云密度太高了。加了体素下采样后流畅了很多:
pcl = pcl.voxel_down_sample(voxel_size=0.005)
4. 内存管理
Open3D 的几何体对象需要手动管理,不然会内存泄漏。特别是在循环中创建 LineSet 的时候,需要复用对象而不是每次都创建新的。
交互控制
加了一些简单的键盘控制:
+
和-
键控制缩放q
键退出程序
key = cv2.waitKey(1)
if key == ord('+'):
zoom_level = max(0.1, zoom_level * 0.8)
vis.get_view_control().set_zoom(zoom_level)
elif key == ord('q'):
break
后续计划
这个小项目还有很多可以改进的地方:
- SLAM 功能:加入视觉里程计,实现实时建图
- 手势识别:利用深度信息识别手势
- 物体抓取:结合机械臂做物体抓取
- AR 应用:在现实场景中叠加虚拟物体

P.S. 点云的世界远比我想象的要精彩,这只是个开始... 🚀