Files
worldmodel/plans/iphone/iphone_3d_reconstruction_opensource.md
T
gaojie 6b64d458bd
Sync to site1 / sync (push) Has been cancelled
chore: update iphone categories from worldmodel to RoomPlan
2026-05-21 02:30:30 +08:00

19 KiB
Raw Blame History

title, date, draft, tags, categories
title date draft tags categories
iPhone 3D重建开源项目研究报告 2026-05-20 false
iPhone
3D 重建
RoomPlan
NeRF
Gaussian Splatting
iOS
RoomPlan

iPhone 3D重建开源项目研究报告

📋 研究概述

本文档研究GitHub上最受欢迎的基于iPhone(特别是LiDAR)的3D重建开源项目,为酒店场景建模项目提供技术参考和实施方案。

研究时间2026-05-16
研究范围GitHub上Stars > 500的相关项目
关键词iPhone LiDAR, 3D Reconstruction, ARKit, RoomPlan, NeRF, 3DGS


一、顶级开源项目分析

1.1 Nerfstudio

GitHub: https://github.com/nerfstudio-project/nerfstudio
Stars: ~7,800
语言: Python
许可证: Apache 2.0

项目简介

Nerfstudio是一个模块化的NeRF训练和渲染框架,支持多种NeRF变体,包括专门针对iPhone数据的优化。

核心特性

支持的方法:
  - Nerfacto: 快速NeRF训练(默认)
  - Instant-NGP: 超快速训练
  - Splatfacto: 3D Gaussian Splatting
  - Nerfacto-big: 高质量场景
  - Depth-Nerfacto: 深度监督

iPhone支持:
  - ✅ 直接支持Record3D导出
  - ✅ 支持Polycam数据
  - ✅ ARKit位姿导入
  - ✅ 深度图融合

优势:
  - 模块化设计,易于扩展
  - Web查看器实时预览
  - 完整的训练pipeline
  - 活跃的社区支持

使用流程

# 1. 安装
pip install nerfstudio

# 2. 从iPhone数据训练(Polycam导出)
ns-process-data polycam \
  --data data/room_301 \
  --output-dir data/room_301/processed

# 3. 训练Splatfacto3DGS
ns-train splatfacto \
  --data data/room_301/processed \
  --max-num-iterations 30000

# 4. 实时查看(浏览器)
# 自动打开 http://localhost:7007

# 5. 导出模型
ns-export gaussian-splat \
  --load-config outputs/room_301/splatfacto/config.yml \
  --output-dir exports/room_301/

与酒店项目集成

# 自定义数据加载器
from nerfstudio.data.dataparsers.base_dataparser import DataparserConfig
from nerfstudio.data.dataparsers.nerfstudio_dataparser import NerfstudioDataParserConfig

# 配置
config = NerfstudioDataParserConfig(
    data=Path("data/room_301"),
    scale_factor=1.0,
    scene_scale=1.0,
    orientation_method="up",
    center_method="poses",
    auto_scale_poses=True,
)

# 训练配置
from nerfstudio.configs.method_configs import method_configs

splatfacto_config = method_configs["splatfacto"]
splatfacto_config.pipeline.datamanager.train_num_rays_per_batch = 4096
splatfacto_config.optimizers.camera_opt.optimizer.lr = 1e-3

推荐指数:
适用场景: 客房重建、高质量渲染、研究原型


1.2 Polycam (开源工具链)

相关项目: https://github.com/Polycam/polycam-cli
Stars: ~300
语言: Python/Swift
许可证: MIT

项目简介

Polycam虽然是商业App,但提供了开源的命令行工具和数据格式转换器,方便与其他工具集成。

核心特性

数据导出格式:
  - OBJ + MTL + 纹理
  - PLY点云
  - USDZ (AR Quick Look)
  - GLTF/GLB
  - FBX

API支持:
  - RESTful API
  - Python SDK
  - 批量处理

优势:
  - 零代码采集
  - 云端处理
  - 高质量输出
  - 支持大场景

数据格式

