WWDC Quick Look 💓 By SwiftGGTeam
Meet Object Capture for iOS

Meet Object Capture for iOS

观看原视频

Highlight

Object Capture 从 macOS 专属功能变成了 iOS 上的完整端到端体验:用户用 iPhone 或 iPad 扫描物体,系统自动拍摄、实时引导、在设备端重建,几分钟内输出 USDZ 格式的 3D 模型,LiDAR 支持让低纹理物体也能获得高质量重建。

核心内容

以前要做 3D 物体扫描,流程很繁琐:用 iPhone 拍一堆照片,传到 Mac,用 Object Capture API 重建模型。整个过程跨设备、耗时长,普通用户很难上手。

WWDC23 把这一切搬到了 iOS 上。现在拍摄和重建都在同一台设备完成,Apple 还提供了完整的 Sample App 作为起点。

LiDAR 让低纹理物体也能扫描

03:02)Object Capture 之前对纹理丰富的物体效果最好——比如花纹复杂的花瓶、雕刻精细的木雕。但对低纹理物体(纯色椅子、光滑桌面)效果很差,因为纯视觉算法难以从单调表面提取特征点。

今年加入 LiDAR 点云数据后,情况变了。扫描时系统同时采集 RGB 照片和 LiDAR 点云,两者融合重建。RGB 负责颜色和精细纹理,LiDAR 负责几何形状和深度信息。一把纯色的椅子,以前重建出来可能缺面少角,现在能恢复完整的 3D 形状。

当然,有些物体仍然不适合扫描:反光表面、透明材质、极细结构。这些限制暂时还在。

引导式拍摄

04:36)手动拍照很容易出问题:角度不够、光线太差、手抖模糊。Guided Capture 把这些麻烦自动化了。

系统自动选择拍摄时机:当画面清晰度、曝光、构图都达标时才按下”快门”。用户只需要拿着设备绕物体转圈,系统会在合适的角度自动采集。

拍摄转盘(Capture Dial)是核心 UI 元素。它显示物体各个角度已经被覆盖的程度,引导用户把转盘填满。遗漏的区域用颜色标识,用户一眼就知道还需要扫哪里。

实时反馈覆盖常见错误场景:

  • 光线不足:提醒调整照明,建议使用漫反射光源
  • 移动太快:自动暂停拍摄,提醒放慢速度
  • 距离不当:太远或太近都会提示
  • 物体出框:箭头指示调整方向

翻转策略

06:45)要获得完整模型,通常需要翻转物体扫描底面。但不是所有物体都适合翻转:

  • 刚性物体可以翻转,可变形物体不建议
  • 纹理丰富的物体适合翻转,对称或重复纹理的物体不适合
  • 低纹理物体翻转后系统难以对齐不同扫描段

系统提供 API 判断物体是否有足够纹理支持翻转扫描。翻转时建议扫描三个方向,每个方向间保持图像重叠。

不能翻转的物体,建议从三个不同高度拍摄。

详细内容

状态机驱动的拍摄流程

09:30)Object Capture 用状态机管理整个拍摄流程:

initializing → ready → detecting → capturing → finishing → completed

每个状态对应不同的 UI 和操作:

  • initializing:session 刚创建
  • ready:显示相机画面,等待用户选择物体
  • detecting:自动检测物体边界框
  • capturing:自动拍摄,显示拍摄转盘
  • finishing:保存数据
  • completed:可以拆除 session,进入重建阶段

出错时进入 failed 状态,需要重新创建 session。

代码实现

10:03)创建 session:

import RealityKit
import SwiftUI

var session = ObjectCaptureSession()

10:25)启动 session:

var configuration = ObjectCaptureSession.Configuration()
configuration.checkpointDirectory = getDocumentsDir().appendingPathComponent("Snapshots/")

session.start(
    imagesDirectory: getDocumentsDir().appendingPathComponent("Images/"),
    configuration: configuration
)

关键点:

  • imagesDirectory 存放拍摄的照片
  • checkpointDirectory 存放检查点数据,加速重建
  • session 启动后进入 ready 状态

10:50)创建拍摄视图:

import RealityKit
import SwiftUI

struct CapturePrimaryView: View {
    var body: some View {
        ZStack {
            ObjectCaptureView(session: session)
        }
    }
}

关键点:

  • ObjectCaptureView 自动根据 session 状态显示对应的 UI
  • 不包含任何 2D 文字或按钮,方便自定义外观
  • 可以嵌入到现有应用的 SwiftUI 界面中

11:20)状态切换的 UI 控制:

var body: some View {
    ZStack {
        ObjectCaptureView(session: session)

        if case .ready = session.state {
            CreateButton(label: "Continue") {
                session.startDetecting()
            }
        } else if case .detecting = session.state {
            CreateButton(label: "Start Capture") {
                session.startCapturing()
            }
        }
    }
}

