chore: initial commit — import worldmodel workspace (plans/, research/)
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user