// Polycam导出的transforms.jsonNeRF格式)
{
  "camera_model": "OPENCV",
  "fl_x": 1066.778,
  "fl_y": 1067.487,
  "cx": 960.0,
  "cy": 540.0,
  "w": 1920,
  "h": 1080,
  "frames": [
    {
      "file_path": "images/frame_00000.jpg",
      "transform_matrix": [
        [0.999, -0.001, 0.002, 0.000],
        [0.001, 0.999, -0.003, 0.000],
        [-0.002, 0.003, 0.999, 0.000],
        [0.0, 0.0, 0.0, 1.0]
      ]
    }
  ]
}

与Nerfstudio集成

# 1. Polycam扫描并导出
# 2. 下载到本地
# 3. 直接用Nerfstudio训练
ns-train splatfacto --data polycam_export/

推荐指数:
适用场景: 快速采集、商业项目、非技术用户


1.3 Record3D

GitHub: https://github.com/marek-simonik/record3d
Stars: ~1,200
语言: Swift/Python
许可证: LGPL-3.0

项目简介

Record3D是一个开源的iPhone LiDAR录制App,支持实时流式传输深度和RGB数据到电脑。

核心特性

功能:
  - ✅ 实时LiDAR + RGB录制
  - ✅ WiFi/USB流式传输
  - ✅ Python API
  - ✅ 导出多种格式

数据格式:
  - R3D (专有格式)
  - PLY点云
  - OBJ网格
  - MP4视频 + 深度

优势:
  - 完全开源
  - 实时预览
  - Python集成简单
  - 支持ARKit位姿

Python API使用

from record3d import Record3DStream
import numpy as np

class MyRecord3DListener:
    def on_new_frame(self):
        # 获取RGB图像
        rgb = self.session.get_rgb_frame()
        
        # 获取深度图
        depth = self.session.get_depth_frame()
        
        # 获取相机位姿
        intrinsics = self.session.get_intrinsic_mat()
        pose = self.session.get_camera_pose()
        
        # 处理数据
        self.process_frame(rgb, depth, pose)
    
    def process_frame(self, rgb, depth, pose):
        # 保存或实时处理
        pass

# 连接iPhone
session = Record3DStream()
session.on_new_frame = MyRecord3DListener().on_new_frame
session.connect('192.168.1.100')  # iPhone IP

数据导出

# 导出为NeRF格式
from record3d_to_nerf import convert_r3d_to_nerf

convert_r3d_to_nerf(
    input_r3d='recording.r3d',
    output_dir='nerf_data/',
    scale=1.0
)

推荐指数:
适用场景: 实时采集、研究开发、自定义pipeline


1.4 3D Gaussian Splatting (官方实现)

GitHub: https://github.com/graphdeco-inria/gaussian-splatting
Stars: ~12,000
语言: Python/CUDA
许可证: Custom (研究使用)

项目简介

3DGS的官方实现,虽然不是专门为iPhone设计,但可以处理iPhone采集的数据。

核心特性

优势:
  - 实时渲染(> 100 FPS
  - 高质量重建
  - 训练快速(< 1小时)
  - 内存效率高

要求:
  - CUDA GPURTX 3090+推荐)
  - COLMAP位姿
  - 高质量图像

iPhone适配:
  - 需要先用COLMAP处理
  - 或使用Nerfstudio转换

使用流程

# 1. 从iPhone导出图像
# 2. COLMAP处理
colmap automatic_reconstructor \
  --workspace_path workspace \
  --image_path images

# 3. 训练3DGS
python train.py \
  -s workspace \
  -m output/room_301 \
  --iterations 30000

# 4. 实时查看
python render.py \
  -m output/room_301 \
  --skip_train

推荐指数:
适用场景: 高质量重建、实时渲染、研究论文


1.5 Apple RoomPlan (官方框架)

文档: https://developer.apple.com/documentation/roomplan
语言: Swift
许可证: Apple Developer License

项目简介

Apple官方的房间扫描框架,自动识别房间结构和家具。

核心特性

自动识别:
  - 墙面、地板、天花板
  - 门、窗户
  - 家具(床、桌子、椅子等)
  - 尺寸测量

输出格式:
  - USDZ (3D模型)
  - JSON (结构化数据)
  - CapturedRoom对象

优势:
  - 零配置
  - 自动语义标注
  - 符合曼哈顿假设
  - 实时反馈

Swift代码示例