关键点:

  • ready 状态显示 Continue 按钮,调用 startDetecting()
  • detecting 状态显示 Start Capture 按钮,调用 startCapturing()
  • 也可以提供 Reset 按钮回到 ready 状态重新选择物体

12:50)完成一轮扫描后:

var body: some View {
    if session.userCompletedScanPass {
        VStack {
            CreateButton(label: "Finish") {
                session.finish()
            }
        }
    } else {
        ZStack {
            ObjectCaptureView(session: session)
        }
    }
}

关键点:

  • userCompletedScanPass 表示拍摄转盘已填满
  • 可以 Finish 结束拍摄,或继续下一轮扫描
  • 建议完成三轮扫描获得最佳效果

点云预览

15:00)可以用 ObjectCapturePointCloudView 预览已扫描的部分:

var body: some View {
    if session.userCompletedScanPass {
        VStack {
            ObjectCapturePointCloudView(session: session)
            CreateButton(label: "Finish") {
                session.finish()
            }
        }
    } else {
        ZStack {
            ObjectCaptureView(session: session)
        }
    }
}

关键点:

  • 点云视图会暂停拍摄,让用户交互式查看
  • 可以全屏显示,也可以和按钮组合使用
  • 帮助用户判断扫描是否完整

重建 API

15:50)拍摄完成后,用 PhotogrammetrySession 重建模型:

var body: some View {
    ReconstructionProgressView()
        .task {
            var configuration = PhotogrammetrySession.Configuration()
            configuration.checkpointDirectory = getDocumentsDir()
                .appendingPathComponent("Snapshots/")

            let session = try PhotogrammetrySession(
                input: getDocumentsDir().appendingPathComponent("Images/"),
                configuration: configuration
            )

            try session.process(requests: [
                .modelFile(url: getDocumentsDir().appendingPathComponent("model.usdz"))
            ])

            for try await output in session.outputs {
                switch output {
                case .processingComplete:
                    handleComplete()
                // 处理其他输出消息
                default:
                    break
                }
            }
        }
}

关键点:

  • 使用与 macOS 相同的异步 API
  • iOS 只支持 reduced 细节级别
  • 输出包含 diffuse、ambient occlusion 和 normal 贴图
  • 重建在设备端完成,不需要网络或 Mac

为 Mac 重建采集更多数据

17:02)如果想在 Mac 上获得更高质量的重建,可以启用超量采集:

var configuration = ObjectCaptureSession.Configuration()
configuration.isOverCaptureEnabled = true

session.start(
    imagesDirectory: getDocumentsDir().appendingPathComponent("Images/"),
    configuration: configuration
)

关键点:

  • isOverCaptureEnabled = true 允许采集比 iOS 重建所需更多的照片
  • 额外的照片存储在 Images 文件夹中
  • 可以导入到 Reality Composer Pro 在 Mac 上重建
  • 不需要写代码,直接在 Reality Composer Pro 中导入即可

新重建特性

18:40)今年重建 API 新增两个功能:

Pose 输出:获取每张照片的相机位姿

try session.process(requests: [
    .poses,
    .modelFile(url: modelURL)
])

for try await output in session.outputs {
    switch output {
    case .poses(let poses):
        handlePoses(poses)
    case .processingComplete:
        handleComplete()
    }
}

关键点:

  • 每个 pose 包含相机的位置和朝向
  • 在模型生成前就会返回
  • 可用于自定义处理流程

自定义细节级别(macOS):可以控制网格简化程度、纹理分辨率、格式和包含哪些贴图。

核心启发

1. 做一个电商商品 3D 展示工具

  • 做什么:让商家用 iPhone 扫描商品,自动生成 3D 模型嵌入到商品详情页
  • 为什么值得做:Object Capture 让 3D 建模零门槛,不需要专业设备和技能
  • 怎么开始:基于 Sample App 修改 UI,扫描后上传 USDZ 到服务器,在网页中用 Quick Look 展示

2. 做一个 AR 家具摆放应用

  • 做什么:用户扫描自己的家具,在 AR 中预览摆放效果
  • 为什么值得做:LiDAR 支持让低纹理的家具也能获得不错的模型质量
  • 怎么开始:集成 Object Capture 扫描流程,用 RealityKit 显示模型,支持缩放和旋转

3. 做一个 3D 资产管理系统

  • 做什么:为设计师和开发者管理 3D 模型库,支持扫描、标注、分类、导出
  • 为什么值得做:扫描 + 重建 + 预览全在设备端完成,不需要后端
  • 怎么开始:用 SwiftData 存储模型元数据,用 Object Capture 扫描,用 Quick Look 预览

4. 做一个教育类的 3D 博物馆应用

  • 做什么:学生扫描博物馆展品,在应用中查看 3D 模型并学习相关知识
  • 为什么值得做:Guided Capture 的引导让非专业用户也能获得高质量扫描
  • 怎么开始:封装 Object Capture 为简单流程,扫描后关联教育内容,支持 AR 查看

关联 Session

评论

GitHub Issues · utterances