22 KiB
22 KiB
title, date, draft, tags, categories
| title | date | draft | tags | categories | ||||
|---|---|---|---|---|---|---|---|---|
| 酒店场景室内建模与物理验证项目详细实施计划(续) | 2026-05-20 | false |
|
|
酒店场景室内建模与物理验证项目详细实施计划(续)
七、数据管理与存储架构(续)
7.2 数据库设计
-- PostgreSQL + PostGIS空间数据库
-- 场景表
CREATE TABLE scenes (
scene_id SERIAL PRIMARY KEY,
scene_type VARCHAR(50), -- 'lobby', 'corridor', 'room', 'bathroom'
hotel_name VARCHAR(100),
floor_number INTEGER,
capture_date TIMESTAMP,
sensor_config JSONB,
bbox_min GEOMETRY(POINTZ, 4326),
bbox_max GEOMETRY(POINTZ, 4326),
metadata JSONB
);
-- 物体实例表
CREATE TABLE object_instances (
instance_id SERIAL PRIMARY KEY,
scene_id INTEGER REFERENCES scenes(scene_id),
label VARCHAR(100),
category VARCHAR(50),
centroid GEOMETRY(POINTZ, 4326),
bbox_min GEOMETRY(POINTZ, 4326),
bbox_max GEOMETRY(POINTZ, 4326),
volume FLOAT,
mesh_path TEXT,
semantic_features VECTOR(512), -- CLIP特征,使用pgvector扩展
attributes JSONB, -- {material, color, state, affordance}
confidence FLOAT
);
-- 空间关系表
CREATE TABLE spatial_relations (
relation_id SERIAL PRIMARY KEY,
source_instance_id INTEGER REFERENCES object_instances(instance_id),
target_instance_id INTEGER REFERENCES object_instances(instance_id),
relation_type VARCHAR(50), -- 'supported_by', 'inside', 'next_to', 'above'
confidence FLOAT,
metadata JSONB
);
-- 重建模型表
CREATE TABLE reconstruction_models (
model_id SERIAL PRIMARY KEY,
scene_id INTEGER REFERENCES scenes(scene_id),
model_type VARCHAR(50), -- '3dgs', 'nerf', 'mesh'
file_path TEXT,
quality_metrics JSONB, -- {psnr, ssim, lpips}
training_config JSONB,
created_at TIMESTAMP
);
-- 物理属性表
CREATE TABLE physics_properties (
property_id SERIAL PRIMARY KEY,
instance_id INTEGER REFERENCES object_instances(instance_id),
mass FLOAT,
friction_static FLOAT,
friction_dynamic FLOAT,
restitution FLOAT,
is_articulated BOOLEAN,
joint_type VARCHAR(50), -- 'revolute', 'prismatic', 'fixed'
joint_params JSONB
);
-- 创建空间索引
CREATE INDEX idx_scenes_bbox ON scenes USING GIST(bbox_min);
CREATE INDEX idx_instances_centroid ON object_instances USING GIST(centroid);
CREATE INDEX idx_instances_semantic ON object_instances USING ivfflat(semantic_features vector_cosine_ops);
7.3 数据存储方案
存储层级:
热数据(频繁访问):
- 存储: NVMe SSD RAID 10
- 容量: 4TB
- 内容:
- 当前处理中的原始数据
- 训练好的3DGS/NeRF模型
- 数据库文件
- 备份: 每日增量备份
温数据(偶尔访问):
- 存储: SATA HDD RAID 6
- 容量: 20TB
- 内容:
- 历史原始数据
- 中间处理结果
- 渲染缓存
- 备份: 每周全量备份
冷数据(归档):
- 存储: 对象存储(MinIO/S3)
- 容量: 无限扩展
- 内容:
- 完成项目的完整数据集
- 多版本模型
- 实验日志
- 备份: 异地容灾
对象存储结构:
bucket: hotel-reconstruction
├── raw-data/
│ └── {hotel_name}/{scene_type}/{date}/
├── processed/
│ └── {hotel_name}/{scene_type}/{version}/
├── models/
│ └── {model_type}/{scene_id}/{checkpoint}/
└── exports/
└── {format}/{scene_id}/
7.4 数据版本控制
使用DVC(Data Version Control):
初始化:
$ dvc init
$ dvc remote add -d storage s3://hotel-reconstruction
跟踪大文件:
$ dvc add data/rooms/room_301/raw/
$ git add data/rooms/room_301/raw/.dvc
$ git commit -m "Add room 301 raw data"
版本切换:
$ git checkout v1.0
$ dvc checkout
数据管道:
# dvc.yaml
stages:
slam:
cmd: python scripts/run_slam.py
deps:
- data/raw/
- scripts/run_slam.py
outs:
- data/processed/slam/
3dgs_training:
cmd: python scripts/train_3dgs.py
deps:
- data/processed/slam/
- scripts/train_3dgs.py
outs:
- models/3dgs/
metrics:
- metrics/3dgs_quality.json
八、评测基准与验证方案
8.1 几何重建质量评测
8.1.1 点云精度评测
class GeometryEvaluator:
def __init__(self, ground_truth_mesh, reconstructed_pointcloud):
self.gt_mesh = ground_truth_mesh
self.recon_pc = reconstructed_pointcloud
def compute_chamfer_distance(self):
"""Chamfer距离(双向最近点距离)"""
# GT mesh采样点云
gt_pc = self.gt_mesh.sample_points_uniformly(100000)
# 重建点云 → GT点云
dist_recon_to_gt = self.nearest_neighbor_distance(
self.recon_pc, gt_pc
)
# GT点云 → 重建点云
dist_gt_to_recon = self.nearest_neighbor_distance(
gt_pc, self.recon_pc
)
chamfer = (dist_recon_to_gt.mean() + dist_gt_to_recon.mean()) / 2
return {
'chamfer_distance': chamfer,
'recon_to_gt_mean': dist_recon_to_gt.mean(),
'gt_to_recon_mean': dist_gt_to_recon.mean(),
'recon_to_gt_std': dist_recon_to_gt.std()
}
def compute_accuracy_completeness(self, threshold=0.05):
"""准确率与完整性(阈值:5cm)"""
gt_pc = self.gt_mesh.sample_points_uniformly(100000)
dist_recon_to_gt = self.nearest_neighbor_distance(
self.recon_pc, gt_pc
)
dist_gt_to_recon = self.nearest_neighbor_distance(
gt_pc, self.recon_pc
)
# 准确率:重建点中有多少在GT附近
accuracy = (dist_recon_to_gt < threshold).mean()
# 完整性:GT点中有多少被重建覆盖
completeness = (dist_gt_to_recon < threshold).mean()
# F-score
f_score = 2 * accuracy * completeness / (accuracy + completeness + 1e-8)
return {
'accuracy': accuracy,
'completeness': completeness,
'f_score': f_score
}
def compute_normal_consistency(self):
"""法线一致性"""
# 估计重建点云的法线
recon_normals = self.estimate_normals(self.recon_pc)
# 对于每个重建点,找到GT mesh上最近的面
closest_faces = self.find_closest_faces(self.recon_pc, self.gt_mesh)
gt_normals = self.gt_mesh.face_normals[closest_faces]
# 计算法线夹角
dot_products = np.abs((recon_normals * gt_normals).sum(axis=1))
normal_consistency = dot_products.mean()
return normal_consistency
8.1.2 渲染质量评测
class RenderingEvaluator:
def __init__(self, model, test_cameras, ground_truth_images):
self.model = model
self.test_cameras = test_cameras
self.gt_images = ground_truth_images
def evaluate_all_metrics(self):
results = {
'psnr': [],
'ssim': [],
'lpips': [],
'rendering_time': []
}
for cam, gt_img in zip(self.test_cameras, self.gt_images):
# 渲染
start_time = time.time()
rendered_img = self.model.render(cam)
render_time = time.time() - start_time
# 计算指标
psnr = self.compute_psnr(rendered_img, gt_img)
ssim = self.compute_ssim(rendered_img, gt_img)
lpips = self.compute_lpips(rendered_img, gt_img)
results['psnr'].append(psnr)
results['ssim'].append(ssim)
results['lpips'].append(lpips)
results['rendering_time'].append(render_time)
# 统计
summary = {
'psnr_mean': np.mean(results['psnr']),
'psnr_std': np.std(results['psnr']),
'ssim_mean': np.mean(results['ssim']),
'lpips_mean': np.mean(results['lpips']),
'fps': 1.0 / np.mean(results['rendering_time'])
}
return summary
def compute_psnr(self, img1, img2):
"""峰值信噪比"""
mse = np.mean((img1 - img2) ** 2)
if mse == 0:
return float('inf')
return 20 * np.log10(1.0 / np.sqrt(mse))
def compute_ssim(self, img1, img2):
"""结构相似性"""
from skimage.metrics import structural_similarity
return structural_similarity(
img1, img2,
multichannel=True,
data_range=1.0
)
def compute_lpips(self, img1, img2):
"""感知相似性(使用预训练网络)"""
import lpips
loss_fn = lpips.LPIPS(net='alex')
# 转换为tensor
img1_t = torch.from_numpy(img1).permute(2, 0, 1).unsqueeze(0)
img2_t = torch.from_numpy(img2).permute(2, 0, 1).unsqueeze(0)
return loss_fn(img1_t, img2_t).item()
8.2 语义理解评测
class SemanticEvaluator:
def __init__(self, predicted_instances, ground_truth_instances):
self.pred = predicted_instances
self.gt = ground_truth_instances
def compute_3d_iou(self):
"""3D IoU(Intersection over Union)"""
ious = []
for pred_inst in self.pred:
best_iou = 0
for gt_inst in self.gt:
if pred_inst['label'] != gt_inst['label']:
continue
# 计算3D包围盒IoU
intersection = self.bbox_intersection(
pred_inst['bbox'], gt_inst['bbox']
)
union = self.bbox_union(
pred_inst['bbox'], gt_inst['bbox']
)
iou = intersection / (union + 1e-8)
best_iou = max(best_iou, iou)
ious.append(best_iou)
return np.mean(ious)
def compute_map_3d(self, iou_threshold=0.5):
"""3D目标检测的mAP"""
# 按类别分组
categories = set([inst['label'] for inst in self.gt])
aps = []
for category in categories:
pred_cat = [p for p in self.pred if p['label'] == category]
gt_cat = [g for g in self.gt if g['label'] == category]
# 按置信度排序
pred_cat = sorted(pred_cat, key=lambda x: x['confidence'], reverse=True)
# 计算precision-recall
tp = np.zeros(len(pred_cat))
fp = np.zeros(len(pred_cat))
matched_gt = set()
for i, pred in enumerate(pred_cat):
best_iou = 0
best_gt_idx = -1
for j, gt in enumerate(gt_cat):
if j in matched_gt:
continue
iou = self.compute_iou_3d(pred['bbox'], gt['bbox'])
if iou > best_iou:
best_iou = iou
best_gt_idx = j
if best_iou >= iou_threshold:
tp[i] = 1
matched_gt.add(best_gt_idx)
else:
fp[i] = 1
# 累积
tp_cumsum = np.cumsum(tp)
fp_cumsum = np.cumsum(fp)
recalls = tp_cumsum / len(gt_cat)
precisions = tp_cumsum / (tp_cumsum + fp_cumsum + 1e-8)
# 计算AP(11点插值)
ap = self.compute_ap(recalls, precisions)
aps.append(ap)
return np.mean(aps)
def evaluate_scene_graph(self, pred_graph, gt_graph):
"""场景图评测"""
# 节点准确率
node_precision = len(set(pred_graph.nodes) & set(gt_graph.nodes)) / len(pred_graph.nodes)
node_recall = len(set(pred_graph.nodes) & set(gt_graph.nodes)) / len(gt_graph.nodes)
# 边准确率
edge_precision = len(set(pred_graph.edges) & set(gt_graph.edges)) / len(pred_graph.edges)
edge_recall = len(set(pred_graph.edges) & set(gt_graph.edges)) / len(gt_graph.edges)
return {
'node_precision': node_precision,
'node_recall': node_recall,
'edge_precision': edge_precision,
'edge_recall': edge_recall
}
8.3 物理交互评测
class PhysicsEvaluator:
def __init__(self, simulator, world_model):
self.sim = simulator
self.model = world_model
def evaluate_prediction_accuracy(self, test_scenarios):
"""评估物理预测准确性"""
results = []
for scenario in test_scenarios:
# 初始状态
initial_state = scenario['initial_state']
action = scenario['action']
# 真实仿真结果
self.sim.set_state(initial_state)
self.sim.apply_action(action)
self.sim.step(n_steps=100)
true_final_state = self.sim.get_state()
# 世界模型预测
predicted_final_state = self.model.predict(
initial_state, action, n_steps=100
)
# 计算误差
position_error = np.linalg.norm(
true_final_state['positions'] - predicted_final_state['positions']
)
velocity_error = np.linalg.norm(
true_final_state['velocities'] - predicted_final_state['velocities']
)
results.append({
'scenario': scenario['name'],
'position_error': position_error,
'velocity_error': velocity_error
})
return results
def evaluate_robot_task_success(self, tasks):
"""评估机器人任务成功率"""
success_count = 0
for task in tasks:
# 执行任务
success = self.execute_task_with_model(task)
if success:
success_count += 1
success_rate = success_count / len(tasks)
return {
'success_rate': success_rate,
'total_tasks': len(tasks),
'successful_tasks': success_count
}
def evaluate_zero_shot_generalization(self, novel_scenarios):
"""评估零样本泛化能力"""
# 在未见过的物体/场景上测试
results = []
for scenario in novel_scenarios:
# 使用世界模型进行规划
plan = self.model.plan(scenario['goal'])
# 执行并评估
success = self.execute_plan(plan, scenario)
results.append({
'scenario': scenario['name'],
'success': success,
'plan_length': len(plan)
})
return results
8.4 综合评测基准
评测套件: HotelScene-Bench
子基准1_几何重建:
数据集: 10个酒店场景(公共区域 + 客房 + 卫生间)
指标:
- Chamfer Distance < 3cm
- Accuracy@5cm > 95%
- Completeness@5cm > 90%
- Normal Consistency > 0.85
子基准2_渲染质量:
测试视角: 每场景100个新视角
指标:
- PSNR > 28 dB
- SSIM > 0.85
- LPIPS < 0.15
- FPS > 30 @ 1080p
子基准3_语义理解:
标注物体: 500+实例
指标:
- 3D mAP@0.5 > 70%
- 场景图节点F1 > 0.80
- 场景图边F1 > 0.65
- 开放词表检测准确率 > 60%
子基准4_物理交互:
任务类型:
- 导航(10个场景)
- 物体操作(50个任务)
- 铰接物体交互(30个任务)
指标:
- 导航成功率 > 85%
- 抓取成功率 > 75%
- 开门/拉抽屉成功率 > 80%
- 物理预测误差 < 10cm
子基准5_卫生间专项:
场景: 5个高反光卫生间
指标:
- 镜面几何恢复准确率 > 80%
- 玻璃透明物体检测率 > 70%
- 水龙头操作成功率 > 75%
九、项目实施时间规划
9.1 总体时间线(12个月)
gantt
title 酒店场景建模项目甘特图
dateFormat YYYY-MM-DD
section 准备阶段
硬件采购与到货 :p1, 2026-06-01, 30d
传感器标定与测试 :p2, after p1, 14d
软件环境搭建 :p3, 2026-06-01, 21d
section 数据采集
公共区域采集 :d1, after p2, 14d
客房采集(5间) :d2, after d1, 21d
卫生间采集 :d3, after d2, 14d
section 算法开发
SLAM建图模块 :a1, after p3, 30d
3DGS训练流程 :a2, after a1, 21d
语义理解模块 :a3, after a2, 30d
Ref-NeRF实现 :a4, after a3, 21d
section 系统集成
场景图构建 :i1, after a3, 21d
物理仿真集成 :i2, after i1, 30d
M-JEPA训练 :i3, after i2, 45d
section 验证与优化
评测基准构建 :v1, after i2, 21d
机器人实验 :v2, after i3, 30d
系统优化迭代 :v3, after v2, 30d
section 成果输出
论文撰写 :o1, after v2, 60d
开源准备 :o2, after v3, 21d
文档编写 :o3, after o2, 14d
9.2 详细里程碑
| 月份 | 里程碑 | 关键交付物 | 验收标准 |
|---|---|---|---|
| M1 | 项目启动 | 硬件到位、环境搭建完成 | 传感器标定误差 < 5mm |
| M2 | 数据采集完成 | 3个场景原始数据 | 数据完整性 > 95% |
| M3 | SLAM建图验证 | 公共区域点云地图 | 闭环误差 < 0.5% |
| M4 | 3DGS训练完成 | 实时渲染模型 | PSNR > 26 dB |
| M5 | 语义理解集成 | 场景图数据库 | mAP@0.5 > 60% |
| M6 | 卫生间模块完成 | Ref-NeRF模型 | 镜面恢复准确率 > 75% |
| M7 | 物理仿真就绪 | Isaac Sim场景 | 可交互物体 > 50个 |
| M8 | M-JEPA训练完成 | 世界模型权重 | 预测误差 < 15cm |
| M9 | 机器人实验 | 任务成功率报告 | 综合成功率 > 70% |
| M10 | 系统优化 | 优化后模型 | 性能提升 > 20% |
| M11 | 论文投稿 | 会议论文 | 投稿至顶会 |
| M12 | 开源发布 | GitHub仓库、数据集 | 文档完整度 100% |
9.3 人力资源配置
团队组成(建议):
项目负责人(PI)× 1:
- 职责: 总体把控、对外合作、论文指导
- 投入: 20% 时间
算法工程师 × 2:
- 职责: SLAM、3DGS、NeRF算法实现与优化
- 技能: C++/Python、CUDA、计算机视觉
- 投入: 100% 时间
机器学习工程师 × 1:
- 职责: M-JEPA训练、语义理解模块
- 技能: PyTorch、Transformer、强化学习
- 投入: 100% 时间
机器人工程师 × 1:
- 职责: Isaac Sim集成、机器人实验
- 技能: ROS2、物理仿真、机械臂控制
- 投入: 100% 时间
数据工程师 × 1:
- 职责: 数据采集、标注、数据库管理
- 技能: 传感器操作、SQL、数据处理
- 投入: 80% 时间(前6个月100%)
研究助理 × 2:
- 职责: 实验辅助、评测、文档编写
- 投入: 50% 时间
十、风险管理与应对策略
10.1 技术风险
| 风险项 | 概率 | 影响 | 应对策略 |
|---|---|---|---|
| 卫生间高反光重建失败 | 中 | 高 | 1. 提前进行小规模测试 2. 准备备选方案(手动建模) 3. 与偏振相机厂商技术支持 |
| 3DGS训练不收敛 | 低 | 中 | 1. 使用成熟的开源实现 2. 调整学习率和初始化 3. 分块训练降低难度 |
| M-JEPA物理预测不准确 | 中 | 中 | 1. 增加仿真数据量 2. 引入物理先验约束 3. 降低预测时长要求 |
| 实时性能不达标 | 低 | 中 | 1. 使用LOD技术 2. 模型剪枝与量化 3. 升级GPU硬件 |
| 语义分割精度低 | 低 | 低 | 1. 人工标注补充训练 2. 使用更大的基础模型 3. 多模型集成 |
10.2 工程风险
| 风险项 | 概率 | 影响 | 应对策略 |
|---|---|---|---|
| 硬件故障或延期 | 中 | 高 | 1. 提前2周下单 2. 准备备用设备 3. 建立供应商备选清单 |
| 数据采集权限受限 | 中 | 高 | 1. 提前与酒店沟通协议 2. 准备数据脱敏方案 3. 考虑使用公开数据集 |
| 存储空间不足 | 低 | 中 | 1. 实时监控存储使用 2. 及时清理中间文件 3. 扩展云存储 |
| 团队成员离职 | 低 | 高 | 1. 代码文档化 2. 知识定期分享 3. 关键模块双人备份 |
10.3 进度风险
| 风险项 | 概率 | 影响 | 应对策略 |
|---|---|---|---|
| 数据采集超时 | 中 | 中 | 1. 预留20%缓冲时间 2. 并行采集多个场景 3. 简化采集流程 |
| 算法调试周期长 | 高 | 中 | 1. 使用小规模数据快速迭代 2. 设置阶段性目标 3. 及时调整技术路线 |
| 论文被拒需返工 | 中 | 低 | 1. 提前内部审稿 2. 准备多个投稿目标 3. 持续改进实验 |
十一、预算估算
11.1 硬件设备预算
| 类别 | 项目 | 数量 | 单价(万元) | 小计(万元) |
|---|---|---|---|---|
| 传感器 | Livox Mid-360 LiDAR | 1 | 1.5 | 1.5 |
| Azure Kinect DK | 2 | 0.3 | 0.6 | |
| 偏振相机 Lucid Phoenix | 1 | 3.0 | 3.0 | |
| 高分辨率相机 Sony α7R IV | 1 | 2.0 | 2.0 | |
| IMU Xsens MTi-630 | 1 | 1.2 | 1.2 | |
| 平台 | 移动采集小车(定制) | 1 | 2.0 | 2.0 |
| Matterport Pro3(可选) | 1 | 4.0 | 0 | |
| 计算 | 工作站(2×RTX 4090) | 2 | 4.0 | 8.0 |
| NVIDIA Jetson AGX Orin | 1 | 1.0 | 1.0 | |