import RoomPlan

class RoomCaptureViewController: UIViewController {
    var roomCaptureView: RoomCaptureView!
    var captureSession: RoomCaptureSession!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 初始化
        roomCaptureView = RoomCaptureView(frame: view.bounds)
        captureSession = RoomCaptureSession()
        
        // 配置
        var configuration = RoomCaptureSession.Configuration()
        configuration.isCoachingEnabled = true
        
        // 开始扫描
        roomCaptureView.captureSession = captureSession
        captureSession.run(configuration: configuration)
        
        // 设置代理
        captureSession.delegate = self
    }
}

extension RoomCaptureViewController: RoomCaptureSessionDelegate {
    func captureSession(_ session: RoomCaptureSession, 
                       didUpdate room: CapturedRoom) {
        // 实时更新
        print("Walls: \(room.walls.count)")
        print("Objects: \(room.objects.count)")
    }
    
    func captureSession(_ session: RoomCaptureSession, 
                       didEndWith data: CapturedRoomData, 
                       error: Error?) {
        // 扫描完成
        exportToUSDZ(data)
        exportToJSON(data)
    }
}

func exportToUSDZ(_ data: CapturedRoomData) {
    let url = FileManager.default.temporaryDirectory
        .appendingPathComponent("room.usdz")
    
    try? data.export(to: url)
}

导出的JSON格式

{
  "version": "1.0",
  "identifier": "room_301",
  "walls": [
    {
      "identifier": "wall_0",
      "transform": [...],
      "dimensions": {"width": 5.0, "height": 2.8}
    }
  ],
  "objects": [
    {
      "identifier": "bed_0",
      "category": "bed",
      "transform": [...],
      "dimensions": {"width": 2.0, "length": 2.0, "height": 0.5},
      "confidence": 0.95
    }
  ]
}

推荐指数:
适用场景: 客房快速建模、自动语义标注、AR应用


1.6 OpenCV SLAM (移动端)

GitHub: https://github.com/raulmur/ORB_SLAM3
Stars: ~6,000
语言: C++
许可证: GPLv3

项目简介

ORB-SLAM3是最先进的视觉SLAM系统,支持单目、双目、RGB-D和IMU融合。

iPhone适配

虽然ORB-SLAM3是C++实现,但有iOS移植版本:

iOS移植: https://github.com/ygx2011/ORB_SLAM2_iOS
Stars: ~200

功能:
  - 实时SLAM
  - 回环检测
  - 重定位
  - 地图保存/加载

iPhone集成:
  - ARKit位姿初始化
  - 深度图辅助
  - IMU融合

推荐指数:
适用场景: 研究项目、需要精确SLAM、大场景


二、开源项目对比矩阵

项目 Stars 易用性 质量 速度 iPhone支持 推荐度
Nerfstudio 7.8k 原生
Polycam 0.3k 专用
Record3D 1.2k 专用
3DGS官方 12k ⚠️ 需转换
RoomPlan N/A 官方
ORB-SLAM3 6k ⚠️ 需移植

三、推荐技术栈组合

3.1 方案A:快速原型(推荐新手)

采集: Polycam App
处理: Nerfstudio
渲染: Nerfstudio Web Viewer
导出: OBJ/GLTF

优势:
  - 零代码采集
  - 一键训练
  - 实时预览
  - 质量可控

工作流:
  1. Polycam扫描房间(15分钟)
  2. 导出数据到电脑
  3. Nerfstudio训练(2小时)
  4. 导出模型

