chore: initial commit — import worldmodel workspace (plans/, research/)
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# 摄像头方案文档集
|
||||
|
||||
本目录包含酒店场景3D重建的各类摄像头方案详细分析。
|
||||
|
||||
## 📷 文档列表
|
||||
|
||||
### 1. [摄像头方案全解析](camera_solutions_comprehensive.md)
|
||||
完整的摄像头技术方案对比与选型指南
|
||||
|
||||
**涵盖内容**:
|
||||
- 单目相机方案(低成本)
|
||||
- 双目相机方案(立体视觉)
|
||||
- 深度相机方案(RGB-D)
|
||||
- 多传感器融合方案(高精度)
|
||||
- 性能对比与选型建议
|
||||
|
||||
## 🎯 快速选型指南
|
||||
|
||||
### 按预算选择
|
||||
|
||||
| 预算范围 | 推荐方案 | 精度 | 适用场景 |
|
||||
|---------|---------|------|---------|
|
||||
| **< ¥1万** | iPhone 15 Pro | ±5cm | 快速验证、个人项目 |
|
||||
| **¥1-3万** | Azure Kinect DK | ±1cm | 室内高质量重建 |
|
||||
| **¥3-5万** | 双目相机 + LiDAR | ±2cm | 中大型场景 |
|
||||
| **> ¥5万** | 全传感器融合 | ±3mm | 专业项目、科研 |
|
||||
|
||||
### 按场景选择
|
||||
|
||||
**公共区域(大堂、走廊)**:
|
||||
- 推荐:Livox Mid-360 + Sony相机
|
||||
- 原因:远距离、大范围覆盖
|
||||
- 成本:¥28,000
|
||||
|
||||
**客房**:
|
||||
- 推荐:Azure Kinect DK
|
||||
- 原因:高质量RGB-D、适合室内
|
||||
- 成本:¥3,000
|
||||
|
||||
**卫生间(高反光)**:
|
||||
- 推荐:偏振相机 + RealSense L515
|
||||
- 原因:抗反光、高精度
|
||||
- 成本:¥7,000
|
||||
|
||||
## 📊 方案对比矩阵
|
||||
|
||||
| 方案类型 | 成本 | 精度 | 实时性 | 难度 | 推荐度 |
|
||||
|---------|------|------|--------|------|--------|
|
||||
| **单目相机** | ¥7k-¥43k | ±3-5cm | ❌ | ⭐⭐ | ⭐⭐⭐ |
|
||||
| **双目相机** | ¥4k-¥11k | ±1-3cm | ✅ | ⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||||
| **深度相机** | ¥1.5k-¥4k | ±1cm | ✅ | ⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
| **多传感器融合** | ¥28k-¥35k | ±3mm | ✅ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
|
||||
|
||||
## 🚀 推荐配置
|
||||
|
||||
### 方案A:性价比之选(¥10,000)
|
||||
```
|
||||
Azure Kinect DK (¥3,000)
|
||||
+ Canon EOS R10 (¥7,000)
|
||||
= 深度 + 高分辨率纹理
|
||||
```
|
||||
|
||||
### 方案B:专业级(¥35,000)
|
||||
```
|
||||
Livox Mid-360 (¥1,500)
|
||||
+ Azure Kinect DK (¥3,000)
|
||||
+ Sony α7R V (¥27,000)
|
||||
+ Xsens IMU (¥3,500)
|
||||
= 最高精度全方位覆盖
|
||||
```
|
||||
|
||||
### 方案C:快速验证(¥10,000)
|
||||
```
|
||||
iPhone 15 Pro Max (¥10,000)
|
||||
= 零学习成本,立即开始
|
||||
```
|
||||
|
||||
## 📞 相关资源
|
||||
|
||||
- iPhone方案:[`../iphone/`](../iphone/)
|
||||
- 完整实施计划:[`../hotel_scene_implementation_plan.md`](../hotel_scene_implementation_plan.md)
|
||||
- 数据格式规范:[`../data_format_specification.md`](../data_format_specification.md)
|
||||
|
||||
---
|
||||
|
||||
**最后更新**:2026-05-16
|
||||
**维护者**:项目规划团队
|
||||
@@ -0,0 +1,712 @@
|
||||
# 酒店场景3D重建摄像头方案全解析
|
||||
|
||||
## 📷 文档概述
|
||||
|
||||
本文档全面分析单目、双目、深度相机及多传感器融合方案,为酒店场景3D重建提供完整的硬件选型指南。
|
||||
|
||||
**涵盖内容**:
|
||||
- 单目相机方案(低成本)
|
||||
- 双目相机方案(立体视觉)
|
||||
- 深度相机方案(RGB-D)
|
||||
- 多传感器融合方案(高精度)
|
||||
- 性能对比与选型建议
|
||||
|
||||
---
|
||||
|
||||
## 一、单目相机方案
|
||||
|
||||
### 1.1 技术原理
|
||||
|
||||
```yaml
|
||||
工作原理:
|
||||
- 单个相机拍摄多张照片
|
||||
- 通过运动恢复结构(SfM)
|
||||
- 估计相机位姿和3D点云
|
||||
- 基于多视图几何
|
||||
|
||||
优势:
|
||||
- 成本最低
|
||||
- 设备简单
|
||||
- 便携性强
|
||||
- 适合大场景
|
||||
|
||||
劣势:
|
||||
- 无绝对尺度
|
||||
- 需要纹理丰富
|
||||
- 处理时间长
|
||||
- 弱纹理区域失败
|
||||
```
|
||||
|
||||
### 1.2 硬件配置
|
||||
|
||||
#### 方案A:专业相机(高质量)
|
||||
|
||||
| 设备 | 型号 | 价格 | 参数 |
|
||||
|-----|------|------|------|
|
||||
| **相机** | Sony α7R V | ¥26,999 | 61MP, 全画幅 |
|
||||
| **镜头** | Sony FE 24mm F1.4 GM | ¥10,999 | 广角定焦 |
|
||||
| **三脚架** | Manfrotto 055 | ¥1,999 | 碳纤维 |
|
||||
| **存储卡** | Sony CFexpress 256GB | ¥2,999 | 高速读写 |
|
||||
| **总计** | | **¥42,996** | |
|
||||
|
||||
**适用场景**:高质量纹理采集、商业项目、论文发表
|
||||
|
||||
#### 方案B:消费级相机(性价比)
|
||||
|
||||
| 设备 | 型号 | 价格 | 参数 |
|
||||
|-----|------|------|------|
|
||||
| **相机** | Canon EOS R10 | ¥6,999 | 24MP, APS-C |
|
||||
| **镜头** | Canon RF-S 18-45mm | ¥1,299 | 套机镜头 |
|
||||
| **三脚架** | 曼富图 Compact | ¥299 | 铝合金 |
|
||||
| **存储卡** | SanDisk 128GB | ¥199 | UHS-I |
|
||||
| **总计** | | **¥8,796** | |
|
||||
|
||||
**适用场景**:预算有限、快速验证、教学演示
|
||||
|
||||
#### 方案C:智能手机(超低成本)
|
||||
|
||||
| 设备 | 型号 | 价格 | 参数 |
|
||||
|-----|------|------|------|
|
||||
| **手机** | iPhone 15 Pro Max | ¥9,999 | 48MP主摄 |
|
||||
| **或** | 小米14 Ultra | ¥6,499 | 50MP主摄 |
|
||||
| **稳定器** | DJI OM 6 | ¥899 | 三轴稳定 |
|
||||
| **总计** | | **¥7,398-¥10,898** | |
|
||||
|
||||
**适用场景**:个人项目、快速采集、移动便携
|
||||
|
||||
### 1.3 采集流程
|
||||
|
||||
```yaml
|
||||
步骤1_拍摄规划:
|
||||
- 确定拍摄路线(环绕房间)
|
||||
- 设置相机参数(固定焦距、光圈)
|
||||
- 重叠率:70-80%
|
||||
- 拍摄数量:200-500张/房间
|
||||
|
||||
步骤2_拍摄技巧:
|
||||
- 保持相机水平
|
||||
- 避免运动模糊
|
||||
- 多角度覆盖
|
||||
- 重点区域密集拍摄
|
||||
|
||||
步骤3_数据处理:
|
||||
- COLMAP进行SfM
|
||||
- 生成稀疏点云
|
||||
- 稠密重建(MVS)
|
||||
- 网格生成
|
||||
```
|
||||
|
||||
### 1.4 软件工具链
|
||||
|
||||
```bash
|
||||
# COLMAP处理流程
|
||||
# 1. 特征提取
|
||||
colmap feature_extractor \
|
||||
--database_path database.db \
|
||||
--image_path images/ \
|
||||
--ImageReader.camera_model PINHOLE
|
||||
|
||||
# 2. 特征匹配
|
||||
colmap exhaustive_matcher \
|
||||
--database_path database.db
|
||||
|
||||
# 3. 稀疏重建
|
||||
colmap mapper \
|
||||
--database_path database.db \
|
||||
--image_path images/ \
|
||||
--output_path sparse/
|
||||
|
||||
# 4. 稠密重建
|
||||
colmap image_undistorter \
|
||||
--image_path images/ \
|
||||
--input_path sparse/0 \
|
||||
--output_path dense/
|
||||
|
||||
colmap patch_match_stereo \
|
||||
--workspace_path dense/
|
||||
|
||||
colmap stereo_fusion \
|
||||
--workspace_path dense/ \
|
||||
--output_path dense/fused.ply
|
||||
```
|
||||
|
||||
### 1.5 性能指标
|
||||
|
||||
| 指标 | 专业相机 | 消费级相机 | 智能手机 |
|
||||
|-----|---------|-----------|---------|
|
||||
| **几何精度** | ±2-3cm | ±3-5cm | ±5-8cm |
|
||||
| **纹理质量** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||||
| **处理时间** | 2-4小时 | 2-4小时 | 2-4小时 |
|
||||
| **采集时间** | 30-60分钟 | 30-60分钟 | 20-40分钟 |
|
||||
| **成本** | ¥43,000 | ¥8,800 | ¥7,400 |
|
||||
|
||||
---
|
||||
|
||||
## 二、双目相机方案
|
||||
|
||||
### 2.1 技术原理
|
||||
|
||||
```yaml
|
||||
工作原理:
|
||||
- 两个相机模拟人眼
|
||||
- 同步拍摄同一场景
|
||||
- 通过视差计算深度
|
||||
- 实时立体匹配
|
||||
|
||||
优势:
|
||||
- 实时深度估计
|
||||
- 无需运动
|
||||
- 尺度准确
|
||||
- 适合动态场景
|
||||
|
||||
劣势:
|
||||
- 需要标定
|
||||
- 基线限制范围
|
||||
- 弱纹理失效
|
||||
- 成本较高
|
||||
```
|
||||
|
||||
### 2.2 硬件配置
|
||||
|
||||
#### 方案A:工业双目相机(高精度)
|
||||
|
||||
| 设备 | 型号 | 价格 | 参数 |
|
||||
|-----|------|------|------|
|
||||
| **双目相机** | ZED 2i | ¥3,999 | 2.2K@15fps, 基线120mm |
|
||||
| **或** | Intel RealSense D455 | ¥2,999 | 1280×720, 基线95mm |
|
||||
| **或** | Luxonis OAK-D Pro | ¥4,999 | 4K, AI加速 |
|
||||
| **支架** | 定制铝合金支架 | ¥500 | 稳定安装 |
|
||||
| **计算单元** | NVIDIA Jetson Orin Nano | ¥2,999 | 边缘计算 |
|
||||
| **总计** | | **¥7,498-¥8,498** | |
|
||||
|
||||
**适用场景**:实时建图、机器人导航、动态场景
|
||||
|
||||
#### 方案B:DIY双目系统(定制化)
|
||||
|
||||
| 设备 | 型号 | 数量 | 单价 | 小计 |
|
||||
|-----|------|------|------|------|
|
||||
| **工业相机** | FLIR Blackfly S | 2 | ¥3,500 | ¥7,000 |
|
||||
| **镜头** | 6mm定焦镜头 | 2 | ¥800 | ¥1,600 |
|
||||
| **同步器** | 硬件触发器 | 1 | ¥500 | ¥500 |
|
||||
| **支架** | 精密滑轨 | 1 | ¥1,500 | ¥1,500 |
|
||||
| **总计** | | | | **¥10,600** |
|
||||
|
||||
**适用场景**:科研项目、定制基线、特殊需求
|
||||
|
||||
### 2.3 关键参数设置
|
||||
|
||||
```yaml
|
||||
基线距离(Baseline):
|
||||
- 近距离(< 2m): 60-100mm
|
||||
- 中距离(2-5m): 100-150mm
|
||||
- 远距离(> 5m): 150-300mm
|
||||
|
||||
酒店客房推荐: 120mm
|
||||
公共区域推荐: 200mm
|
||||
|
||||
分辨率:
|
||||
- 最低: 1280×720 (HD)
|
||||
- 推荐: 1920×1080 (FHD)
|
||||
- 高质量: 2560×1440 (2K)
|
||||
|
||||
帧率:
|
||||
- 静态扫描: 15-30 fps
|
||||
- 动态场景: 30-60 fps
|
||||
- 高速运动: 60-120 fps
|
||||
|
||||
视场角(FOV):
|
||||
- 窄视场: 60-70° (远距离)
|
||||
- 标准视场: 80-90° (通用)
|
||||
- 广视场: 100-120° (室内)
|
||||
```
|
||||
|
||||
### 2.4 标定流程
|
||||
|
||||
```python
|
||||
# 双目相机标定(OpenCV)
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
def calibrate_stereo_camera():
|
||||
"""双目相机标定"""
|
||||
|
||||
# 1. 准备标定板(棋盘格)
|
||||
pattern_size = (9, 6) # 内角点数量
|
||||
square_size = 0.025 # 25mm方格
|
||||
|
||||
# 2. 采集标定图像(20-30对)
|
||||
left_images = [] # 左相机图像
|
||||
right_images = [] # 右相机图像
|
||||
|
||||
# 3. 检测角点
|
||||
obj_points = [] # 3D点
|
||||
img_points_left = [] # 左图像点
|
||||
img_points_right = [] # 右图像点
|
||||
|
||||
for left_img, right_img in zip(left_images, right_images):
|
||||
# 检测角点
|
||||
ret_l, corners_l = cv2.findChessboardCorners(left_img, pattern_size)
|
||||
ret_r, corners_r = cv2.findChessboardCorners(right_img, pattern_size)
|
||||
|
||||
if ret_l and ret_r:
|
||||
# 亚像素精化
|
||||
corners_l = cv2.cornerSubPix(left_img, corners_l, (11,11), (-1,-1), criteria)
|
||||
corners_r = cv2.cornerSubPix(right_img, corners_r, (11,11), (-1,-1), criteria)
|
||||
|
||||
img_points_left.append(corners_l)
|
||||
img_points_right.append(corners_r)
|
||||
obj_points.append(objp)
|
||||
|
||||
# 4. 单目标定
|
||||
ret_l, K_l, dist_l, rvecs_l, tvecs_l = cv2.calibrateCamera(
|
||||
obj_points, img_points_left, left_img.shape[::-1], None, None
|
||||
)
|
||||
|
||||
ret_r, K_r, dist_r, rvecs_r, tvecs_r = cv2.calibrateCamera(
|
||||
obj_points, img_points_right, right_img.shape[::-1], None, None
|
||||
)
|
||||
|
||||
# 5. 双目标定
|
||||
ret, K_l, dist_l, K_r, dist_r, R, T, E, F = cv2.stereoCalibrate(
|
||||
obj_points, img_points_left, img_points_right,
|
||||
K_l, dist_l, K_r, dist_r,
|
||||
left_img.shape[::-1],
|
||||
flags=cv2.CALIB_FIX_INTRINSIC
|
||||
)
|
||||
|
||||
# 6. 立体校正
|
||||
R_l, R_r, P_l, P_r, Q, roi_l, roi_r = cv2.stereoRectify(
|
||||
K_l, dist_l, K_r, dist_r,
|
||||
left_img.shape[::-1], R, T,
|
||||
alpha=0
|
||||
)
|
||||
|
||||
# 7. 保存标定结果
|
||||
calibration_data = {
|
||||
'K_left': K_l,
|
||||
'dist_left': dist_l,
|
||||
'K_right': K_r,
|
||||
'dist_right': dist_r,
|
||||
'R': R,
|
||||
'T': T,
|
||||
'R_left': R_l,
|
||||
'R_right': R_r,
|
||||
'P_left': P_l,
|
||||
'P_right': P_r,
|
||||
'Q': Q
|
||||
}
|
||||
|
||||
np.savez('stereo_calibration.npz', **calibration_data)
|
||||
|
||||
return calibration_data
|
||||
```
|
||||
|
||||
### 2.5 深度计算
|
||||
|
||||
```python
|
||||
# 立体匹配与深度计算
|
||||
def compute_depth_map(left_img, right_img, calibration):
|
||||
"""计算深度图"""
|
||||
|
||||
# 1. 加载标定参数
|
||||
calib = np.load('stereo_calibration.npz')
|
||||
|
||||
# 2. 图像校正
|
||||
map_l_x, map_l_y = cv2.initUndistortRectifyMap(
|
||||
calib['K_left'], calib['dist_left'], calib['R_left'],
|
||||
calib['P_left'], left_img.shape[::-1], cv2.CV_32FC1
|
||||
)
|
||||
|
||||
map_r_x, map_r_y = cv2.initUndistortRectifyMap(
|
||||
calib['K_right'], calib['dist_right'], calib['R_right'],
|
||||
calib['P_right'], right_img.shape[::-1], cv2.CV_32FC1
|
||||
)
|
||||
|
||||
left_rectified = cv2.remap(left_img, map_l_x, map_l_y, cv2.INTER_LINEAR)
|
||||
right_rectified = cv2.remap(right_img, map_r_x, map_r_y, cv2.INTER_LINEAR)
|
||||
|
||||
# 3. 立体匹配(SGBM算法)
|
||||
stereo = cv2.StereoSGBM_create(
|
||||
minDisparity=0,
|
||||
numDisparities=128, # 必须是16的倍数
|
||||
blockSize=5,
|
||||
P1=8 * 3 * 5**2,
|
||||
P2=32 * 3 * 5**2,
|
||||
disp12MaxDiff=1,
|
||||
uniquenessRatio=10,
|
||||
speckleWindowSize=100,
|
||||
speckleRange=32,
|
||||
mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
|
||||
)
|
||||
|
||||
disparity = stereo.compute(left_rectified, right_rectified).astype(np.float32) / 16.0
|
||||
|
||||
# 4. 视差转深度
|
||||
depth = cv2.reprojectImageTo3D(disparity, calib['Q'])
|
||||
|
||||
return depth, disparity
|
||||
```
|
||||
|
||||
### 2.6 性能指标
|
||||
|
||||
| 指标 | ZED 2i | RealSense D455 | OAK-D Pro | DIY系统 |
|
||||
|-----|--------|----------------|-----------|---------|
|
||||
| **深度精度** | ±1-2% | ±2% | ±1% | ±1-3% |
|
||||
| **测距范围** | 0.3-20m | 0.6-6m | 0.4-15m | 可定制 |
|
||||
| **帧率** | 15 fps | 90 fps | 60 fps | 30-60 fps |
|
||||
| **分辨率** | 2.2K | 1280×720 | 4K | 可定制 |
|
||||
| **成本** | ¥4,000 | ¥3,000 | ¥5,000 | ¥10,600 |
|
||||
|
||||
---
|
||||
|
||||
## 三、深度相机方案(RGB-D)
|
||||
|
||||
### 3.1 技术原理
|
||||
|
||||
```yaml
|
||||
ToF(Time-of-Flight):
|
||||
原理: 测量光飞行时间
|
||||
代表: Azure Kinect, RealSense L515
|
||||
优势: 远距离、抗环境光
|
||||
劣势: 分辨率低、多机干扰
|
||||
|
||||
结构光(Structured Light):
|
||||
原理: 投射编码光图案
|
||||
代表: RealSense D435, Kinect v1
|
||||
优势: 精度高、成本低
|
||||
劣势: 室外失效、基线限制
|
||||
|
||||
激光雷达(LiDAR):
|
||||
原理: 激光扫描测距
|
||||
代表: Livox Mid-360, Ouster
|
||||
优势: 远距离、高精度
|
||||
劣势: 成本高、点云稀疏
|
||||
```
|
||||
|
||||
### 3.2 硬件配置
|
||||
|
||||
#### 方案A:Azure Kinect DK(推荐)
|
||||
|
||||
```yaml
|
||||
设备: Microsoft Azure Kinect DK
|
||||
价格: ¥2,999
|
||||
|
||||
规格:
|
||||
RGB相机: 4K (3840×2160) @ 30fps
|
||||
深度相机: 1024×1024 @ 30fps (ToF)
|
||||
测距范围: 0.25m - 5.46m
|
||||
深度精度: ±1% @ 1m
|
||||
视场角: 75°×65° (NFOV), 120°×120° (WFOV)
|
||||
IMU: 6轴加速度计+陀螺仪
|
||||
|
||||
优势:
|
||||
- 高分辨率RGB
|
||||
- 宽视场角
|
||||
- SDK完善
|
||||
- 多机同步
|
||||
|
||||
劣势:
|
||||
- 已停产(库存有限)
|
||||
- 功耗较高
|
||||
- 需要USB 3.0
|
||||
|
||||
适用场景:
|
||||
- 室内高质量重建
|
||||
- 人体骨骼追踪
|
||||
- 混合现实应用
|
||||
```
|
||||
|
||||
#### 方案B:Intel RealSense系列
|
||||
|
||||
| 型号 | 价格 | 技术 | 测距范围 | 适用场景 |
|
||||
|-----|------|------|---------|---------|
|
||||
| **D435i** | ¥1,999 | 结构光 | 0.3-3m | 近距离精细重建 |
|
||||
| **D455** | ¥2,999 | 结构光 | 0.6-6m | 中距离通用 |
|
||||
| **L515** | ¥3,999 | LiDAR | 0.25-9m | 高精度室内 |
|
||||
|
||||
**推荐组合**:D455(通用)+ L515(高精度补充)
|
||||
|
||||
#### 方案C:Livox Mid-360(激光雷达)
|
||||
|
||||
```yaml
|
||||
设备: Livox Mid-360
|
||||
价格: ¥1,499
|
||||
|
||||
规格:
|
||||
类型: 固态激光雷达
|
||||
测距范围: 0.05m - 70m
|
||||
精度: ±2cm
|
||||
视场角: 360°×59°
|
||||
点频: 200,000 points/s
|
||||
重量: 265g
|
||||
|
||||
优势:
|
||||
- 超远距离
|
||||
- 360°覆盖
|
||||
- 高精度
|
||||
- 性价比高
|
||||
|
||||
劣势:
|
||||
- 无RGB
|
||||
- 需要外接相机
|
||||
- 点云稀疏(近距离)
|
||||
|
||||
适用场景:
|
||||
- 大场景建图
|
||||
- 公共区域
|
||||
- 户外环境
|
||||
```
|
||||
|
||||
### 3.3 多机同步方案
|
||||
|
||||
```python
|
||||
# Azure Kinect多机同步
|
||||
from pykinect_azure import K4A, K4AConfiguration
|
||||
|
||||
def setup_multi_kinect():
|
||||
"""配置多台Kinect同步"""
|
||||
|
||||
# 主机配置
|
||||
master_config = K4AConfiguration()
|
||||
master_config.color_resolution = K4A_COLOR_RESOLUTION_3072P
|
||||
master_config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED
|
||||
master_config.camera_fps = K4A_FRAMES_PER_SECOND_30
|
||||
master_config.synchronized_images_only = True
|
||||
master_config.wired_sync_mode = K4A_WIRED_SYNC_MODE_MASTER
|
||||
|
||||
# 从机配置
|
||||
subordinate_config = K4AConfiguration()
|
||||
subordinate_config.color_resolution = K4A_COLOR_RESOLUTION_3072P
|
||||
subordinate_config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED
|
||||
subordinate_config.camera_fps = K4A_FRAMES_PER_SECOND_30
|
||||
subordinate_config.synchronized_images_only = True
|
||||
subordinate_config.wired_sync_mode = K4A_WIRED_SYNC_MODE_SUBORDINATE
|
||||
subordinate_config.subordinate_delay_off_master_usec = 0
|
||||
|
||||
# 启动设备
|
||||
master = K4A(device_id=0, config=master_config)
|
||||
subordinate1 = K4A(device_id=1, config=subordinate_config)
|
||||
subordinate2 = K4A(device_id=2, config=subordinate_config)
|
||||
|
||||
master.start()
|
||||
subordinate1.start()
|
||||
subordinate2.start()
|
||||
|
||||
return master, [subordinate1, subordinate2]
|
||||
|
||||
# 同步采集
|
||||
def capture_synchronized_frames(master, subordinates):
|
||||
"""同步采集多机数据"""
|
||||
|
||||
# 主机触发
|
||||
master_capture = master.get_capture()
|
||||
|
||||
# 从机同步
|
||||
sub_captures = []
|
||||
for sub in subordinates:
|
||||
sub_capture = sub.get_capture()
|
||||
sub_captures.append(sub_capture)
|
||||
|
||||
# 提取数据
|
||||
frames = {
|
||||
'master': {
|
||||
'rgb': master_capture.color,
|
||||
'depth': master_capture.depth,
|
||||
'timestamp': master_capture.color_timestamp_usec
|
||||
},
|
||||
'subordinates': []
|
||||
}
|
||||
|
||||
for i, sub_cap in enumerate(sub_captures):
|
||||
frames['subordinates'].append({
|
||||
'rgb': sub_cap.color,
|
||||
'depth': sub_cap.depth,
|
||||
'timestamp': sub_cap.color_timestamp_usec
|
||||
})
|
||||
|
||||
return frames
|
||||
```
|
||||
|
||||
### 3.4 深度图处理
|
||||
|
||||
```python
|
||||
# 深度图滤波与优化
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
class DepthProcessor:
|
||||
"""深度图处理器"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def filter_depth(self, depth_map):
|
||||
"""深度图滤波"""
|
||||
|
||||
# 1. 去除无效深度
|
||||
depth_filtered = depth_map.copy()
|
||||
depth_filtered[depth_map == 0] = np.nan
|
||||
|
||||
# 2. 中值滤波(去除噪声)
|
||||
depth_filtered = cv2.medianBlur(
|
||||
depth_filtered.astype(np.float32), 5
|
||||
)
|
||||
|
||||
# 3. 双边滤波(保持边缘)
|
||||
depth_filtered = cv2.bilateralFilter(
|
||||
depth_filtered, 9, 75, 75
|
||||
)
|
||||
|
||||
# 4. 孔洞填充
|
||||
mask = np.isnan(depth_filtered).astype(np.uint8)
|
||||
depth_filled = cv2.inpaint(
|
||||
depth_filtered, mask, 3, cv2.INPAINT_TELEA
|
||||
)
|
||||
|
||||
return depth_filled
|
||||
|
||||
def depth_to_pointcloud(self, depth, rgb, intrinsics):
|
||||
"""深度图转点云"""
|
||||
|
||||
h, w = depth.shape
|
||||
fx, fy = intrinsics['fx'], intrinsics['fy']
|
||||
cx, cy = intrinsics['cx'], intrinsics['cy']
|
||||
|
||||
# 生成像素坐标网格
|
||||
u, v = np.meshgrid(np.arange(w), np.arange(h))
|
||||
|
||||
# 反投影到3D
|
||||
z = depth
|
||||
x = (u - cx) * z / fx
|
||||
y = (v - cy) * z / fy
|
||||
|
||||
# 组合为点云
|
||||
points = np.stack([x, y, z], axis=-1)
|
||||
colors = rgb / 255.0
|
||||
|
||||
# 过滤无效点
|
||||
valid = (z > 0) & (z < 10) # 0-10m范围
|
||||
points = points[valid]
|
||||
colors = colors[valid]
|
||||
|
||||
return points, colors
|
||||
|
||||
def temporal_filter(self, depth_sequence, window_size=5):
|
||||
"""时序滤波(多帧融合)"""
|
||||
|
||||
# 滑动窗口中值滤波
|
||||
filtered_sequence = []
|
||||
|
||||
for i in range(len(depth_sequence)):
|
||||
start = max(0, i - window_size // 2)
|
||||
end = min(len(depth_sequence), i + window_size // 2 + 1)
|
||||
|
||||
window = depth_sequence[start:end]
|
||||
median_depth = np.median(window, axis=0)
|
||||
|
||||
filtered_sequence.append(median_depth)
|
||||
|
||||
return np.array(filtered_sequence)
|
||||
```
|
||||
|
||||
### 3.5 性能对比
|
||||
|
||||
| 设备 | 技术 | 深度精度 | 测距范围 | RGB分辨率 | 价格 | 推荐度 |
|
||||
|-----|------|---------|---------|-----------|------|--------|
|
||||
| **Azure Kinect** | ToF | ±1% @ 1m | 0.25-5.46m | 4K | ¥2,999 | ⭐⭐⭐⭐⭐ |
|
||||
| **RealSense D455** | 结构光 | ±2% | 0.6-6m | 1920×1080 | ¥2,999 | ⭐⭐⭐⭐ |
|
||||
| **RealSense L515** | LiDAR | ±5mm | 0.25-9m | 1920×1080 | ¥3,999 | ⭐⭐⭐⭐⭐ |
|
||||
| **Livox Mid-360** | LiDAR | ±2cm | 0.05-70m | 无 | ¥1,499 | ⭐⭐⭐⭐ |
|
||||
|
||||
---
|
||||
|
||||
## 四、多传感器融合方案
|
||||
|
||||
### 4.1 融合架构
|
||||
|
||||
```yaml
|
||||
方案A_LiDAR + RGB相机:
|
||||
LiDAR: Livox Mid-360
|
||||
相机: Sony α7R V
|
||||
优势: 远距离 + 高质量纹理
|
||||
成本: ¥28,000
|
||||
|
||||
方案B_深度相机 + 单目相机:
|
||||
深度: Azure Kinect
|
||||
相机: Canon EOS R10
|
||||
优势: 深度 + 高分辨率RGB
|
||||
成本: ¥10,000
|
||||
|
||||
方案C_双目 + IMU:
|
||||
双目: ZED 2i
|
||||
IMU: 内置
|
||||
优势: 实时 + 位姿估计
|
||||
成本: ¥4,000
|
||||
|
||||
方案D_全传感器融合:
|
||||
LiDAR: Livox Mid-360
|
||||
RGB-D: Azure Kinect
|
||||
IMU: Xsens MTi-630
|
||||
相机: Sony α7R V
|
||||
优势: 最高精度 + 完整数据
|
||||
成本: ¥35,000
|
||||
```
|
||||
|
||||
### 4.2 传感器标定
|
||||
|
||||
```python
|
||||
# LiDAR-Camera标定
|
||||
import numpy as np
|
||||
from scipy.optimize import least_squares
|
||||
|
||||
class LiDARCameraCalibration:
|
||||
"""LiDAR-相机外参标定"""
|
||||
|
||||
def __init__(self):
|
||||
self.correspondences = [] # 对应点对
|
||||
|
||||
def collect_correspondences(self, lidar_points, image_points, camera_K):
|
||||
"""采集对应点"""
|
||||
|
||||
# 使用标定板(棋盘格)
|
||||
# 1. 在LiDAR点云中检测平面
|
||||
# 2. 在图像中检测棋盘格角点
|
||||
# 3. 建立3D-2D对应关系
|
||||
|
||||
self.correspondences.append({
|
||||
'lidar_3d': lidar_points,
|
||||
'image_2d': image_points,
|
||||
'camera_K': camera_K
|
||||
})
|
||||
|
||||
def calibrate(self):
|
||||
"""优化外参"""
|
||||
|
||||
def reprojection_error(params):
|
||||
"""重投影误差"""
|
||||
# params: [rx, ry, rz, tx, ty, tz]
|
||||
R = self.rodrigues(params[:3])
|
||||
T = params[3:6]
|
||||
|
||||
errors = []
|
||||
for corr in self.correspondences:
|
||||
# 3D点变换
|
||||
points_3d = corr['lidar_3d']
|
||||
points_cam = (R @ points_3d.T).T + T
|
||||
|
||||
# 投影到图像
|
||||
K = corr['camera_K']
|
||||
points_2d_proj = (K @ points_cam.T).T
|
||||
points_2d_proj = points_2d_proj[:, :2] / points_2d_proj[:, 2:]
|
||||
|
||||
# 计算误差
|
||||
error = points_2d_proj - corr['image_2d']
|
||||
errors.append(error.flatten())
|
||||
|
||||
return np.concatenate(errors)
|
||||
|
||||
# 初始猜测
|
||||
x0 = np.zeros(6)
|
||||
|
||||
# 优化
|
||||
result = least_squares(reprojection_error
|
||||
@@ -0,0 +1,977 @@
|
||||
# 摄像头方案对应的GitHub开源项目
|
||||
|
||||
## 📋 研究概述
|
||||
|
||||
本文档整理了与各类摄像头方案对应的GitHub成熟开源项目,提供完整的软件工具链支持。
|
||||
|
||||
**研究范围**:GitHub Stars > 500的活跃项目
|
||||
**更新时间**:2026-05-16
|
||||
|
||||
---
|
||||
|
||||
## 一、单目相机开源项目
|
||||
|
||||
### 1.1 COLMAP ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/colmap/colmap
|
||||
**Stars**: ~7,000
|
||||
**语言**: C++
|
||||
**许可证**: BSD-3-Clause
|
||||
|
||||
#### 项目简介
|
||||
|
||||
COLMAP是最成熟的单目SfM(Structure-from-Motion)和MVS(Multi-View Stereo)系统,被学术界和工业界广泛使用。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- 特征提取与匹配
|
||||
- 增量式SfM重建
|
||||
- 稠密MVS重建
|
||||
- 网格生成
|
||||
|
||||
支持相机:
|
||||
- 所有单目相机
|
||||
- 鱼眼镜头
|
||||
- 全景相机
|
||||
|
||||
优势:
|
||||
- 鲁棒性强
|
||||
- 精度高
|
||||
- 文档完善
|
||||
- GUI + CLI
|
||||
|
||||
适用场景:
|
||||
- 照片建模
|
||||
- 文化遗产数字化
|
||||
- 影视特效
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```bash
|
||||
# 完整重建流程
|
||||
# 1. 特征提取
|
||||
colmap feature_extractor \
|
||||
--database_path database.db \
|
||||
--image_path images/ \
|
||||
--ImageReader.camera_model PINHOLE \
|
||||
--ImageReader.single_camera 1
|
||||
|
||||
# 2. 特征匹配
|
||||
colmap exhaustive_matcher \
|
||||
--database_path database.db \
|
||||
--SiftMatching.guided_matching 1
|
||||
|
||||
# 3. 稀疏重建
|
||||
colmap mapper \
|
||||
--database_path database.db \
|
||||
--image_path images/ \
|
||||
--output_path sparse/
|
||||
|
||||
# 4. 图像去畸变
|
||||
colmap image_undistorter \
|
||||
--image_path images/ \
|
||||
--input_path sparse/0 \
|
||||
--output_path dense/ \
|
||||
--output_type COLMAP
|
||||
|
||||
# 5. 稠密重建
|
||||
colmap patch_match_stereo \
|
||||
--workspace_path dense/ \
|
||||
--workspace_format COLMAP \
|
||||
--PatchMatchStereo.geom_consistency true
|
||||
|
||||
# 6. 点云融合
|
||||
colmap stereo_fusion \
|
||||
--workspace_path dense/ \
|
||||
--workspace_format COLMAP \
|
||||
--input_type geometric \
|
||||
--output_path dense/fused.ply
|
||||
|
||||
# 7. Mesh生成
|
||||
colmap poisson_mesher \
|
||||
--input_path dense/fused.ply \
|
||||
--output_path dense/meshed.ply
|
||||
```
|
||||
|
||||
#### Python接口
|
||||
|
||||
```python
|
||||
# pycolmap - Python绑定
|
||||
import pycolmap
|
||||
|
||||
# 运行SfM
|
||||
reconstruction = pycolmap.incremental_mapping(
|
||||
database_path="database.db",
|
||||
image_path="images/",
|
||||
output_path="sparse/"
|
||||
)
|
||||
|
||||
# 访问重建结果
|
||||
for image_id, image in reconstruction.images.items():
|
||||
print(f"Image {image_id}: {image.name}")
|
||||
print(f"Camera pose: {image.cam_from_world}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.2 OpenMVG ⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/openMVG/openMVG
|
||||
**Stars**: ~5,500
|
||||
**语言**: C++
|
||||
**许可证**: MPL-2.0
|
||||
|
||||
#### 项目简介
|
||||
|
||||
OpenMVG(Open Multiple View Geometry)是另一个强大的SfM库,强调模块化和可扩展性。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- 多种SfM算法
|
||||
- 增量式/全局式重建
|
||||
- 相机标定
|
||||
- 特征匹配
|
||||
|
||||
优势:
|
||||
- 模块化设计
|
||||
- 算法多样
|
||||
- 易于扩展
|
||||
- 教学友好
|
||||
|
||||
与COLMAP对比:
|
||||
- 更模块化
|
||||
- 算法选择多
|
||||
- 速度稍慢
|
||||
- 精度相当
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```bash
|
||||
# OpenMVG pipeline
|
||||
# 1. 图像列表
|
||||
openMVG_main_SfMInit_ImageListing \
|
||||
-i images/ \
|
||||
-o matches/ \
|
||||
-d sensor_width_database.txt
|
||||
|
||||
# 2. 特征提取
|
||||
openMVG_main_ComputeFeatures \
|
||||
-i matches/sfm_data.json \
|
||||
-o matches/ \
|
||||
-m SIFT
|
||||
|
||||
# 3. 特征匹配
|
||||
openMVG_main_ComputeMatches \
|
||||
-i matches/sfm_data.json \
|
||||
-o matches/
|
||||
|
||||
# 4. 增量式SfM
|
||||
openMVG_main_IncrementalSfM \
|
||||
-i matches/sfm_data.json \
|
||||
-m matches/ \
|
||||
-o reconstruction/
|
||||
|
||||
# 5. 导出为COLMAP格式
|
||||
openMVG_main_openMVG2COLMAP \
|
||||
-i reconstruction/sfm_data.bin \
|
||||
-o colmap/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 1.3 Meshroom ⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/alicevision/Meshroom
|
||||
**Stars**: ~11,000
|
||||
**语言**: Python/C++
|
||||
**许可证**: MPL-2.0
|
||||
|
||||
#### 项目简介
|
||||
|
||||
Meshroom是基于AliceVision的开源3D重建软件,提供完整的GUI界面,零代码操作。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- 全自动3D重建
|
||||
- 可视化节点编辑器
|
||||
- 实时预览
|
||||
- 纹理映射
|
||||
|
||||
优势:
|
||||
- 完全免费
|
||||
- GUI友好
|
||||
- 质量高
|
||||
- 社区活跃
|
||||
|
||||
适用场景:
|
||||
- 非技术用户
|
||||
- 快速原型
|
||||
- 教学演示
|
||||
- 艺术创作
|
||||
```
|
||||
|
||||
#### 使用方法
|
||||
|
||||
```bash
|
||||
# 1. 下载安装
|
||||
# https://github.com/alicevision/Meshroom/releases
|
||||
|
||||
# 2. 启动GUI
|
||||
./Meshroom
|
||||
|
||||
# 3. 拖拽图片到界面
|
||||
# 4. 点击"Start"自动重建
|
||||
# 5. 导出OBJ/FBX模型
|
||||
|
||||
# 命令行模式
|
||||
meshroom_batch \
|
||||
--input images/ \
|
||||
--output output/ \
|
||||
--save output/project.mg
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、双目相机开源项目
|
||||
|
||||
### 2.1 ORB-SLAM3 ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/UZ-SLAMLab/ORB_SLAM3
|
||||
**Stars**: ~6,000
|
||||
**语言**: C++
|
||||
**许可证**: GPLv3
|
||||
|
||||
#### 项目简介
|
||||
|
||||
ORB-SLAM3是最先进的视觉SLAM系统,支持单目、双目、RGB-D和IMU融合。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- 实时SLAM
|
||||
- 回环检测
|
||||
- 重定位
|
||||
- 地图保存/加载
|
||||
- 多地图管理
|
||||
|
||||
支持传感器:
|
||||
- 单目相机
|
||||
- 双目相机
|
||||
- RGB-D相机
|
||||
- 单目+IMU
|
||||
- 双目+IMU
|
||||
|
||||
优势:
|
||||
- 精度最高
|
||||
- 鲁棒性强
|
||||
- 实时性好
|
||||
- 学术标准
|
||||
|
||||
适用场景:
|
||||
- 机器人导航
|
||||
- AR/VR
|
||||
- 自动驾驶
|
||||
- 无人机
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```bash
|
||||
# 编译
|
||||
cd ORB_SLAM3
|
||||
chmod +x build.sh
|
||||
./build.sh
|
||||
|
||||
# 双目相机运行
|
||||
./Examples/Stereo/stereo_euroc \
|
||||
Vocabulary/ORBvoc.txt \
|
||||
Examples/Stereo/EuRoC.yaml \
|
||||
dataset/MH01 \
|
||||
Examples/Stereo/EuRoC_TimeStamps/MH01.txt \
|
||||
dataset-MH01_stereo
|
||||
|
||||
# 双目+IMU运行
|
||||
./Examples/Stereo-Inertial/stereo_inertial_euroc \
|
||||
Vocabulary/ORBvoc.txt \
|
||||
Examples/Stereo-Inertial/EuRoC.yaml \
|
||||
dataset/MH01 \
|
||||
Examples/Stereo-Inertial/EuRoC_TimeStamps/MH01.txt \
|
||||
dataset-MH01_stereoi
|
||||
```
|
||||
|
||||
#### Python绑定
|
||||
|
||||
```python
|
||||
# 使用orbslam3_python
|
||||
import orbslam3
|
||||
|
||||
# 初始化
|
||||
slam = orbslam3.System(
|
||||
vocab_file="Vocabulary/ORBvoc.txt",
|
||||
settings_file="Examples/Stereo/EuRoC.yaml",
|
||||
sensor_type=orbslam3.Sensor.STEREO
|
||||
)
|
||||
|
||||
# 处理帧
|
||||
for left_img, right_img, timestamp in stereo_stream:
|
||||
pose = slam.process_image_stereo(
|
||||
left_img, right_img, timestamp
|
||||
)
|
||||
|
||||
if pose is not None:
|
||||
print(f"Camera pose: {pose}")
|
||||
|
||||
# 保存地图
|
||||
slam.save_map("map.bin")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 OpenCV Stereo ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/opencv/opencv
|
||||
**Stars**: ~77,000
|
||||
**语言**: C++/Python
|
||||
**许可证**: Apache 2.0
|
||||
|
||||
#### 项目简介
|
||||
|
||||
OpenCV提供了完整的双目视觉工具链,从标定到深度计算。
|
||||
|
||||
```yaml
|
||||
核心模块:
|
||||
- calib3d: 相机标定
|
||||
- stereo: 立体匹配
|
||||
- 3d: 点云处理
|
||||
|
||||
算法支持:
|
||||
- StereoBM: 块匹配
|
||||
- StereoSGBM: 半全局匹配
|
||||
- StereoBeliefPropagation: 置信传播
|
||||
- StereoConstantSpaceBP: 恒定空间BP
|
||||
|
||||
优势:
|
||||
- 文档完善
|
||||
- 社区庞大
|
||||
- 跨平台
|
||||
- 性能优化
|
||||
```
|
||||
|
||||
#### 完整示例
|
||||
|
||||
```python
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
class StereoVision:
|
||||
"""双目视觉系统"""
|
||||
|
||||
def __init__(self, calib_file):
|
||||
# 加载标定参数
|
||||
calib = np.load(calib_file)
|
||||
self.K_left = calib['K_left']
|
||||
self.dist_left = calib['dist_left']
|
||||
self.K_right = calib['K_right']
|
||||
self.dist_right = calib['dist_right']
|
||||
self.R = calib['R']
|
||||
self.T = calib['T']
|
||||
|
||||
# 计算校正映射
|
||||
self.R_left, self.R_right, self.P_left, self.P_right, self.Q, \
|
||||
self.roi_left, self.roi_right = cv2.stereoRectify(
|
||||
self.K_left, self.dist_left,
|
||||
self.K_right, self.dist_right,
|
||||
(1280, 720), self.R, self.T,
|
||||
alpha=0
|
||||
)
|
||||
|
||||
self.map_left_x, self.map_left_y = cv2.initUndistortRectifyMap(
|
||||
self.K_left, self.dist_left, self.R_left,
|
||||
self.P_left, (1280, 720), cv2.CV_32FC1
|
||||
)
|
||||
|
||||
self.map_right_x, self.map_right_y = cv2.initUndistortRectifyMap(
|
||||
self.K_right, self.dist_right, self.R_right,
|
||||
self.P_right, (1280, 720), cv2.CV_32FC1
|
||||
)
|
||||
|
||||
# 创建立体匹配器
|
||||
self.stereo = cv2.StereoSGBM_create(
|
||||
minDisparity=0,
|
||||
numDisparities=128,
|
||||
blockSize=5,
|
||||
P1=8 * 3 * 5**2,
|
||||
P2=32 * 3 * 5**2,
|
||||
disp12MaxDiff=1,
|
||||
uniquenessRatio=10,
|
||||
speckleWindowSize=100,
|
||||
speckleRange=32,
|
||||
mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY
|
||||
)
|
||||
|
||||
def compute_depth(self, left_img, right_img):
|
||||
"""计算深度图"""
|
||||
# 校正
|
||||
left_rect = cv2.remap(
|
||||
left_img, self.map_left_x, self.map_left_y,
|
||||
cv2.INTER_LINEAR
|
||||
)
|
||||
right_rect = cv2.remap(
|
||||
right_img, self.map_right_x, self.map_right_y,
|
||||
cv2.INTER_LINEAR
|
||||
)
|
||||
|
||||
# 立体匹配
|
||||
disparity = self.stereo.compute(
|
||||
left_rect, right_rect
|
||||
).astype(np.float32) / 16.0
|
||||
|
||||
# 视差转深度
|
||||
depth = cv2.reprojectImageTo3D(disparity, self.Q)
|
||||
|
||||
return depth, disparity
|
||||
|
||||
def get_pointcloud(self, left_img, right_img):
|
||||
"""生成点云"""
|
||||
depth, disparity = self.compute_depth(left_img, right_img)
|
||||
|
||||
# 过滤无效点
|
||||
mask = (disparity > 0) & (disparity < 128)
|
||||
|
||||
points = depth[mask]
|
||||
colors = left_img[mask] / 255.0
|
||||
|
||||
return points, colors
|
||||
|
||||
# 使用
|
||||
stereo = StereoVision('stereo_calib.npz')
|
||||
depth, disparity = stereo.compute_depth(left_img, right_img)
|
||||
points, colors = stereo.get_pointcloud(left_img, right_img)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 libelas ⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/jlowenz/libelas
|
||||
**Stars**: ~300
|
||||
**语言**: C++
|
||||
**许可证**: GPLv3
|
||||
|
||||
#### 项目简介
|
||||
|
||||
ELAS(Efficient Large-Scale Stereo)是一个高效的双目立体匹配库。
|
||||
|
||||
```yaml
|
||||
核心特点:
|
||||
- 速度快
|
||||
- 精度高
|
||||
- 内存效率高
|
||||
- 适合大图像
|
||||
|
||||
优势:
|
||||
- 实时性能
|
||||
- 边缘保持
|
||||
- 鲁棒性好
|
||||
|
||||
适用场景:
|
||||
- 自动驾驶
|
||||
- 机器人
|
||||
- 实时应用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、深度相机(RGB-D)开源项目
|
||||
|
||||
### 3.1 Azure Kinect SDK ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/microsoft/Azure-Kinect-Sensor-SDK
|
||||
**Stars**: ~1,500
|
||||
**语言**: C/C++
|
||||
**许可证**: MIT
|
||||
|
||||
#### 项目简介
|
||||
|
||||
Microsoft官方的Azure Kinect开发套件,提供完整的硬件访问接口。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- RGB相机访问
|
||||
- 深度相机访问
|
||||
- IMU数据读取
|
||||
- 多机同步
|
||||
- 骨骼追踪
|
||||
|
||||
支持平台:
|
||||
- Windows
|
||||
- Linux
|
||||
- ROS
|
||||
|
||||
优势:
|
||||
- 官方支持
|
||||
- 文档完善
|
||||
- 性能优化
|
||||
- 示例丰富
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```c
|
||||
// C API
|
||||
#include <k4a/k4a.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
// 打开设备
|
||||
k4a_device_t device = NULL;
|
||||
k4a_device_open(0, &device);
|
||||
|
||||
// 配置
|
||||
k4a_device_configuration_t config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
|
||||
config.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
|
||||
config.color_resolution = K4A_COLOR_RESOLUTION_1080P;
|
||||
config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED;
|
||||
config.camera_fps = K4A_FRAMES_PER_SECOND_30;
|
||||
|
||||
// 启动相机
|
||||
k4a_device_start_cameras(device, &config);
|
||||
|
||||
// 采集帧
|
||||
k4a_capture_t capture = NULL;
|
||||
k4a_device_get_capture(device, &capture, K4A_WAIT_INFINITE);
|
||||
|
||||
// 获取图像
|
||||
k4a_image_t color_image = k4a_capture_get_color_image(capture);
|
||||
k4a_image_t depth_image = k4a_capture_get_depth_image(capture);
|
||||
|
||||
// 处理...
|
||||
|
||||
// 释放
|
||||
k4a_image_release(color_image);
|
||||
k4a_image_release(depth_image);
|
||||
k4a_capture_release(capture);
|
||||
k4a_device_stop_cameras(device);
|
||||
k4a_device_close(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
#### Python绑定
|
||||
|
||||
```python
|
||||
# pyk4a - Python包装
|
||||
from pyk4a import PyK4A, Config
|
||||
|
||||
# 配置
|
||||
config = Config(
|
||||
color_resolution=PyK4A.ColorResolution.RES_1080P,
|
||||
depth_mode=PyK4A.DepthMode.NFOV_UNBINNED,
|
||||
camera_fps=PyK4A.FPS.FPS_30,
|
||||
synchronized_images_only=True
|
||||
)
|
||||
|
||||
# 启动
|
||||
k4a = PyK4A(config=config)
|
||||
k4a.start()
|
||||
|
||||
# 采集
|
||||
while True:
|
||||
capture = k4a.get_capture()
|
||||
|
||||
if capture.color is not None and capture.depth is not None:
|
||||
rgb = capture.color
|
||||
depth = capture.depth
|
||||
|
||||
# 处理RGB和深度
|
||||
process_frame(rgb, depth)
|
||||
|
||||
k4a.stop()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.2 librealsense ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/IntelRealSense/librealsense
|
||||
**Stars**: ~7,500
|
||||
**语言**: C++/Python
|
||||
**许可证**: Apache 2.0
|
||||
|
||||
#### 项目简介
|
||||
|
||||
Intel RealSense官方SDK,支持全系列RealSense相机。
|
||||
|
||||
```yaml
|
||||
支持设备:
|
||||
- D400系列(结构光)
|
||||
- D500系列(结构光)
|
||||
- L500系列(LiDAR)
|
||||
- T200系列(追踪)
|
||||
|
||||
核心功能:
|
||||
- 深度流
|
||||
- RGB流
|
||||
- IMU数据
|
||||
- 点云生成
|
||||
- 后处理滤波
|
||||
|
||||
优势:
|
||||
- 跨平台
|
||||
- Python/C++/C#
|
||||
- ROS集成
|
||||
- 实时性能
|
||||
```
|
||||
|
||||
#### Python示例
|
||||
|
||||
```python
|
||||
import pyrealsense2 as rs
|
||||
import numpy as np
|
||||
|
||||
class RealSenseCamera:
|
||||
"""RealSense相机封装"""
|
||||
|
||||
def __init__(self):
|
||||
# 创建pipeline
|
||||
self.pipeline = rs.pipeline()
|
||||
self.config = rs.config()
|
||||
|
||||
# 配置流
|
||||
self.config.enable_stream(
|
||||
rs.stream.depth, 640, 480, rs.format.z16, 30
|
||||
)
|
||||
self.config.enable_stream(
|
||||
rs.stream.color, 1920, 1080, rs.format.bgr8, 30
|
||||
)
|
||||
|
||||
# 启动
|
||||
self.profile = self.pipeline.start(self.config)
|
||||
|
||||
# 获取内参
|
||||
depth_stream = self.profile.get_stream(rs.stream.depth)
|
||||
self.intrinsics = depth_stream.as_video_stream_profile().get_intrinsics()
|
||||
|
||||
# 创建对齐对象
|
||||
self.align = rs.align(rs.stream.color)
|
||||
|
||||
# 后处理滤波器
|
||||
self.decimation = rs.decimation_filter()
|
||||
self.spatial = rs.spatial_filter()
|
||||
self.temporal = rs.temporal_filter()
|
||||
self.hole_filling = rs.hole_filling_filter()
|
||||
|
||||
def get_frames(self):
|
||||
"""获取对齐的RGB-D帧"""
|
||||
# 等待帧
|
||||
frames = self.pipeline.wait_for_frames()
|
||||
|
||||
# 对齐到RGB
|
||||
aligned_frames = self.align.process(frames)
|
||||
|
||||
# 获取帧
|
||||
depth_frame = aligned_frames.get_depth_frame()
|
||||
color_frame = aligned_frames.get_color_frame()
|
||||
|
||||
if not depth_frame or not color_frame:
|
||||
return None, None
|
||||
|
||||
# 深度后处理
|
||||
depth_frame = self.decimation.process(depth_frame)
|
||||
depth_frame = self.spatial.process(depth_frame)
|
||||
depth_frame = self.temporal.process(depth_frame)
|
||||
depth_frame = self.hole_filling.process(depth_frame)
|
||||
|
||||
# 转换为numpy
|
||||
depth_image = np.asanyarray(depth_frame.get_data())
|
||||
color_image = np.asanyarray(color_frame.get_data())
|
||||
|
||||
return color_image, depth_image
|
||||
|
||||
def get_pointcloud(self):
|
||||
"""生成点云"""
|
||||
frames = self.pipeline.wait_for_frames()
|
||||
aligned_frames = self.align.process(frames)
|
||||
|
||||
depth_frame = aligned_frames.get_depth_frame()
|
||||
color_frame = aligned_frames.get_color_frame()
|
||||
|
||||
# 创建点云
|
||||
pc = rs.pointcloud()
|
||||
pc.map_to(color_frame)
|
||||
points = pc.calculate(depth_frame)
|
||||
|
||||
# 导出
|
||||
vertices = np.asanyarray(points.get_vertices())
|
||||
texcoords = np.asanyarray(points.get_texture_coordinates())
|
||||
|
||||
return vertices, texcoords
|
||||
|
||||
def stop(self):
|
||||
self.pipeline.stop()
|
||||
|
||||
# 使用
|
||||
camera = RealSenseCamera()
|
||||
|
||||
while True:
|
||||
rgb, depth = camera.get_frames()
|
||||
if rgb is not None:
|
||||
# 处理
|
||||
pass
|
||||
|
||||
camera.stop()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Open3D ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/isl-org/Open3D
|
||||
**Stars**: ~11,000
|
||||
**语言**: C++/Python
|
||||
**许可证**: MIT
|
||||
|
||||
#### 项目简介
|
||||
|
||||
Open3D是一个现代化的3D数据处理库,完美支持RGB-D数据。
|
||||
|
||||
```yaml
|
||||
核心功能:
|
||||
- 点云处理
|
||||
- 网格处理
|
||||
- RGB-D集成
|
||||
- SLAM
|
||||
- 可视化
|
||||
|
||||
支持设备:
|
||||
- Azure Kinect
|
||||
- RealSense
|
||||
- 通用RGB-D
|
||||
|
||||
优势:
|
||||
- API简洁
|
||||
- 性能优秀
|
||||
- 文档完善
|
||||
- 可视化强大
|
||||
```
|
||||
|
||||
#### RGB-D SLAM示例
|
||||
|
||||
```python
|
||||
import open3d as o3d
|
||||
import numpy as np
|
||||
|
||||
class RGBD_SLAM:
|
||||
"""基于Open3D的RGB-D SLAM"""
|
||||
|
||||
def __init__(self, intrinsics):
|
||||
self.intrinsics = o3d.camera.PinholeCameraIntrinsic(
|
||||
width=intrinsics['width'],
|
||||
height=intrinsics['height'],
|
||||
fx=intrinsics['fx'],
|
||||
fy=intrinsics['fy'],
|
||||
cx=intrinsics['cx'],
|
||||
cy=intrinsics['cy']
|
||||
)
|
||||
|
||||
self.volume = o3d.pipelines.integration.ScalableTSDFVolume(
|
||||
voxel_length=0.01,
|
||||
sdf_trunc=0.04,
|
||||
color_type=o3d.pipelines.integration.TSDFVolumeColorType.RGB8
|
||||
)
|
||||
|
||||
self.poses = []
|
||||
self.current_pose = np.eye(4)
|
||||
|
||||
def process_frame(self, rgb, depth):
|
||||
"""处理RGB-D帧"""
|
||||
# 创建RGB-D图像
|
||||
rgbd = o3d.geometry.RGBDImage.create_from_color_and_depth(
|
||||
o3d.geometry.Image(rgb),
|
||||
o3d.geometry.Image(depth),
|
||||
depth_scale=1000.0,
|
||||
depth_trunc=3.0,
|
||||
convert_rgb_to_intensity=False
|
||||
)
|
||||
|
||||
# 如果是第一帧
|
||||
if len(self.poses) == 0:
|
||||
self.poses.append(self.current_pose)
|
||||
self.volume.integrate(
|
||||
rgbd, self.intrinsics, np.linalg.inv(self.current_pose)
|
||||
)
|
||||
return self.current_pose
|
||||
|
||||
# 里程计估计
|
||||
option = o3d.pipelines.odometry.OdometryOption()
|
||||
odo_init = np.eye(4)
|
||||
|
||||
[success, trans, info] = o3d.pipelines.odometry.compute_rgbd_odometry(
|
||||
rgbd, self.prev_rgbd,
|
||||
self.intrinsics, odo_init,
|
||||
o3d.pipelines.odometry.RGBDOdometryJacobianFromHybridTerm(),
|
||||
option
|
||||
)
|
||||
|
||||
if success:
|
||||
# 更新位姿
|
||||
self.current_pose = self.current_pose @ trans
|
||||
self.poses.append(self.current_pose.copy())
|
||||
|
||||
# 集成到TSDF
|
||||
self.volume.integrate(
|
||||
rgbd, self.intrinsics, np.linalg.inv(self.current_pose)
|
||||
)
|
||||
|
||||
self.prev_rgbd = rgbd
|
||||
return self.current_pose
|
||||
|
||||
def extract_mesh(self):
|
||||
"""提取网格"""
|
||||
mesh = self.volume.extract_triangle_mesh()
|
||||
mesh.compute_vertex_normals()
|
||||
return mesh
|
||||
|
||||
def get_pointcloud(self):
|
||||
"""提取点云"""
|
||||
pcd = self.volume.extract_point_cloud()
|
||||
return pcd
|
||||
|
||||
# 使用
|
||||
slam = RGBD_SLAM({
|
||||
'width': 1920,
|
||||
'height': 1080,
|
||||
'fx': 1066.778,
|
||||
'fy': 1067.487,
|
||||
'cx': 960.0,
|
||||
'cy': 540.0
|
||||
})
|
||||
|
||||
for rgb, depth in rgbd_stream:
|
||||
pose = slam.process_frame(rgb, depth)
|
||||
print(f"Current pose: {pose}")
|
||||
|
||||
# 提取最终模型
|
||||
mesh = slam.extract_mesh()
|
||||
o3d.io.write_triangle_mesh("output.ply", mesh)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、LiDAR开源项目
|
||||
|
||||
### 4.1 FAST-LIO2 ⭐⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/hku-mars/FAST_LIO
|
||||
**Stars**: ~2,500
|
||||
**语言**: C++
|
||||
**许可证**: GPLv2
|
||||
|
||||
#### 项目简介
|
||||
|
||||
FAST-LIO2是最先进的LiDAR-惯性里程计,支持固态和机械式LiDAR。
|
||||
|
||||
```yaml
|
||||
核心特点:
|
||||
- 实时性能
|
||||
- 高精度
|
||||
- 鲁棒性强
|
||||
- 支持多种LiDAR
|
||||
|
||||
支持设备:
|
||||
- Livox系列
|
||||
- Velodyne
|
||||
- Ouster
|
||||
- Hesai
|
||||
|
||||
优势:
|
||||
- 速度快
|
||||
- 精度高
|
||||
- 抗退化
|
||||
- 开源免费
|
||||
```
|
||||
|
||||
#### 使用示例
|
||||
|
||||
```bash
|
||||
# 编译
|
||||
cd FAST_LIO
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make
|
||||
|
||||
# 运行(Livox Mid-360)
|
||||
roslaunch fast_lio mapping_mid360.launch
|
||||
|
||||
# 保存地图
|
||||
rosservice call /map_save "resolution: 0.01
|
||||
destination: '/home/user/map.pcd'"
|
||||
```
|
||||
|
||||
#### 配置文件
|
||||
|
||||
```yaml
|
||||
# config/mid360.yaml
|
||||
common:
|
||||
lid_topic: "/livox/lidar"
|
||||
imu_topic: "/livox/imu"
|
||||
time_sync_en: false
|
||||
|
||||
preprocess:
|
||||
lidar_type: 1 # 1: Livox
|
||||
scan_line: 6
|
||||
blind: 0.5
|
||||
|
||||
mapping:
|
||||
acc_cov: 0.1
|
||||
gyr_cov: 0.1
|
||||
b_acc_cov: 0.0001
|
||||
b_gyr_cov: 0.0001
|
||||
det_range: 100.0
|
||||
|
||||
publish:
|
||||
path_en: true
|
||||
scan_publish_en: true
|
||||
dense_publish_en: true
|
||||
scan_bodyframe_pub_en: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2 LIO-SAM ⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/TixiaoShan/LIO-SAM
|
||||
**Stars**: ~3,000
|
||||
**语言**: C++
|
||||
**许可证**: BSD-3-Clause
|
||||
|
||||
#### 项目简介
|
||||
|
||||
LIO-SAM是一个紧耦合的LiDAR-惯性-视觉SLAM框架。
|
||||
|
||||
```yaml
|
||||
核心特点:
|
||||
- 因子图优化
|
||||
- 回环检测
|
||||
- 全局一致性
|
||||
- 多传感器融合
|
||||
|
||||
支持传感器:
|
||||
- LiDAR
|
||||
- IMU
|
||||
- GPS(可选)
|
||||
- 相机(可选)
|
||||
|
||||
优势:
|
||||
- 精度高
|
||||
- 全局优化
|
||||
- 长时稳定
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.3 Livox SDK ⭐⭐⭐⭐
|
||||
|
||||
**GitHub**: https://github.com/Livox-SDK/Livox-
|
||||
@@ -0,0 +1,448 @@
|
||||
# ZED 2i 国产化替代方案对照(China Alternatives)
|
||||
|
||||
> 面向"双目立体 + IMU + RGB-D + SDK"的整体替代选型。覆盖**硬件对标、软件生态、迁移成本、采购与合规**四个维度,服务于在国产化要求、供应链稳定性、成本压缩三类场景下替换 Stereolabs ZED 2i。
|
||||
>
|
||||
> 配套:[`zed2i_stereo_imu_solution.md`](zed2i_stereo_imu_solution.md)(原方案细节)/ [`zed2i_iterative_framework.md`](zed2i_iterative_framework.md)(迭代框架)
|
||||
|
||||
---
|
||||
|
||||
## 0. 关键结论速览
|
||||
|
||||
| 替代档位 | 推荐产品 | 价格 | 与 ZED 2i 差距 | 何时选它 |
|
||||
|---|---|---|---|---|
|
||||
| **① 一比一对标(双目+IMU+SDK)** | **奥比中光 Gemini 2 / Gemini 335L** | ¥2,500–¥4,500 | 基本持平,深度算法略弱 | 需要"开箱即用 + 国产票据 + 中文支持" |
|
||||
| **② 性价比最高(结构光/iToF RGB-D)** | **奥比中光 Astra 2 / 乐视 Femto Mega** | ¥1,200–¥2,800 | 牺牲户外能力,室内精度更高 | 室内为主、预算敏感 |
|
||||
| **③ 工业级双目(高动态/远距)** | **图漾 PERCIPIO FM/FS 系列** | ¥4,000–¥12,000 | 户外/远距优于 ZED | 工业、机器人、户外 |
|
||||
| **④ 高端机器人/具身智能** | **大疆 Livox Mid-360 + 海康双目** 或 **小觅 MYNT EYE D 系列** | ¥3,000–¥10,000 | LiDAR 路线,互补非对标 | 大场景 SLAM、L4 自动驾驶 |
|
||||
| **⑤ 极致低成本(DIY 双目)** | **海康/大华 工业相机×2 + Bosch BMI088** | ¥1,500–¥3,000 | 需自研标定/算法栈 | 科研、教学、定制 |
|
||||
|
||||
**一句话决策**:
|
||||
- 要**最少改动迁移 ZED 2i 代码** → 奥比中光 Gemini 335L(双目+IMU+ROS)
|
||||
- 要**最高性价比室内** → 奥比中光 Astra 2 或 乐鑫 Femto Mega
|
||||
- 要**工业耐用 + 户外** → 图漾 FM851-GI-E1
|
||||
|
||||
---
|
||||
|
||||
## 1. ZED 2i 技术对标基线
|
||||
|
||||
为了客观对比,把 ZED 2i 抽象成 6 项核心能力指标:
|
||||
|
||||
| 能力维度 | ZED 2i 指标 |
|
||||
|---|---|
|
||||
| C1 双目立体(被动) | 2.2K@15 / 1080p@30 / 720p@60,120mm 基线,全局快门 |
|
||||
| C2 深度有效范围 | 0.3 – 20 m |
|
||||
| C3 深度精度 | ±1–2% @ 1–3m |
|
||||
| C4 IMU | 6 轴 400 Hz,硬件时间同步 |
|
||||
| C5 SDK 生态 | C++/Python/ROS1/2/Unity/UE/Jetson,自带 VIO + Spatial Mapping + OD |
|
||||
| C6 接口/功耗 | USB 3.0 Type-C,3.5W,IP44 |
|
||||
|
||||
下面所有国产替代将围绕这 6 项打分(满分 5 ⭐)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 主流国产厂商全景
|
||||
|
||||
### 2.1 厂商定位地图
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph 消费/室内级
|
||||
OB[奥比中光 Orbbec]
|
||||
LS[乐视/Femto 系列]
|
||||
XS[小觅 MYNT EYE]
|
||||
end
|
||||
subgraph 工业级
|
||||
TY[图漾 Percipio]
|
||||
HK[海康机器人 Hikrobot]
|
||||
DH[大华 Dahua]
|
||||
end
|
||||
subgraph 机器人/具身
|
||||
LV[大疆览沃 Livox]
|
||||
DJ[大疆 RoboMaster Tello]
|
||||
UR[宇树 Unitree DepthCam]
|
||||
end
|
||||
subgraph 模组级
|
||||
GW[格灵深瞳]
|
||||
SU[速腾聚创 RoboSense]
|
||||
end
|
||||
```
|
||||
|
||||
### 2.2 厂商核心对比
|
||||
|
||||
| 厂商 | 主力产品线 | 技术路线 | 出货量级 | SDK 成熟度 | 国产化属性 |
|
||||
|---|---|---|---|---|---|
|
||||
| **奥比中光 Orbbec** | Astra / Gemini / Femto | 结构光 + 双目 + iToF | 千万级(科大讯飞/微软 Azure Kinect 接盘方) | ⭐⭐⭐⭐⭐ | A 股科创板上市,纯国产 |
|
||||
| **图漾科技 Percipio** | FM/FS/PS 系列 | 双目 + 散斑主动投射 | 工业百万级 | ⭐⭐⭐⭐ | 上海,纯国产 |
|
||||
| **小觅智能 MYNT** | MYNT EYE S/D | 双目 + IMU | 十万级(创业团队) | ⭐⭐⭐⭐ | 北京,纯国产 |
|
||||
| **海康机器人** | MV-DB 系列 | 工业双目 | 工业头部 | ⭐⭐⭐ | 海康威视子公司 |
|
||||
| **大疆 Livox** | Mid-360/Avia | LiDAR(非双目,互补) | 万级 | ⭐⭐⭐⭐ | 深圳大疆 |
|
||||
| **乐视 Femto / 微视** | Femto Mega/Bolt | iToF(Azure Kinect 同源) | 万级 | ⭐⭐⭐⭐ | 微软授权 + 国产代工 |
|
||||
| **宇树 Unitree** | DepthCam | 双目 + IMU(机器人配件) | 跟随机器狗出货 | ⭐⭐⭐ | 杭州,机器人头部 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 重点替代产品深度评测
|
||||
|
||||
### 3.1 奥比中光 Gemini 335 / 335L(**首推一比一替代**)
|
||||
|
||||
```yaml
|
||||
产品定位: 双目结构光 + 主动 IR 投射 + 内置 6 轴 IMU
|
||||
价格:
|
||||
Gemini 335: ¥2,499
|
||||
Gemini 335L: ¥3,299(带长基线)
|
||||
传感器:
|
||||
双目: 2× 1MP 全局快门,基线 95mm
|
||||
深度: 1280×800 @30fps(IR 主动散斑辅助)
|
||||
RGB: 1920×1080 @30fps
|
||||
IMU: BMI088 6 轴 @200Hz(部分批次 400Hz)
|
||||
深度:
|
||||
范围: 0.25 – 10 m
|
||||
精度: ±1% @ 1m, ±2% @ 3m
|
||||
模式: 结构光 + 立体匹配混合
|
||||
SDK:
|
||||
- Orbbec SDK v2(C++/Python)
|
||||
- ROS / ROS 2 wrapper
|
||||
- Jetson 全系支持
|
||||
- 提供 OrbbecViewer 类似 ZED Explorer
|
||||
功耗/接口: USB 3.0,4W
|
||||
```
|
||||
|
||||
**对标打分**:
|
||||
|
||||
| 能力 | ZED 2i | Gemini 335L | 说明 |
|
||||
|---|---|---|---|
|
||||
| C1 双目分辨率/帧率 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 1MP vs 2.1MP,但有主动 IR 补强 |
|
||||
| C2 有效范围 | ⭐⭐⭐⭐⭐ 0.3–20m | ⭐⭐⭐ 0.25–10m | 远距弱,室内足够 |
|
||||
| C3 深度精度 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 近距甚至更优(IR 投射) |
|
||||
| C4 IMU | ⭐⭐⭐⭐⭐ 400Hz | ⭐⭐⭐⭐ 200Hz | 频率略低 |
|
||||
| C5 SDK/生态 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 自带 VIO 弱于 ZED,需外接 ORB-SLAM3 |
|
||||
| C6 接口/功耗 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 类似 |
|
||||
|
||||
**适用本项目**:✅ 推荐为 ZED 2i 主力替代品;M1–M2 几乎可零改动迁移;M3 阶段需要把"ZED 内建 VIO"换成"Gemini 数据 + ORB-SLAM3/VINS-Fusion"。
|
||||
|
||||
---
|
||||
|
||||
### 3.2 奥比中光 Astra 2 / Astra Pro Plus(**性价比首选**)
|
||||
|
||||
```yaml
|
||||
产品定位: 单目 RGB + 结构光深度(非双目,但功能等价 RGB-D)
|
||||
价格:
|
||||
Astra 2: ¥1,299
|
||||
Astra Pro Plus: ¥1,899
|
||||
深度:
|
||||
范围: 0.6 – 8 m
|
||||
精度: ±1% @ 1m
|
||||
分辨率: 640×400 @30fps
|
||||
RGB: 1920×1080
|
||||
IMU: ❌(需外接,劣势)
|
||||
SDK: Orbbec SDK,Azure Kinect 兼容层(重要!)
|
||||
```
|
||||
|
||||
**优势**:硬件成本低;**官方提供 Azure Kinect SDK 兼容接口**,意味着大量基于 Kinect 的开源代码(如 KinectFusion、Open3D RGB-D 流水线)可直接复用。
|
||||
|
||||
**劣势**:无 IMU,不适合机器人 VIO 场景,定位需依赖外接 IMU 或纯视觉。
|
||||
|
||||
**适用本项目**:室内静态扫描子任务(M2-2/M2-3)非常合适;需要时序运动建模时不如 Gemini 335L。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 乐视/微视 Femto Mega(**Azure Kinect 国产平替**)
|
||||
|
||||
```yaml
|
||||
产品定位: iToF + RGB + 6DoF IMU(与微软联合开发,国产代工)
|
||||
价格: ¥2,799
|
||||
深度:
|
||||
范围: 0.25 – 5.46 m
|
||||
精度: ±11 mm(NFOV)
|
||||
分辨率: 640×576 @30fps
|
||||
RGB: 4K@30fps
|
||||
IMU: 6 轴 1.6kHz(行业最高)
|
||||
SDK: 微软 Azure Kinect SDK 完全兼容
|
||||
特色: 内置 NVIDIA Jetson Nano,可独立部署
|
||||
```
|
||||
|
||||
**优势**:与微软 Azure Kinect DK 100% 兼容,无缝继承所有 Kinect 生态(Body Tracking、Spatial Audio、Open3D 等);IMU 频率秒杀 ZED。
|
||||
|
||||
**劣势**:iToF 路线对**强光**敏感(户外受限);最大距离仅 5.46m。
|
||||
|
||||
**适用本项目**:作为 ZED 2i 在**室内客房精细扫描**场景下的**升级**而非"平替"——若不需要户外/长距,Femto Mega 综合体验**优于** ZED 2i。
|
||||
|
||||
---
|
||||
|
||||
### 3.4 小觅 MYNT EYE D-1000-IR-120(**双目+IMU 老牌**)
|
||||
|
||||
```yaml
|
||||
产品定位: 国内最早做 VIO 双目 IMU 一体机的团队
|
||||
价格: ¥2,999–¥4,999
|
||||
传感器:
|
||||
双目: 1280×720 @60fps,基线 120mm(与 ZED 2i 完全一致!)
|
||||
IMU: 6 轴 200Hz(早期版本 100Hz)
|
||||
IR 主动: 部分型号支持
|
||||
SDK:
|
||||
- C++ / Python / ROS / ROS 2
|
||||
- 提供 ORB-SLAM2 / VINS-Mono / OKVIS 适配 demo
|
||||
- 标定工具链开源
|
||||
```
|
||||
|
||||
**优势**:基线与 ZED 2i **完全一致**(120mm),物理迁移最容易;ROS 生态成熟;为学术圈 SLAM 研究的常用平台。
|
||||
|
||||
**劣势**:分辨率低于 ZED 2i;公司近年增速放缓,售后响应一般。
|
||||
|
||||
**适用本项目**:学术研究、SLAM 算法迭代(M3-3);想要"开源 + 可控"路线时优先考虑。
|
||||
|
||||
---
|
||||
|
||||
### 3.5 图漾科技 PERCIPIO FM851-GI-E1(**工业级最强**)
|
||||
|
||||
```yaml
|
||||
产品定位: 工业双目 + 散斑投射,IP67
|
||||
价格: ¥7,500–¥12,000
|
||||
深度:
|
||||
范围: 0.5 – 6 m(短焦) / 1 – 15 m(长焦可换)
|
||||
精度: ±0.3% @ 1m(强于 ZED)
|
||||
分辨率: 1280×960 @30fps
|
||||
IMU: ❌ 标配无,可选外接型号
|
||||
接口: GigE / USB 3.0,工业 M12 连接器
|
||||
SDK: Percipio Camport,C++/Python
|
||||
```
|
||||
|
||||
**优势**:工业品级别耐用度、户外强光下仍稳定;远距精度优于 ZED;GigE 接口适合长距离布线。
|
||||
|
||||
**劣势**:贵;标配无 IMU;SDK 没有像 ZED 那样的高层 Spatial Mapping/OD 模块,需要自己接 SLAM 后端。
|
||||
|
||||
**适用本项目**:酒店**公区/室外**采集(大堂挑高、走廊远端、入口)的子任务;与 Gemini 335L 形成"室内+公区"组合。
|
||||
|
||||
---
|
||||
|
||||
### 3.6 海康机器人 MV-DB2000(**性价比工业**)
|
||||
|
||||
```yaml
|
||||
价格: ¥3,500
|
||||
分辨率: 1920×1200 @30fps,基线 100mm
|
||||
深度精度: ±2% @ 2m
|
||||
IMU: ❌
|
||||
SDK: HikRobot SDK + ROS
|
||||
```
|
||||
|
||||
**适用本项目**:备选,国产化采购通道顺畅(央国企/银行项目友好),但生态封闭,二次开发空间小。
|
||||
|
||||
---
|
||||
|
||||
## 4. 全场景对照决策表
|
||||
|
||||
| 场景 | ZED 2i 配置 | 推荐国产替代 | 改动量 | 价格差 |
|
||||
|---|---|---|---|---|
|
||||
| 室内客房快速扫描 | ZED 2i + Spatial Mapping | **Gemini 335L** + Orbbec SDK | 小(API 映射) | -¥700 |
|
||||
| 室内客房高精度建模 | ZED 2i ULTRA | **Femto Mega**(iToF,更精) | 中(换 Kinect SDK) | -¥1,200 |
|
||||
| 走廊/大堂大场景 | ZED 2i + AreaMemory | **图漾 FM851** + 外接 IMU | 大(自接 SLAM) | +¥3,500 |
|
||||
| 机器人 SLAM | ZED 2i + 内建 VIO | **MYNT EYE D-1000** + VINS-Fusion | 中(换 VIO) | -¥1,000 |
|
||||
| 物体级近距建模 | ZED 2i 0.3m 模式 | **Astra Pro Plus** | 小 | -¥2,100 |
|
||||
| 户外/强光 | ZED 2i + 主动模式 | **图漾 FM851**(被动散斑) | 大 | +¥3,500 |
|
||||
| 极致低成本 DIY | — | **海康 MV-CA013 ×2 + BMI088** | 全自研 | -¥2,500 |
|
||||
|
||||
---
|
||||
|
||||
## 5. SDK 与代码迁移指南
|
||||
|
||||
### 5.1 API 映射表(ZED → Orbbec Gemini)
|
||||
|
||||
| ZED SDK | Orbbec SDK v2 | 备注 |
|
||||
|---|---|---|
|
||||
| `sl.Camera()` | `ob.Pipeline()` | 入口对象 |
|
||||
| `sl.InitParameters` | `ob.Config` + `ob.StreamProfile` | 多个对象 |
|
||||
| `zed.open(init_params)` | `pipeline.start(config)` | 启动 |
|
||||
| `zed.grab()` | `pipeline.wait_for_frames(timeout)` | 取帧 |
|
||||
| `retrieve_image(sl.VIEW.LEFT)` | `frames.color_frame()` / `frames.left_ir_frame()` | RGB / 左目 |
|
||||
| `retrieve_measure(sl.MEASURE.DEPTH)` | `frames.depth_frame()` | 深度 |
|
||||
| `retrieve_measure(sl.MEASURE.XYZRGBA)` | `frames.point_cloud_filter()` | 点云 |
|
||||
| `enable_positional_tracking()` | ❌ 需外接 ORB-SLAM3/VINS-Fusion | **主要差距** |
|
||||
| `enable_spatial_mapping()` | ❌ 需外接 Open3D / Voxblox | **主要差距** |
|
||||
| `enable_object_detection()` | ❌ 需外接 YOLO/SAM2 | **主要差距** |
|
||||
| `get_sensors_data().get_imu_data()` | `pipeline.get_imu_frame_set()` | IMU |
|
||||
|
||||
**核心结论**:奥比中光 SDK 提供**底层数据流**和**优秀的硬件接入**,但**高层算法**(VIO/Mapping/OD)需要自接开源栈。这对本项目反而是**好事**——M3 阶段本来就要做算法消融。
|
||||
|
||||
### 5.2 推荐的国产化软件栈
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
HW[国产相机硬件<br/>Gemini 335L / Femto Mega] --> SDK[Orbbec SDK / K4A SDK]
|
||||
SDK --> ROS[ROS 2 Humble]
|
||||
ROS --> VIO[VIO: ORB-SLAM3 / VINS-Fusion]
|
||||
ROS --> MAP[Mapping: Open3D / Voxblox / Nerfstudio]
|
||||
ROS --> OD[OD: YOLOv8 / GroundedSAM]
|
||||
VIO & MAP & OD --> DATA[统一数据契约<br/>M1-2 schema]
|
||||
```
|
||||
|
||||
### 5.3 迁移工作量估算
|
||||
|
||||
| 任务 | ZED 2i 工时 | 迁移到 Gemini 335L 工时 | 说明 |
|
||||
|---|---|---|---|
|
||||
| 数据采集脚本 | 1 天 | 1.5 天 | API 映射 |
|
||||
| 内外参标定导出 | 0.5 天 | 1 天 | Orbbec 标定文件格式不同 |
|
||||
| 深度图后处理 | 1 天 | 1 天 | 几乎无差异 |
|
||||
| VIO 位姿 | 0 天(内建) | 3–5 天 | 接 VINS-Fusion |
|
||||
| Spatial Mapping | 0 天(内建) | 3–5 天 | 接 Open3D TSDF / 3DGS |
|
||||
| ROS 2 集成 | 1 天 | 1.5 天 | 官方 wrapper 即可 |
|
||||
| **总计** | ~3.5 天 | ~12 天 | M3 阶段集中投入 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 采购、合规、供应链
|
||||
|
||||
### 6.1 采购渠道
|
||||
|
||||
| 厂商 | 官方直购 | 京东自营 | 淘宝/天猫 | 大客户报价 | 开票 |
|
||||
|---|---|---|---|---|---|
|
||||
| 奥比中光 | orbbec.com.cn | ✅ | ✅ | ✅ 5 折起 | 13% 增值税专票 |
|
||||
| 图漾 | percipio.xyz | ✅ 旗舰店 | ✅ | ✅ | 13% 专票 |
|
||||
| 小觅 | mynteye.com | ✅ | ✅ | ✅ | 13% 专票 |
|
||||
| 海康机器人 | hikrobotics.com | ❌(仅代理) | ❌ | ✅ 必须 | 13% 专票 |
|
||||
| 乐视 Femto | szlcsc.com 立创 | ✅ | ✅ | ✅ | 13% 专票 |
|
||||
|
||||
**建议**:
|
||||
- 试用阶段(M1):京东自营 1–2 台
|
||||
- M2–M3 批量:直接联系厂商大客户经理,5–8 折常见
|
||||
- M4 量产:签 OEM 协议,可定制外壳/接口
|
||||
|
||||
### 6.2 合规与信创要求
|
||||
|
||||
| 维度 | 状态 |
|
||||
|---|---|
|
||||
| 央国企/政府采购名录 | 奥比中光、海康均在;图漾部分在 |
|
||||
| 信创认证(鲲鹏/飞腾/麒麟) | 奥比中光官方支持鲲鹏 + 麒麟 V10 |
|
||||
| 数据出境合规 | 全部本地处理,无云端依赖(vs ZED 部分功能需要联网激活) |
|
||||
| 元器件国产化率 | 奥比中光主控为国产 ASIC;图漾为 FPGA + 国产 ARM;海康自研 SoC |
|
||||
|
||||
**关键风险点**:
|
||||
- ZED SDK 在国内**不强制**联网,但部分高级功能(Object Detection 模型下载)需要访问 Stereolabs 服务器,**有潜在断供风险**。
|
||||
- 国产替代后,所有模型/标定数据均落地本机,符合等保 2.0 三级要求。
|
||||
|
||||
### 6.3 供应链稳定性
|
||||
|
||||
| 厂商 | 主控芯片来源 | 关键传感器来源 | 风险等级 |
|
||||
|---|---|---|---|
|
||||
| 奥比中光 | 自研 ASIC(中芯流片) | OmniVision/索尼(双路备份) | 🟢 低 |
|
||||
| 图漾 | Xilinx FPGA(已部分切 Lattice) | 索尼 IMX 系列 | 🟡 中(FPGA 受限) |
|
||||
| 小觅 | NXP/TI | 索尼 / 长光辰芯 | 🟡 中 |
|
||||
| Stereolabs ZED | NVIDIA Tegra(深度依赖) | OnSemi | 🔴 高(地缘风险) |
|
||||
|
||||
---
|
||||
|
||||
## 7. 推荐的国产化组合套餐
|
||||
|
||||
### 7.1 套餐 A:性价比室内组(**首推**)
|
||||
|
||||
```
|
||||
主力:奥比中光 Gemini 335L ¥3,299
|
||||
公区补强:奥比中光 Astra Pro Plus ¥1,899
|
||||
总价:¥5,198
|
||||
覆盖:客房 + 走廊 + 大堂
|
||||
特点:Orbbec SDK 统一,开发体验一致
|
||||
```
|
||||
|
||||
### 7.2 套餐 B:高精度科研组
|
||||
|
||||
```
|
||||
主力:乐视 Femto Mega(Kinect 同源) ¥2,799
|
||||
SLAM 备份:MYNT EYE D-1000 ¥2,999
|
||||
总价:¥5,798
|
||||
覆盖:高精度 RGB-D + 双目 VIO 双路验证
|
||||
特点:可对照 Azure Kinect 学术基线
|
||||
```
|
||||
|
||||
### 7.3 套餐 C:工业部署组
|
||||
|
||||
```
|
||||
主力:图漾 FM851-GI-E1 ¥9,500
|
||||
室内补充:奥比中光 Gemini 335 ¥2,499
|
||||
IMU:Xsens MTi-3 ¥3,500
|
||||
总价:¥15,499
|
||||
覆盖:户外大场景 + 室内 + 高精度 IMU
|
||||
特点:IP67 + GigE,工业部署
|
||||
```
|
||||
|
||||
### 7.4 套餐 D:极致低成本研究组
|
||||
|
||||
```
|
||||
海康 MV-CA013-A0UC ×2(双目) ¥1,600
|
||||
Bosch BMI088 IMU 模组 ¥299
|
||||
3D 打印支架 + 同步触发板 ¥500
|
||||
总价:¥2,399
|
||||
覆盖:教学、SLAM 论文复现
|
||||
特点:全自研标定,完全可控,但工时投入大
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 与本项目 M1–M4 框架的对接
|
||||
|
||||
把国产化替代嵌入 [`zed2i_iterative_framework.md`](zed2i_iterative_framework.md) 的迭代节奏:
|
||||
|
||||
| 里程碑 | 国产化决策点 | 建议动作 |
|
||||
|---|---|---|
|
||||
| **M1 环境搂环** | 数据契约必须**抽象掉厂商差异** | M1-2 schema 用厂商中立字段(如 `depth.uint16`, `imu.6axis_hz`),让 ZED / Gemini / Femto 输出都能落到同一目录树 |
|
||||
| **M2 单场景达标** | 同一房间用 ZED 2i + Gemini 335L **各采一次**,互测精度 | 形成"国产 vs 进口"对照数据集,是 M4 评测基准的关键证据 |
|
||||
| **M3 批量化迭代** | 算法消融时把 SLAM 后端从"ZED 内建 VIO"换成"VINS-Fusion / ORB-SLAM3" | M3-3 直接受益:换硬件不换算法,可量化国产替代的真实差距 |
|
||||
| **M4 评测发布** | 在数据卡里**显式声明国产化率** | 服务于央国企/科研基金验收,是差异化卖点 |
|
||||
|
||||
### 8.1 推荐迁移路径(渐进式去 ZED)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
P1[阶段 1<br/>ZED 2i 跑通流程] --> P2[阶段 2<br/>加入 Gemini 335L 平行采集]
|
||||
P2 --> P3[阶段 3<br/>对照评测确认无明显差距]
|
||||
P3 --> P4[阶段 4<br/>主力切换为 Gemini<br/>ZED 退为对照基线]
|
||||
P4 --> P5[阶段 5<br/>对外发布国产化版本]
|
||||
```
|
||||
|
||||
**关键守则**:**不要一次性替换**——先在 M2 阶段并行采集对照,M3 阶段做完算法消融、确认精度差距 < 阈值后,再在 M4 发布国产化主力版本。
|
||||
|
||||
---
|
||||
|
||||
## 9. 风险与缓解
|
||||
|
||||
| 风险 | 触发场景 | 缓解策略 |
|
||||
|---|---|---|
|
||||
| 国产 SDK 文档/示例不如 ZED 详尽 | M1-1 环境搂环 | 优先选奥比中光(文档最全) + 加入官方钉钉群获得 1v1 支持 |
|
||||
| 国产相机缺乏"开箱即用的 VIO" | M2-1 / M3-3 | 把 VIO 作为**独立模块**接入(VINS-Fusion / ORB-SLAM3),反而提升可控性 |
|
||||
| iToF 路线(Femto)户外失效 | 大堂/室外采集 | 套餐 A/C 用结构光或双目相机补强公区 |
|
||||
| 国产相机 IMU 频率/同步质量差异 | M3-3 IMU 融合消融 | 严格在 M1-3 阶段做时间戳对齐验证;必要时外挂 Xsens MTi-3 |
|
||||
| 大客户折扣谈判周期长 | M3 批量采购 | 提前 1 个月联系厂商;先用试用单位起步 |
|
||||
| 替换后 Spatial Mapping 性能下降 | M2-1 房间级建图 | 用 Open3D ScalableTSDF / Nerfstudio 替代 ZED Spatial Mapping,质量反而更高 |
|
||||
|
||||
---
|
||||
|
||||
## 10. 引用与相关资源
|
||||
|
||||
### 10.1 官方资源
|
||||
|
||||
- 奥比中光:<https://www.orbbec.com.cn>(Gemini 335 产品页 + Orbbec SDK v2 文档)
|
||||
- 图漾科技:<https://www.percipio.xyz>(Camport SDK)
|
||||
- 小觅智能:<https://mynteye.com>(D-1000 产品页)
|
||||
- 海康机器人:<https://www.hikrobotics.com>
|
||||
- 大疆 Livox:<https://www.livoxtech.com>
|
||||
- 乐视/Femto(Orbbec 代工):包含在 Orbbec 官网 Femto 系列
|
||||
|
||||
### 10.2 本项目内文档
|
||||
|
||||
- 原方案细节:[`zed2i_stereo_imu_solution.md`](zed2i_stereo_imu_solution.md)
|
||||
- 迭代执行框架:[`zed2i_iterative_framework.md`](zed2i_iterative_framework.md)
|
||||
- 横向方案对比:[`camera_solutions_comprehensive.md`](camera_solutions_comprehensive.md)
|
||||
- 开源工具链:[`github_opensource_projects.md`](github_opensource_projects.md)
|
||||
- iPhone 对照线:[`../iphone/README.md`](../iphone/README.md)
|
||||
|
||||
### 10.3 开源 SLAM/Mapping 栈(国产替代 VIO/Mapping 模块)
|
||||
|
||||
- ORB-SLAM3:<https://github.com/UZ-SLAMLab/ORB_SLAM3>
|
||||
- VINS-Fusion:<https://github.com/HKUST-Aerial-Robotics/VINS-Fusion>
|
||||
- Open3D(TSDF/RGB-D Odometry):<https://github.com/isl-org/Open3D>
|
||||
- Nerfstudio(神经建图后端):<https://github.com/nerfstudio-project/nerfstudio>
|
||||
- gsplat / 3DGS(高保真重建):<https://github.com/nerfstudio-project/gsplat>
|
||||
|
||||
---
|
||||
|
||||
**版本**:v0.1(国产化替代方案首版)
|
||||
**最后更新**:2026-05-16
|
||||
**维护者**:项目规划团队
|
||||
**免责声明**:文中价格为公开渠道参考价(含税未含运费),随汇率/供需变动;最终采购请以厂商书面报价为准。
|
||||
@@ -0,0 +1,223 @@
|
||||
# ZED 2i 数据 Pipeline 迭代框架(面向 World Model 训练)
|
||||
|
||||
> 上层执行框架,承接 [`zed2i_stereo_imu_solution.md`](zed2i_stereo_imu_solution.md) 的硬件/SDK 细节,向下细化为可独立执行的 todo 项。
|
||||
> 设计哲学:**时间维度多次迭代**(M1→M4 螺旋上升)× **空间维度从粗到细**(场景→房间→物体→像素)。
|
||||
|
||||
---
|
||||
|
||||
## 0. 框架总览
|
||||
|
||||
### 0.1 两个正交维度
|
||||
|
||||
| 维度 | 取值 | 含义 |
|
||||
|------|------|------|
|
||||
| **时间(里程碑)** | M1 → M2 → M3 → M4 | 一次性原型 → 单场景达标 → 批量化迭代 → 评测发布 |
|
||||
| **空间(粒度)** | L1 场景 / L2 房间 / L3 物体 / L4 像素 | 全局拓扑 → 房间布局 → 家具个体 → 深度/纹理质量 |
|
||||
|
||||
每个里程碑都**在四个空间层级各完成一次切片**,形成 4 × 4 = 16 个交叉单元格。下游 world model 训练所需的"多尺度时空数据"由此自然涌现。
|
||||
|
||||
### 0.2 框架矩阵
|
||||
|
||||
| 空间\时间 | **M1 环境搂环** | **M2 单场景达标** | **M3 批量化迭代** | **M4 评测与发布** |
|
||||
|---|---|---|---|---|
|
||||
| **L1 场景** | 跑通 30s 走廊录制 | 单客房 Spatial Mapping 闭合 | ≥10 房型 SOP 化采集 | 场景级 benchmark split |
|
||||
| **L2 房间** | 房间数据目录契约 | 分区域稠密扫描覆盖率达标 | 自动质控 + 重采触发 | 房间布局/affordance 标注 |
|
||||
| **L3 物体** | 物体级 schema 占位 | 近距离环拍 ±2cm | 神经深度后处理消融 | 物体语义层(家具类别) |
|
||||
| **L4 像素** | 深度/位姿格式定义 | 置信度 mask + 失效分析 | VIO/深度算法对比 | 像素级误差指标定版 |
|
||||
|
||||
### 0.3 主线流程(Mermaid)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
M1[M1 环境搂环<br/>格式契约] --> M2[M2 单场景达标<br/>一间客房闭环]
|
||||
M2 --> M3[M3 批量化迭代<br/>多场景 + 算法消融]
|
||||
M3 --> M4[M4 评测发布<br/>World Model 接口]
|
||||
M4 -.反馈.-> M2
|
||||
M4 -.反馈.-> M3
|
||||
|
||||
subgraph 每个里程碑内部
|
||||
L1[L1 场景级] --> L2[L2 房间级]
|
||||
L2 --> L3[L3 物体级]
|
||||
L3 --> L4[L4 像素级]
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. M1:环境搂环与数据格式契约
|
||||
|
||||
**目标**:把"一段 30 秒走廊 SVO"完整跑通从录制到落盘到读取的全链路,建立后续所有工作的**数据契约**与**评测脚手架**。
|
||||
**出口判据**:任一新人按文档可在 1 小时内复现"录制→解析→评测桩输出"全流程。
|
||||
|
||||
### 1.1 任务分解
|
||||
|
||||
| ID | 空间层 | 任务 | 关键产出 |
|
||||
|---|---|---|---|
|
||||
| M1-1 | L1 | ZED SDK + CUDA + pyzed + ROS 2 安装;`ZED_Explorer` 与 `basic_capture.py` 烟囱测试 | `env_setup.md` + 一段 30s SVO |
|
||||
| M1-2 | L2 | 数据格式契约:目录树、命名、时间戳对齐、JSON/YAML schema | [`data_contract.md`](data_contract.md)(待建) |
|
||||
| M1-3 | L3/L4 | 相机内参导出、IMU-Camera 外参、世界坐标系约定(Z-up)、与 world model 坐标系映射 | `calibration.yaml` |
|
||||
| M1-4 | L4 | 评测脚手架(指标桩:ATE/RPE/深度误差/覆盖率/重投影) | `eval/` 目录骨架 |
|
||||
|
||||
### 1.2 推荐目录契约(落到 M1-2)
|
||||
|
||||
```
|
||||
dataset_root/
|
||||
├── sessions/
|
||||
│ └── {hotel_id}/{room_id}/{session_ts}/
|
||||
│ ├── raw.svo2 # ZED 原生录制
|
||||
│ ├── images/{left,right}/000000.png
|
||||
│ ├── depth/000000.npz # float32 + confidence
|
||||
│ ├── imu.parquet # 400Hz, 时间戳对齐
|
||||
│ ├── poses.tum # TUM 格式轨迹
|
||||
│ ├── pointcloud.ply # 融合点云
|
||||
│ ├── mesh.obj # Spatial Mapping 网格
|
||||
│ ├── area_memory.area # ZED 区域记忆
|
||||
│ └── meta.yaml # 设备、参数、环境、操作员
|
||||
├── calibration/{device_serial}.yaml
|
||||
└── eval/ # M1-4 脚手架
|
||||
├── metrics/
|
||||
└── reports/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. M2:单场景达标(一间客房闭环)
|
||||
|
||||
**目标**:把**一间客房**做到"world model 训练可直接使用"的质量,所有指标都有量化判据。空间上完成 L1→L4 一次完整下沉。
|
||||
**出口判据**:单房间数据包通过 M1-4 评测脚本所有阈值。
|
||||
|
||||
### 2.1 任务分解
|
||||
|
||||
| ID | 空间层 | 任务 | 量化判据 |
|
||||
|---|---|---|---|
|
||||
| M2-1 | L1 场景 | 一次性环绕扫描,输出 Spatial Mapping 网格 + 轨迹 | 环回误差 < 5cm,覆盖率 > 85% |
|
||||
| M2-2 | L2 房间 | 分区域慢扫(床区/卫浴/桌面/角落) | 每区域深度覆盖 ≥ 90%,空洞率 ≤ 5% |
|
||||
| M2-3 | L3 物体 | 家具/电器/装饰物 0.5–1m 环拍(ULTRA 模式) | 几何精度 ±2cm(用卷尺锚点验证) |
|
||||
| M2-4 | L4 像素 | 反光/透明/弱纹理失效分析;置信度过滤 mask | 失效区 mask 召回 > 90% |
|
||||
| M2-5 | 综合 | 单场景出口验收 | 通过 M1-4 全部阈值 |
|
||||
|
||||
### 2.2 空间下沉示意
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
A[L1 场景级 一次性环绕] --> B[L2 房间级 分区慢扫]
|
||||
B --> C[L3 物体级 近距环拍]
|
||||
C --> D[L4 像素级 失效mask]
|
||||
D --> E[出口验收包]
|
||||
E -.指标不达标.-> A
|
||||
```
|
||||
|
||||
### 2.3 采集动作规范(落到 SOP)
|
||||
|
||||
- L1 走位:门口起步,沿墙顺时针一圈,1m/s,相机略下倾 15°
|
||||
- L2 走位:每个功能区慢扫 30s,0.3 m/s,多视角往返
|
||||
- L3 走位:物体距离 0.5–1m,环拍 ≥ 270°,含俯视
|
||||
- L4 标注:人工标记反光/透明区域作为失效 GT
|
||||
|
||||
---
|
||||
|
||||
## 3. M3:批量化迭代(多场景 + 算法消融)
|
||||
|
||||
**目标**:把 M2 的单房成功复制到 ≥10 个房型,同时通过算法消融把整体质量再推高一档。
|
||||
**出口判据**:10+ 房型数据全部通过质控;至少一项算法迭代带来可量化提升(如深度 RMSE ↓ 20%)。
|
||||
|
||||
### 3.1 任务分解
|
||||
|
||||
| ID | 空间层 | 任务 | 关键消融变量 |
|
||||
|---|---|---|---|
|
||||
| M3-1 | L1 | 多房型批量采集 SOP(走位/时长/光照) | 房型 × 光照 × 操作员 |
|
||||
| M3-2 | L2 | 数据质控自动化(PASS/FAIL 报告 + 自动重采) | 阈值参数 |
|
||||
| M3-3 | L4 | 位姿算法对比:ZED VIO vs ORB-SLAM3 vs VINS-Fusion;IMU 融合开关 | 算法 × IMU on/off |
|
||||
| M3-4 | L4 | 深度算法对比:ZED ULTRA vs FoundationStereo/UniDepth 后处理 | 神经后处理 on/off |
|
||||
| M3-5 | L1/L2 | 多会话融合:`.area` 拼接、TSDF/Nerfacto/3DGS 后端选型 | 后端 × 输入子集 |
|
||||
| M3-6 | 综合 | 数据湖目录、按房间/时间/质量打标、子集导出工具 | — |
|
||||
|
||||
### 3.2 算法消融流(Mermaid)
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
DATA[M2 单场景数据] --> SPLIT[10 房型采集池]
|
||||
SPLIT --> VIO{位姿后端}
|
||||
SPLIT --> DEP{深度后端}
|
||||
VIO --> EVAL1[ATE/RPE]
|
||||
DEP --> EVAL2[深度 RMSE/覆盖]
|
||||
EVAL1 --> PICK[最优配置]
|
||||
EVAL2 --> PICK
|
||||
PICK --> FUSE[M3-5 融合建图]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. M4:评测基准与 World Model 接口
|
||||
|
||||
**目标**:把数据资产**对外可用**——定版评测基准、对齐主流 world model 训练框架、跑通基线模型回灌验证。
|
||||
**出口判据**:用本数据训练的小规模 world model 收敛并复现公开任务指标。
|
||||
|
||||
### 4.1 任务分解
|
||||
|
||||
| ID | 空间层 | 任务 | 关键产出 |
|
||||
|---|---|---|---|
|
||||
| M4-1 | L1–L4 | 评测基准定版:轨迹/深度/几何/时序/NVS 指标 + benchmark split | `benchmark/` |
|
||||
| M4-2 | 综合 | World Model 数据接口:webdataset / HDF5 / LeRobot 格式 | 导出脚本 + sample schema |
|
||||
| M4-3 | L2/L3/L4 | 任务化标注层:家具类别、可交互性、affordance | 多层级监督标签 |
|
||||
| M4-4 | 综合 | 基线回灌:训练 video prediction 或 NeRF 小模型 | 复现报告 |
|
||||
| M4-5 | 综合 | 数据卡(Datasheet for Datasets)+ 复现指南 + license | 发布包 |
|
||||
|
||||
### 4.2 World Model 接口示意
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
RAW[原始 SVO/RGB-D/IMU/Pose] --> EXPORT[M4-2 导出器]
|
||||
EXPORT --> WDS[webdataset]
|
||||
EXPORT --> H5[HDF5]
|
||||
EXPORT --> LEROBOT[LeRobot]
|
||||
WDS --> TRAIN[video prediction]
|
||||
H5 --> NERF[NeRF/3DGS]
|
||||
LEROBOT --> POLICY[robot policy]
|
||||
TRAIN & NERF & POLICY --> METRIC[M4-1 评测基准]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 跨里程碑的"螺旋反馈"
|
||||
|
||||
框架不是单向瀑布,而是**螺旋**:
|
||||
|
||||
- M4 评测发现的弱点 → 反馈到 M3 算法消融
|
||||
- M3 算法消融的最优配置 → 反向更新 M2 的采集 SOP
|
||||
- M2 的失败案例 → 暴露 M1 数据契约的缺陷 → 修订 schema
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
M1 --> M2 --> M3 --> M4
|
||||
M4 -- 弱点 --> M3
|
||||
M3 -- 最优配置 --> M2
|
||||
M2 -- 失败案例 --> M1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 风险与缓解
|
||||
|
||||
| 风险 | 触发里程碑 | 缓解策略 |
|
||||
|---|---|---|
|
||||
| 反光/玻璃区域深度大面积失效 | M2-4 | 偏振滤镜 + 神经深度后处理(M3-4) |
|
||||
| IMU 温度漂移导致长序列轨迹偏移 | M2-1 / M3-3 | 预热 5 分钟 + 多会话 `.area` 重定位 |
|
||||
| 数据量爆炸(10 房型 × N 会话) | M3-6 | 早期建立数据湖 + 质量打标 + 子集导出 |
|
||||
| World Model 框架接口频繁变动 | M4-2 | 中间层 schema 隔离,导出器适配多目标格式 |
|
||||
| 标注成本高 | M4-3 | 先半自动(ZED OD + SAM2)再人工修正 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 与既有文档的关系
|
||||
|
||||
- **底层硬件/SDK**:[`zed2i_stereo_imu_solution.md`](zed2i_stereo_imu_solution.md)
|
||||
- **横向方案对比**:[`camera_solutions_comprehensive.md`](camera_solutions_comprehensive.md)
|
||||
- **开源工具链**:[`github_opensource_projects.md`](github_opensource_projects.md)
|
||||
- **场景上层规划**:[`../hotel_scene_implementation_plan.md`](../hotel_scene_implementation_plan.md)
|
||||
- **iPhone 对照方案**:[`../iphone/README.md`](../iphone/README.md) / [`../iphone/iphone_simplified_plan.md`](../iphone/iphone_simplified_plan.md) / [`../iphone/roomplan_accuracy_and_cad_export.md`](../iphone/roomplan_accuracy_and_cad_export.md)
|
||||
|
||||
---
|
||||
|
||||
**版本**:v0.1(框架草案)
|
||||
**维护者**:项目规划团队
|
||||
@@ -0,0 +1,818 @@
|
||||
# ZED 2i 双目+IMU 完整解决方案
|
||||
|
||||
## 📋 方案概述
|
||||
|
||||
本方案基于Stereolabs ZED 2i双目相机,集成IMU传感器,提供实时3D感知和位姿估计能力,是性价比最高的一体化视觉惯性方案。
|
||||
|
||||
### 核心优势
|
||||
|
||||
- 💰 **成本低**:¥3,999(单设备完整方案)
|
||||
- ⚡ **实时性**:15-30 FPS深度计算
|
||||
- 🎯 **精度高**:深度精度±1-2%,位姿精度±0.1%
|
||||
- 🔧 **易集成**:SDK完善,支持多平台
|
||||
- 🤖 **即插即用**:无需标定,开箱可用
|
||||
|
||||
### 适用场景
|
||||
|
||||
- ✅ 室内移动机器人导航
|
||||
- ✅ 实时3D建图与定位
|
||||
- ✅ AR/VR应用
|
||||
- ✅ 无人机室内飞行
|
||||
- ✅ 酒店场景快速扫描
|
||||
|
||||
---
|
||||
|
||||
## 一、硬件规格详解
|
||||
|
||||
### 1.1 ZED 2i 技术参数
|
||||
|
||||
```yaml
|
||||
基本信息:
|
||||
型号: ZED 2i
|
||||
制造商: Stereolabs
|
||||
价格: ¥3,999
|
||||
重量: 159g
|
||||
尺寸: 175mm × 30mm × 33mm
|
||||
|
||||
双目相机:
|
||||
传感器: 2× 2.1MP CMOS
|
||||
分辨率:
|
||||
- 2.2K: 2208×1242 @ 15fps
|
||||
- 1080p: 1920×1080 @ 30fps
|
||||
- 720p: 1280×720 @ 60fps
|
||||
- WVGA: 1344×376 @ 100fps
|
||||
基线距离: 120mm
|
||||
视场角: 110° (H) × 70° (V)
|
||||
快门: 全局快门(避免运动模糊)
|
||||
|
||||
深度感知:
|
||||
测距范围: 0.3m - 20m
|
||||
深度精度: ±1-2% @ 1-3m
|
||||
深度模式:
|
||||
- PERFORMANCE: 高速
|
||||
- QUALITY: 高质量
|
||||
- ULTRA: 超高质量
|
||||
最小深度: 0.3m (近距离模式)
|
||||
|
||||
IMU传感器:
|
||||
类型: 6轴IMU (加速度计 + 陀螺仪)
|
||||
采样率: 400 Hz
|
||||
加速度计范围: ±16g
|
||||
陀螺仪范围: ±2000 dps
|
||||
温度补偿: 是
|
||||
|
||||
其他特性:
|
||||
接口: USB 3.0 Type-C
|
||||
功耗: 3.5W (典型)
|
||||
工作温度: 0°C - 45°C
|
||||
防护等级: IP44 (防尘防溅)
|
||||
```
|
||||
|
||||
### 1.2 与其他双目相机对比
|
||||
|
||||
| 型号 | 价格 | 基线 | 分辨率 | IMU | 深度精度 | 推荐度 |
|
||||
|-----|------|------|--------|-----|---------|--------|
|
||||
| **ZED 2i** | ¥3,999 | 120mm | 2.2K@15fps | ✅ 400Hz | ±1-2% | ⭐⭐⭐⭐⭐ |
|
||||
| ZED 2 | ¥2,999 | 120mm | 2.2K@15fps | ✅ 100Hz | ±1-2% | ⭐⭐⭐⭐ |
|
||||
| ZED X | ¥5,999 | 120mm | 1.2MP@60fps | ✅ 400Hz | ±1% | ⭐⭐⭐⭐ |
|
||||
| RealSense D455 | ¥2,999 | 95mm | 1280×720 | ❌ | ±2% | ⭐⭐⭐ |
|
||||
| OAK-D Pro | ¥4,999 | 75mm | 4K@30fps | ✅ | ±1% | ⭐⭐⭐⭐ |
|
||||
|
||||
**结论**:ZED 2i在价格、性能、IMU质量的平衡上最优。
|
||||
|
||||
---
|
||||
|
||||
## 二、软件生态与SDK
|
||||
|
||||
### 2.1 ZED SDK
|
||||
|
||||
```yaml
|
||||
支持平台:
|
||||
- Windows 10/11
|
||||
- Ubuntu 18.04/20.04/22.04
|
||||
- Jetson (Nano, Xavier, Orin)
|
||||
- Docker
|
||||
|
||||
编程语言:
|
||||
- C++
|
||||
- Python
|
||||
- C#
|
||||
- Unity
|
||||
- Unreal Engine
|
||||
|
||||
核心模块:
|
||||
- Camera: 相机控制
|
||||
- Depth: 深度计算
|
||||
- Tracking: 位姿估计
|
||||
- Spatial Mapping: 3D建图
|
||||
- Object Detection: 物体检测
|
||||
- Body Tracking: 人体追踪
|
||||
|
||||
ROS支持:
|
||||
- ROS 1 (Melodic, Noetic)
|
||||
- ROS 2 (Foxy, Humble)
|
||||
```
|
||||
|
||||
### 2.2 安装配置
|
||||
|
||||
```bash
|
||||
# Ubuntu安装ZED SDK
|
||||
# 1. 下载SDK
|
||||
wget https://download.stereolabs.com/zedsdk/4.0/cu118/ubuntu22
|
||||
|
||||
# 2. 安装
|
||||
chmod +x ZED_SDK_Ubuntu22_cuda11.8_v4.0.run
|
||||
./ZED_SDK_Ubuntu22_cuda11.8_v4.0.run
|
||||
|
||||
# 3. 安装Python包
|
||||
pip install pyzed
|
||||
|
||||
# 4. 验证安装
|
||||
ZED_Explorer
|
||||
|
||||
# ROS 2安装
|
||||
sudo apt install ros-humble-zed-ros2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、核心功能实现
|
||||
|
||||
### 3.1 基础采集
|
||||
|
||||
```python
|
||||
# basic_capture.py
|
||||
import pyzed.sl as sl
|
||||
import numpy as np
|
||||
import cv2
|
||||
|
||||
class ZED2iCamera:
|
||||
"""ZED 2i相机封装"""
|
||||
|
||||
def __init__(self):
|
||||
# 创建相机对象
|
||||
self.zed = sl.Camera()
|
||||
|
||||
# 配置参数
|
||||
self.init_params = sl.InitParameters()
|
||||
self.init_params.camera_resolution = sl.RESOLUTION.HD1080
|
||||
self.init_params.camera_fps = 30
|
||||
self.init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
self.init_params.coordinate_units = sl.UNIT.METER
|
||||
self.init_params.depth_minimum_distance = 0.3
|
||||
self.init_params.depth_maximum_distance = 20.0
|
||||
|
||||
# 打开相机
|
||||
err = self.zed.open(self.init_params)
|
||||
if err != sl.ERROR_CODE.SUCCESS:
|
||||
print(f"Error opening camera: {err}")
|
||||
exit(1)
|
||||
|
||||
# 创建图像容器
|
||||
self.image_left = sl.Mat()
|
||||
self.image_right = sl.Mat()
|
||||
self.depth_map = sl.Mat()
|
||||
self.point_cloud = sl.Mat()
|
||||
|
||||
# 运行时参数
|
||||
self.runtime_params = sl.RuntimeParameters()
|
||||
self.runtime_params.sensing_mode = sl.SENSING_MODE.STANDARD
|
||||
|
||||
print("ZED 2i initialized successfully")
|
||||
|
||||
def grab_frame(self):
|
||||
"""采集一帧数据"""
|
||||
if self.zed.grab(self.runtime_params) == sl.ERROR_CODE.SUCCESS:
|
||||
# 获取左右图像
|
||||
self.zed.retrieve_image(self.image_left, sl.VIEW.LEFT)
|
||||
self.zed.retrieve_image(self.image_right, sl.VIEW.RIGHT)
|
||||
|
||||
# 获取深度图
|
||||
self.zed.retrieve_measure(self.depth_map, sl.MEASURE.DEPTH)
|
||||
|
||||
# 获取点云
|
||||
self.zed.retrieve_measure(self.point_cloud, sl.MEASURE.XYZRGBA)
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_images(self):
|
||||
"""获取RGB图像"""
|
||||
left_img = self.image_left.get_data()
|
||||
right_img = self.image_right.get_data()
|
||||
return left_img, right_img
|
||||
|
||||
def get_depth(self):
|
||||
"""获取深度图"""
|
||||
depth = self.depth_map.get_data()
|
||||
return depth
|
||||
|
||||
def get_pointcloud(self):
|
||||
"""获取点云"""
|
||||
pc = self.point_cloud.get_data()
|
||||
return pc
|
||||
|
||||
def close(self):
|
||||
"""关闭相机"""
|
||||
self.zed.close()
|
||||
|
||||
# 使用示例
|
||||
camera = ZED2iCamera()
|
||||
|
||||
while True:
|
||||
if camera.grab_frame():
|
||||
# 获取数据
|
||||
left, right = camera.get_images()
|
||||
depth = camera.get_depth()
|
||||
|
||||
# 显示
|
||||
cv2.imshow("Left", left)
|
||||
cv2.imshow("Depth", depth / 20.0) # 归一化到0-1
|
||||
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
|
||||
camera.close()
|
||||
cv2.destroyAllWindows()
|
||||
```
|
||||
|
||||
### 3.2 位姿追踪(Tracking)
|
||||
|
||||
```python
|
||||
# tracking.py
|
||||
import pyzed.sl as sl
|
||||
import numpy as np
|
||||
|
||||
class ZED2iTracking:
|
||||
"""ZED 2i位姿追踪"""
|
||||
|
||||
def __init__(self):
|
||||
self.zed = sl.Camera()
|
||||
|
||||
# 初始化参数
|
||||
init_params = sl.InitParameters()
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720
|
||||
init_params.camera_fps = 60
|
||||
init_params.coordinate_units = sl.UNIT.METER
|
||||
init_params.coordinate_system = sl.COORDINATE_SYSTEM.RIGHT_HANDED_Z_UP
|
||||
|
||||
# 打开相机
|
||||
err = self.zed.open(init_params)
|
||||
if err != sl.ERROR_CODE.SUCCESS:
|
||||
exit(1)
|
||||
|
||||
# 启用位姿追踪
|
||||
tracking_params = sl.PositionalTrackingParameters()
|
||||
tracking_params.enable_imu_fusion = True # 启用IMU融合
|
||||
tracking_params.enable_area_memory = True # 启用区域记忆
|
||||
|
||||
err = self.zed.enable_positional_tracking(tracking_params)
|
||||
if err != sl.ERROR_CODE.SUCCESS:
|
||||
print(f"Error enabling tracking: {err}")
|
||||
exit(1)
|
||||
|
||||
# 位姿对象
|
||||
self.camera_pose = sl.Pose()
|
||||
self.imu_data = sl.SensorsData()
|
||||
|
||||
print("Tracking initialized")
|
||||
|
||||
def get_pose(self):
|
||||
"""获取相机位姿"""
|
||||
if self.zed.grab() == sl.ERROR_CODE.SUCCESS:
|
||||
# 获取位姿
|
||||
tracking_state = self.zed.get_position(
|
||||
self.camera_pose,
|
||||
sl.REFERENCE_FRAME.WORLD
|
||||
)
|
||||
|
||||
if tracking_state == sl.POSITIONAL_TRACKING_STATE.OK:
|
||||
# 提取位置和旋转
|
||||
translation = self.camera_pose.get_translation().get()
|
||||
rotation = self.camera_pose.get_rotation_matrix().r
|
||||
|
||||
# 获取IMU数据
|
||||
self.zed.get_sensors_data(
|
||||
self.imu_data,
|
||||
sl.TIME_REFERENCE.IMAGE
|
||||
)
|
||||
|
||||
imu = self.imu_data.get_imu_data()
|
||||
|
||||
return {
|
||||
'position': translation,
|
||||
'rotation': rotation,
|
||||
'tracking_state': tracking_state,
|
||||
'imu': {
|
||||
'linear_acceleration': imu.get_linear_acceleration(),
|
||||
'angular_velocity': imu.get_angular_velocity(),
|
||||
'orientation': imu.get_pose().get_orientation().get()
|
||||
}
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
def reset_tracking(self):
|
||||
"""重置追踪"""
|
||||
self.zed.reset_positional_tracking(sl.Transform())
|
||||
|
||||
def save_area_memory(self, filename):
|
||||
"""保存区域记忆"""
|
||||
self.zed.save_area_memory(filename)
|
||||
|
||||
def load_area_memory(self, filename):
|
||||
"""加载区域记忆"""
|
||||
self.zed.load_area_memory(filename)
|
||||
|
||||
# 使用示例
|
||||
tracker = ZED2iTracking()
|
||||
|
||||
trajectory = []
|
||||
|
||||
while True:
|
||||
pose_data = tracker.get_pose()
|
||||
|
||||
if pose_data:
|
||||
pos = pose_data['position']
|
||||
trajectory.append(pos)
|
||||
|
||||
print(f"Position: x={pos[0]:.2f}, y={pos[1]:.2f}, z={pos[2]:.2f}")
|
||||
print(f"IMU Accel: {pose_data['imu']['linear_acceleration']}")
|
||||
|
||||
# 每100帧保存一次轨迹
|
||||
if len(trajectory) % 100 == 0:
|
||||
np.save('trajectory.npy', np.array(trajectory))
|
||||
|
||||
# 保存区域记忆
|
||||
tracker.save_area_memory("hotel_room.area")
|
||||
```
|
||||
|
||||
### 3.3 空间建图(Spatial Mapping)
|
||||
|
||||
```python
|
||||
# spatial_mapping.py
|
||||
import pyzed.sl as sl
|
||||
import numpy as np
|
||||
|
||||
class ZED2iMapping:
|
||||
"""ZED 2i 3D建图"""
|
||||
|
||||
def __init__(self):
|
||||
self.zed = sl.Camera()
|
||||
|
||||
# 初始化
|
||||
init_params = sl.InitParameters()
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720
|
||||
init_params.camera_fps = 30
|
||||
init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
init_params.coordinate_units = sl.UNIT.METER
|
||||
|
||||
self.zed.open(init_params)
|
||||
|
||||
# 启用追踪
|
||||
tracking_params = sl.PositionalTrackingParameters()
|
||||
tracking_params.enable_imu_fusion = True
|
||||
self.zed.enable_positional_tracking(tracking_params)
|
||||
|
||||
# 启用空间建图
|
||||
mapping_params = sl.SpatialMappingParameters()
|
||||
mapping_params.resolution_meter = 0.05 # 5cm分辨率
|
||||
mapping_params.range_meter = 10.0 # 10m范围
|
||||
mapping_params.use_chunk_only = False
|
||||
mapping_params.save_texture = True
|
||||
mapping_params.map_type = sl.SPATIAL_MAP_TYPE.FUSED_POINT_CLOUD
|
||||
|
||||
self.zed.enable_spatial_mapping(mapping_params)
|
||||
|
||||
self.mesh = sl.Mesh()
|
||||
self.fused_pc = sl.FusedPointCloud()
|
||||
|
||||
print("Spatial mapping initialized")
|
||||
|
||||
def update_map(self):
|
||||
"""更新地图"""
|
||||
if self.zed.grab() == sl.ERROR_CODE.SUCCESS:
|
||||
# 获取建图状态
|
||||
mapping_state = self.zed.get_spatial_mapping_state()
|
||||
|
||||
return mapping_state
|
||||
|
||||
return None
|
||||
|
||||
def extract_mesh(self, output_path="room.obj"):
|
||||
"""提取网格"""
|
||||
# 停止建图
|
||||
self.zed.pause_spatial_mapping(True)
|
||||
|
||||
# 提取网格
|
||||
self.zed.extract_whole_spatial_map(self.mesh)
|
||||
|
||||
# 过滤网格
|
||||
self.mesh.filter(
|
||||
sl.MeshFilterParameters.MESH_FILTER.LOW,
|
||||
update_chunk_only=False
|
||||
)
|
||||
|
||||
# 保存
|
||||
self.mesh.save(output_path)
|
||||
|
||||
print(f"Mesh saved to {output_path}")
|
||||
print(f"Vertices: {self.mesh.vertices.shape[0]}")
|
||||
print(f"Triangles: {self.mesh.triangles.shape[0]}")
|
||||
|
||||
# 恢复建图
|
||||
self.zed.pause_spatial_mapping(False)
|
||||
|
||||
def extract_pointcloud(self, output_path="room.ply"):
|
||||
"""提取点云"""
|
||||
self.zed.pause_spatial_mapping(True)
|
||||
|
||||
# 提取融合点云
|
||||
self.zed.extract_whole_spatial_map(self.fused_pc)
|
||||
|
||||
# 保存
|
||||
self.fused_pc.save(output_path)
|
||||
|
||||
print(f"Point cloud saved to {output_path}")
|
||||
print(f"Points: {self.fused_pc.vertices.shape[0]}")
|
||||
|
||||
self.zed.pause_spatial_mapping(False)
|
||||
|
||||
def get_map_statistics(self):
|
||||
"""获取地图统计信息"""
|
||||
stats = {
|
||||
'chunks': self.zed.get_spatial_mapping_state().number_of_chunks,
|
||||
'vertices': self.mesh.vertices.shape[0] if self.mesh.vertices.size > 0 else 0,
|
||||
'triangles': self.mesh.triangles.shape[0] if self.mesh.triangles.size > 0 else 0
|
||||
}
|
||||
return stats
|
||||
|
||||
# 使用示例
|
||||
mapper = ZED2iMapping()
|
||||
|
||||
print("开始建图,请移动相机扫描房间...")
|
||||
print("按 's' 保存地图,按 'q' 退出")
|
||||
|
||||
frame_count = 0
|
||||
|
||||
while True:
|
||||
state = mapper.update_map()
|
||||
|
||||
if state:
|
||||
frame_count += 1
|
||||
|
||||
if frame_count % 30 == 0: # 每秒显示一次
|
||||
stats = mapper.get_map_statistics()
|
||||
print(f"Chunks: {stats['chunks']}, "
|
||||
f"Vertices: {stats['vertices']}, "
|
||||
f"Triangles: {stats['triangles']}")
|
||||
|
||||
# 键盘控制
|
||||
key = cv2.waitKey(1) & 0xFF
|
||||
if key == ord('s'):
|
||||
print("保存地图...")
|
||||
mapper.extract_mesh("hotel_room.obj")
|
||||
mapper.extract_pointcloud("hotel_room.ply")
|
||||
elif key == ord('q'):
|
||||
break
|
||||
|
||||
print("建图完成")
|
||||
```
|
||||
|
||||
### 3.4 物体检测(Object Detection)
|
||||
|
||||
```python
|
||||
# object_detection.py
|
||||
import pyzed.sl as sl
|
||||
|
||||
class ZED2iObjectDetection:
|
||||
"""ZED 2i物体检测"""
|
||||
|
||||
def __init__(self):
|
||||
self.zed = sl.Camera()
|
||||
|
||||
# 初始化
|
||||
init_params = sl.InitParameters()
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720
|
||||
init_params.camera_fps = 30
|
||||
init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
|
||||
self.zed.open(init_params)
|
||||
|
||||
# 启用追踪
|
||||
tracking_params = sl.PositionalTrackingParameters()
|
||||
self.zed.enable_positional_tracking(tracking_params)
|
||||
|
||||
# 启用物体检测
|
||||
obj_det_params = sl.ObjectDetectionParameters()
|
||||
obj_det_params.enable_tracking = True
|
||||
obj_det_params.enable_segmentation = False
|
||||
obj_det_params.detection_model = sl.OBJECT_DETECTION_MODEL.MULTI_CLASS_BOX_FAST
|
||||
|
||||
self.zed.enable_object_detection(obj_det_params)
|
||||
|
||||
self.objects = sl.Objects()
|
||||
self.obj_runtime_params = sl.ObjectDetectionRuntimeParameters()
|
||||
self.obj_runtime_params.detection_confidence_threshold = 50
|
||||
|
||||
print("Object detection initialized")
|
||||
|
||||
def detect_objects(self):
|
||||
"""检测物体"""
|
||||
if self.zed.grab() == sl.ERROR_CODE.SUCCESS:
|
||||
# 检测物体
|
||||
self.zed.retrieve_objects(
|
||||
self.objects,
|
||||
self.obj_runtime_params
|
||||
)
|
||||
|
||||
detected = []
|
||||
|
||||
for obj in self.objects.object_list:
|
||||
detected.append({
|
||||
'id': obj.id,
|
||||
'label': obj.label,
|
||||
'confidence': obj.confidence,
|
||||
'position': obj.position,
|
||||
'velocity': obj.velocity,
|
||||
'bounding_box_2d': obj.bounding_box_2d,
|
||||
'bounding_box_3d': obj.bounding_box
|
||||
})
|
||||
|
||||
return detected
|
||||
|
||||
return []
|
||||
|
||||
# 使用示例
|
||||
detector = ZED2iObjectDetection()
|
||||
|
||||
while True:
|
||||
objects = detector.detect_objects()
|
||||
|
||||
for obj in objects:
|
||||
print(f"Object {obj['id']}: {obj['label']} "
|
||||
f"({obj['confidence']:.0f}%) "
|
||||
f"at {obj['position']}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、酒店场景应用方案
|
||||
|
||||
### 4.1 客房快速扫描
|
||||
|
||||
```yaml
|
||||
应用场景: 5分钟完成客房3D建模
|
||||
|
||||
硬件配置:
|
||||
- ZED 2i相机: ¥3,999
|
||||
- 手持稳定器: ¥899
|
||||
- 笔记本电脑: ¥8,000
|
||||
总成本: ¥12,898
|
||||
|
||||
扫描流程:
|
||||
1. 启动ZED 2i + 空间建图
|
||||
2. 从门口开始环绕房间
|
||||
3. 保持1-1.5m距离
|
||||
4. 移动速度: 0.3-0.5 m/s
|
||||
5. 重点扫描家具和角落
|
||||
6. 实时查看建图进度
|
||||
7. 完成后导出Mesh
|
||||
|
||||
输出结果:
|
||||
- 3D网格模型(OBJ)
|
||||
- 融合点云(PLY)
|
||||
- 相机轨迹(TXT)
|
||||
- 区域记忆(AREA)
|
||||
|
||||
精度指标:
|
||||
- 几何精度: ±3-5cm
|
||||
- 覆盖率: > 90%
|
||||
- 采集时间: 5-10分钟
|
||||
- 处理时间: 实时
|
||||
```
|
||||
|
||||
### 4.2 机器人导航
|
||||
|
||||
```yaml
|
||||
应用场景: 服务机器人室内导航
|
||||
|
||||
系统架构:
|
||||
ZED 2i → ROS 2 → Navigation Stack → 机器人控制
|
||||
|
||||
ROS 2节点:
|
||||
- zed_wrapper: 相机驱动
|
||||
- zed_tracking: 位姿发布
|
||||
- zed_mapping: 地图构建
|
||||
- nav2: 导航规划
|
||||
|
||||
功能实现:
|
||||
- 实时SLAM建图
|
||||
- 自主定位
|
||||
- 路径规划
|
||||
- 障碍物避让
|
||||
- 动态重规划
|
||||
|
||||
性能指标:
|
||||
- 定位精度: ±5cm
|
||||
- 更新频率: 30 Hz
|
||||
- 地图分辨率: 5cm
|
||||
- 最大速度: 1 m/s
|
||||
```
|
||||
|
||||
### 4.3 AR导览系统
|
||||
|
||||
```yaml
|
||||
应用场景: 酒店AR导览与信息叠加
|
||||
|
||||
技术栈:
|
||||
- ZED 2i: 位姿追踪
|
||||
- Unity: AR渲染
|
||||
- ZED Unity Plugin: 集成
|
||||
|
||||
功能特性:
|
||||
- 实时位姿追踪
|
||||
- 虚拟信息叠加
|
||||
- 空间锚点
|
||||
- 遮挡处理
|
||||
|
||||
应用示例:
|
||||
- 房间导航箭头
|
||||
- 设施信息标注
|
||||
- 虚拟导游
|
||||
- 互动游戏
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、性能优化
|
||||
|
||||
### 5.1 参数调优
|
||||
|
||||
```python
|
||||
# 不同场景的最佳参数
|
||||
|
||||
# 场景1:高速移动(机器人)
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720
|
||||
init_params.camera_fps = 60
|
||||
init_params.depth_mode = sl.DEPTH_MODE.PERFORMANCE
|
||||
|
||||
# 场景2:高质量建图(静态扫描)
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD1080
|
||||
init_params.camera_fps = 15
|
||||
init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
|
||||
# 场景3:实时AR(低延迟)
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720
|
||||
init_params.camera_fps = 60
|
||||
init_params.depth_mode = sl.DEPTH_MODE.PERFORMANCE
|
||||
runtime_params.enable_depth = False # 仅追踪
|
||||
|
||||
# 场景4:远距离检测
|
||||
init_params.depth_minimum_distance = 1.0
|
||||
init_params.depth_maximum_distance = 20.0
|
||||
init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
```
|
||||
|
||||
### 5.2 性能基准
|
||||
|
||||
| 配置 | 分辨率 | FPS | 深度模式 | CPU占用 | GPU占用 | 延迟 |
|
||||
|-----|--------|-----|---------|---------|---------|------|
|
||||
| 高速 | 720p | 60 | PERFORMANCE | 15% | 20% | 16ms |
|
||||
| 标准 | 1080p | 30 | QUALITY | 25% | 35% | 33ms |
|
||||
| 高质量 | 1080p | 15 | ULTRA | 35% | 50% | 66ms |
|
||||
| 超高质量 | 2.2K | 15 | ULTRA | 45% | 65% | 66ms |
|
||||
|
||||
**测试平台**:Intel i7-11800H + RTX 3060 Laptop
|
||||
|
||||
---
|
||||
|
||||
## 六、故障排查
|
||||
|
||||
### 6.1 常见问题
|
||||
|
||||
```yaml
|
||||
问题1: 相机无法打开
|
||||
原因: USB带宽不足
|
||||
解决: 使用USB 3.0接口,避免USB Hub
|
||||
|
||||
问题2: 追踪丢失
|
||||
原因: 纹理不足或运动过快
|
||||
解决: 降低移动速度,增加环境纹理
|
||||
|
||||
问题3: 深度图有空洞
|
||||
原因: 反光表面或透明物体
|
||||
解决: 调整光照,使用ULTRA模式
|
||||
|
||||
问题4: IMU数据不稳定
|
||||
原因: 温度漂移或磁干扰
|
||||
解决: 预热5分钟,远离磁场
|
||||
|
||||
问题5: 建图不完整
|
||||
原因: 移动过快或覆盖不足
|
||||
解决: 降低速度,增加重叠率
|
||||
```
|
||||
|
||||
### 6.2 性能优化建议
|
||||
|
||||
```python
|
||||
# 优化技巧
|
||||
|
||||
# 1. 降低分辨率提升帧率
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD720 # 而非HD1080
|
||||
|
||||
# 2. 使用GPU加速
|
||||
init_params.sdk_gpu_id = 0 # 指定GPU
|
||||
|
||||
# 3. 禁用不需要的功能
|
||||
runtime_params.enable_depth = False # 仅需RGB时
|
||||
|
||||
# 4. 批量处理
|
||||
# 每N帧处理一次深度,而非每帧
|
||||
|
||||
# 5. 异步处理
|
||||
# 使用多线程分离采集和处理
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、完整项目示例
|
||||
|
||||
### 7.1 酒店客房扫描系统
|
||||
|
||||
```python
|
||||
# hotel_room_scanner.py
|
||||
import pyzed.sl as sl
|
||||
import cv2
|
||||
import numpy as np
|
||||
import time
|
||||
|
||||
class HotelRoomScanner:
|
||||
"""酒店客房扫描系统"""
|
||||
|
||||
def __init__(self, room_id):
|
||||
self.room_id = room_id
|
||||
self.zed = sl.Camera()
|
||||
|
||||
# 初始化相机
|
||||
init_params = sl.InitParameters()
|
||||
init_params.camera_resolution = sl.RESOLUTION.HD1080
|
||||
init_params.camera_fps = 30
|
||||
init_params.depth_mode = sl.DEPTH_MODE.ULTRA
|
||||
init_params.coordinate_units = sl.UNIT.METER
|
||||
|
||||
err = self.zed.open(init_params)
|
||||
if err != sl.ERROR_CODE.SUCCESS:
|
||||
print(f"Error: {err}")
|
||||
exit(1)
|
||||
|
||||
# 启用追踪
|
||||
tracking_params = sl.PositionalTrackingParameters()
|
||||
tracking_params.enable_imu_fusion = True
|
||||
tracking_params.enable_area_memory = True
|
||||
self.zed.enable_positional_tracking(tracking_params)
|
||||
|
||||
# 启用建图
|
||||
mapping_params = sl.SpatialMappingParameters()
|
||||
mapping_params.resolution_meter = 0.05
|
||||
mapping_params.range_meter = 10.0
|
||||
mapping_params.save_texture = True
|
||||
self.zed.enable_spatial_mapping(mapping_params)
|
||||
|
||||
# 数据容器
|
||||
self.image = sl.Mat()
|
||||
self.depth = sl.Mat()
|
||||
self.mesh = sl.Mesh()
|
||||
self.pose = sl.Pose()
|
||||
|
||||
# 统计
|
||||
self.start_time = time.time()
|
||||
self.frame_count = 0
|
||||
|
||||
print(f"Room {room_id} scanner initialized")
|
||||
|
||||
def scan(self, duration_seconds=300):
|
||||
"""扫描房间"""
|
||||
print(f"开始扫描房间 {self.room_id}")
|
||||
print(f"扫描时长: {duration_seconds}秒")
|
||||
print("请缓慢移动相机环绕房间...")
|
||||
|
||||
while (time.time() - self.start_time) < duration_seconds:
|
||||
if self.zed.grab() == sl.ERROR_CODE.SUCCESS:
|
||||
self.frame_count += 1
|
||||
|
||||
# 获取图像和深度
|
||||
self.zed.retrieve_image(self.image, sl.VIEW.LEFT)
|
||||
self.zed.retrieve_measure(self.depth, sl.MEASURE.DEPTH)
|
||||
|
||||
# 获取位姿
|
||||
state = self.zed.get_position(self.pose, sl.REFERENCE_FRAME.WORLD)
|
||||
|
||||
# 显示进度
|
||||
if self.frame_count % 30 == 0:
|
||||
elapsed = time.time() - self.start_time
|
||||
remaining = duration_seconds - elapsed
|
||||
|
||||
stats = self.zed.get_spatial_mapping_state()
|
||||
|
||||
print(f"[{elapsed:.0f}s/{duration_seconds}s] "
|
||||
Reference in New Issue
Block a user