成本: $11.99/月(Polycam Pro

3.2 方案B:高质量研究(推荐进阶)

采集: Record3D (开源)
SLAM: COLMAP
重建: 3DGS官方 + Nerfstudio
语义: RoomPlan API
物理: 手动标注 + USD导出

优势:
  - 完全开源
  - 最高质量
  - 完全可控
  - 适合论文

工作流:
  1. Record3D采集(20分钟)
  2. COLMAP位姿估计(30分钟)
  3. 3DGS训练(1小时)
  4. RoomPlan语义标注(5分钟)
  5. 手动物理属性标注(30分钟)

成本: 免费(需GPU

3.3 方案C:商业部署(推荐生产)

采集: 定制iOS App(基于RoomPlan
处理: 云端Nerfstudio
存储: AWS S3
查看: Web 3D Viewer

优势:
  - 用户友好
  - 可扩展
  - 自动化
  - 商业级

架构:
  iOS App → API Gateway → Lambda → Nerfstudio (EC2)
         
      S3 Storage → CloudFront → Web Viewer

成本: 按使用量计费

四、实战:基于开源工具的完整流程

4.1 环境准备

# 1. 安装Nerfstudio
pip install nerfstudio

# 2. 安装Record3D Python库
pip install record3d

# 3. 安装COLMAP(可选)
conda install -c conda-forge colmap

# 4. 安装其他依赖
pip install open3d opencv-python numpy

4.2 数据采集(Record3D

# record3d_capture.py
from record3d import Record3DStream
import cv2
import numpy as np
import json
from pathlib import Path

class DataCapture:
    def __init__(self, output_dir):
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(exist_ok=True)
        
        self.rgb_dir = self.output_dir / 'images'
        self.depth_dir = self.output_dir / 'depth'
        self.rgb_dir.mkdir(exist_ok=True)
        self.depth_dir.mkdir(exist_ok=True)
        
        self.frame_count = 0
        self.poses = []
        self.intrinsics = None
    
    def on_new_frame(self, session):
        # RGB
        rgb = session.get_rgb_frame()
        cv2.imwrite(
            str(self.rgb_dir / f'{self.frame_count:06d}.jpg'),
            cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR)
        )
        
        # Depth
        depth = session.get_depth_frame()
        depth_mm = (depth * 1000).astype(np.uint16)
        cv2.imwrite(
            str(self.depth_dir / f'{self.frame_count:06d}.png'),
            depth_mm
        )
        
        # Pose
        pose = session.get_camera_pose()
        self.poses.append(pose.tolist())
        
        # Intrinsics (只需一次)
        if self.intrinsics is None:
            self.intrinsics = session.get_intrinsic_mat().tolist()
        
        self.frame_count += 1
        
        if self.frame_count % 10 == 0:
            print(f'Captured {self.frame_count} frames')
    
    def save_metadata(self):
        metadata = {
            'intrinsics': self.intrinsics,
            'poses': self.poses,
            'num_frames': self.frame_count
        }
        
        with open(self.output_dir / 'metadata.json', 'w') as f:
            json.dump(metadata, f, indent=2)

# 使用
capture = DataCapture('data/room_301')
session = Record3DStream()
session.on_new_frame = lambda: capture.on_new_frame(session)

print("Connecting to iPhone...")
session.connect('192.168.1.100')  # 替换为iPhone IP

# 录制完成后
capture.save_metadata()
print(f"Captured {capture.frame_count} frames")

4.3 数据转换(NeRF格式)

# convert_to_nerf.py
import json
import numpy as np
from pathlib import Path

def convert_record3d_to_nerf(input_dir, output_dir):
    """转换Record3D数据为NeRF格式"""
    input_dir = Path(input_dir)
    output_dir = Path(output_dir)
    output_dir.mkdir(exist_ok=True)
    
    # 读取元数据
    with open(input_dir / 'metadata.json') as f:
        metadata = json.load(f)
    
    intrinsics = np.array(metadata['intrinsics'])
    poses = [np.array(p) for p in metadata['poses']]
    
    # 构建transforms.json
    transforms = {
        'camera_model': 'OPENCV',
        'fl_x': intrinsics[0, 0],
        'fl_y': intrinsics[1, 1],
        'cx': intrinsics[0, 2],
        'cy': intrinsics[1, 2],
        'w': 1920,
        'h': 1440,
        'frames': []
    }
    
    for i, pose in enumerate(poses):
        frame = {
            'file_path': f'images/{i:06d}.jpg',
            'transform_matrix': pose.tolist()
        }
        transforms['frames'].append(frame)
    
    # 保存
    with open(output_dir / 'transforms.json', 'w') as f:
        json.dump(transforms, f, indent=2)
    
    # 复制图像
    import shutil
    shutil.copytree(input_dir / 'images', output_dir / 'images')
    
    print(f"Converted {len(poses)} frames to NeRF format")

# 使用
convert_record3d_to_nerf('data/room_301', 'data/room_301_nerf')

4.4 训练3DGSNerfstudio

# 训练
ns-train splatfacto \
  --data data/room_301_nerf \
  --output-dir outputs/room_301 \
  --max-num-iterations 30000 \
  --viewer.websocket-port 7007

# 实时查看:打开浏览器访问 http://localhost:7007

4.5 导出模型

# 导出3DGS
ns-export gaussian-splat \
  --load-config outputs/room_301/splatfacto/config.yml \
  --output-dir exports/room_301/

# 导出Mesh
ns-export poisson \
  --load-config outputs/room_301/splatfacto/config.yml \
  --output-dir exports/room_301/mesh/ \
  --num-points 1000000 \
  --depth 10

# 导出点云
ns-export pointcloud \
  --load-config outputs/room_301/splatfacto/config.yml \
  --output-dir exports/room_301/pointcloud/ \
  --num-points 1000000

五、性能对比与选择建议

5.1 质量对比

方法 PSNR SSIM 训练时间 渲染FPS 文件大小
Nerfacto 26-28 0.85 30分钟 5-10 100MB
Splatfacto 28-30 0.88 1小时 60-100 500MB
3DGS官方 29-31 0.90 1小时 100+ 500MB
Polycam云端 25-27 0.83 20分钟 N/A 50MB

5.2 选择建议

选择Nerfstudio,如果:
  - 需要快速迭代
  - 想尝试多种方法
  - 需要实时预览
  - Python开发为主

选择3DGS官方,如果:
  - 追求最高质量
  - 需要实时渲染
  - 发表论文
  - 有强大GPU

选择Polycam,如果:
  - 非技术用户
  - 快速交付
  - 商业项目
  - 预算充足

选择Record3D,如果:
  - 需要实时流式
  - 自定义pipeline
  - 研究开发
  - 完全开源

六、集成到酒店项目的建议

6.1 推荐技术栈

数据采集:
  主方案: Polycam App(快速)
  备选: Record3D(开源)
  
位姿估计:
  自动: Polycam内置
  手动: COLMAP
  
3D重建:
  主方案: Nerfstudio Splatfacto
  高质量: 3DGS官方
  
语义标注:
  自动: RoomPlan API
  手动: YOLO-World + SAM
  
物理属性:
  自动: 基于几何推断
  手动: USD编辑器

6.2 完整工作流

graph LR
    A[iPhone采集] --> B{数据源}
    B -->|Polycam| C[云端处理]
    B -->|Record3D| D[本地处理]
    
    C --> E[下载模型]
    D --> F[COLMAP]
    F --> G[Nerfstudio]
    
    E --> H[3DGS模型]
    G --> H
    
    H --> I[RoomPlan语义]
    I --> J[场景图]
    J --> K[USD物理]
    K --> L[最终交付]

6.3 代码集成示例

# hotel_reconstruction_pipeline.py
class HotelReconstructionPipeline:
    def __init__(self, scene_id):
        self.scene_id = scene_id
        self.data_dir = Path(f'data/{scene_id}')
    
    def step1_capture(self, method='polycam'):
        """数据采集"""
        if method == 'polycam':
            print("使用Polycam App扫描...")
            print("完成后下载数据到", self.data_dir)
        elif method == 'record3d':
            capture = Record3DCapture(self.data_dir)
            capture.start()
    
    def step2_process(self):
        """数据处理"""
        # 转换为NeRF格式
        convert_to_nerf(self.data_dir, self.data_dir / 'nerf')
    
    def step3_reconstruct(self):
        """3D重建"""
        import subprocess
        subprocess.run([
            'ns-train', 'splatfacto',
            '--data', str(self.data_dir / 'nerf'),
            '--output-dir', str(self.data_dir / 'output')
        ])
    
    def step4_semantic(self):
        """语义标注"""
        # 使用RoomPlan或YOLO
        pass
    
    def step5_export(self):
        """导出最终模型"""
        subprocess.run([
            'ns-export', 'gaussian-splat',
            '--load-config', str(self.data_dir / 'output/config.yml'),
            '--output-dir', str(self.data_dir / 'final')
        ])

# 使用
pipeline = HotelReconstructionP