WWDC Quick Look 💓 By SwiftGGTeam
Meet Object Capture for iOS

Meet Object Capture for iOS

元の動画を見る

ハイライト

オブジェクト キャプチャは、macOS 専用の機能から iOS での完全なエンドツーエンド エクスペリエンスに変更されました。ユーザーが iPhone または iPad でオブジェクトをスキャンすると、システムが自動的にキャプチャし、リアルタイムでガイドし、デバイス側で再構築し、数分以内に USDZ 形式で 3D モデルを出力します。 LiDAR のサポートにより、低テクスチャのオブジェクトを高品質で再構築できます。

主要内容

以前は、3D オブジェクトをスキャンするプロセスは非常に面倒でした。iPhone で大量の写真を撮り、Mac に転送し、Object Capture API を使用してモデルを再構築しました。プロセス全体はクロスデバイスで時間がかかるため、一般のユーザーが始めるのは困難です。

WWDC23 では、すべてが iOS に提​​供されます。撮影と再構成の両方が同じデバイス上で行われるようになったことで、Apple は出発点として完全なサンプル アプリも提供しています。

LiDAR により、テクスチャの低いオブジェクトのスキャンが可能になります

(03:02) オブジェクト キャプチャは、これまで、複雑なパターンを持つ花瓶や細かく刻まれた木彫りなど、豊かなテクスチャを持つオブジェクトに最適に機能していました。ただし、純粋に視覚的なアルゴリズムでは単調な表面から特徴点を抽出することが難しいため、テクスチャの低いオブジェクト (単色の椅子、滑らかなテーブルトップ) では効果が不十分です。

今年は、LiDAR 点群データが追加されたことで状況が変わりました。スキャン中に、システムは RGB 写真と LiDAR 点群を同時に収集し、この 2 つを融合して再構築します。 RGB は色と細かいテクスチャを担当し、LiDAR はジオメトリと深度情報を担当します。面や角が欠けて再構築された可能性がある単色の椅子を、完全な 3D 形状に復元できるようになりました。

もちろん、反射面、透明な素材、非常に微細な構造など、一部のオブジェクトは依然としてスキャンに適していません。これらの制限は今のところ引き続き適用されます。

ガイド付き撮影

(04:36) マニュアル撮影では、角度が不十分、光が弱すぎる、手が震えてぼやけるなどの問題が発生しがちです。 Guided Capture はこれらの面倒な作業を自動化します。

システムは撮影時間を自動的に選択します。画像の鮮明さ、露出、構図がすべて標準に達したら「シャッター」を押します。ユーザーはデバイスを持って物体の周りを一周するだけで、システムが自動的に適切な角度で物体を収集します。

キャプチャ ダイヤルは、核となる UI 要素です。オブジェクトがどの程度カバーされているかをあらゆる角度から表示し、ユーザーがターンテーブルを埋めるようにガイドします。欠落した領域は色分けされているため、ユーザーはどこをまだスキャンする必要があるか一目でわかります。

リアルタイムのフィードバックは、一般的なエラー シナリオをカバーします。

  • 光が不十分: 照明を調整するようリマインダーを送ります。拡散光源の使用をお勧めします。
  • 動きが速すぎる: 自動的に撮影を一時停止し、速度を落とすよう通知します。
  • 不適切な距離: 遠すぎるか近すぎるとプロンプトが表示されます
  • フレーム外のオブジェクト: 矢印は調整方向を示します

反転戦略

(06:45) 完全なモデルを取得するには、通常、オブジェクトを反転して底面をスキャンする必要があります。ただし、すべてのオブジェクトが反転に適しているわけではありません。

  • 硬いオブジェクトは反転できますが、変形可能なオブジェクトは推奨されません
  • 豊富なテクスチャを持つオブジェクトは反転に適していますが、対称または繰り返しテクスチャを持つオブジェクトは適していません
  • 低テクスチャ オブジェクト 反転後、システムは異なるスキャン セグメントを位置合わせするのが困難になります

このシステムは、オブジェクトにフリップ スキャンをサポートするのに十分なテクスチャがあるかどうかを判断する API を提供します。反転する場合は、3 方向にスキャンし、各方向で画像が重なるようにすることをお勧めします。

反転できないオブジェクトの場合は、3 つの異なる高さから撮影することをお勧めします。

詳細

ステートマシン駆動の撮影プロセス

(09:30) オブジェクト キャプチャはステート マシンを使用して撮影プロセス全体を管理します。

initializing → ready → detecting → capturing → finishing → completed

各状態は、異なる UI と操作に対応します。

  • 初期化中: セッションが作成されたばかりです
  • 準備完了: カメラ画面を表示し、ユーザーがオブジェクトを選択するのを待ちます
  • 検出: オブジェクトの境界ボックスを自動的に検出します。
  • キャプチャ: 自動的にキャプチャし、撮影ダイヤルを表示します
  • 仕上げ: データを保存します
  • 完了: セッションは解体され、再構築フェーズに入ることができます。

エラーが発生すると、失敗 状態になり、セッションを再作成する必要があります。

コードの実装

(10:03) セッションを作成します。

import RealityKit
import SwiftUI

var session = ObjectCaptureSession()

(10:25) セッションを開始します:

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

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

キーポイント:

  • imagesDirectory撮った写真を保存する -checkpointDirectory再構築を高速化するためにチェックポイント データを保存する
  • セッションが開始されると、準備完了状態になります。

(10:50) 撮影ビューを作成します。

import RealityKit
import SwiftUI

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

キーポイント:

  • ObjectCaptureViewセッションのステータスに応じて、対応する 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()
            }
        }
    }
}

キーポイント:

  • 準備完了ステータスでは [続行] ボタンが表示され、呼び出しが行われます。startDetecting()- 検出ステータスが表示され、「キャプチャ開始」ボタンを呼び出します。startCapturing()- 準備完了状態に戻ってオブジェクトを再選択するための [リセット] ボタンを提供することもできます。

(12:50) 一連のスキャンが完了したら:

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

キーポイント:

  • userCompletedScanPass撮影ダイヤルがフルであることを示します
  • 「終了」をクリックして撮影を終了するか、次のスキャンに進むことができます。
  • 最良の結果を得るには、3 ラウンドのスキャンを完了することをお勧めします。

点群プレビュー

(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 は低減された詳細レベルのみをサポートします
  • 出力には拡散マップ、アンビエント オクルージョン マップ、法線マップが含まれます
  • 再構築はデバイス上で行われ、ネットワークや Mac は必要ありません

Mac の再構築のためにさらにデータを収集する

(17:02) Mac でより高品質の再構築が必要な場合は、過剰取得を有効にすることができます。

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

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

キーポイント:

  • isOverCaptureEnabled = trueiOS の再構築に必要な以上の写真を収集できるようにする
  • 追加の写真は画像フォルダーに保存されます
  • Mac 上で再構築するために Reality Composer Pro にインポート可能
  • コードを記述する必要はなく、Reality Composer Pro に直接インポートするだけです

新しい再構築機能

(18:40) 今年の API の再構築により、2 つの新しい関数が追加されました。

ポーズ出力: 各写真のカメラポーズを取得します。

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()
    }
}

キーポイント:

  • 各ポーズにはカメラの位置と方向が含まれています
  • モデルが生成される前に返されます
  • 処理フローのカスタマイズに使用可能

カスタム詳細レベル (macOS): メッシュの単純化、テクスチャ解像度、形式、およびどのマップが含まれるかを制御します。

重要ポイント

1. eコマース商品の3D表示ツールを作成

  • 対処法: 販売者が iPhone で商品をスキャンし、3D モデルを自動的に生成して商品詳細ページに埋め込むことを許可します。
  • 実行する価値がある理由: Object Capture では、3D モデリングをゼロしきい値で行うことができ、専門的な機器やスキルは必要ありません。
  • 開始方法: サンプル アプリに基づいて UI を変更し、スキャン後に USDZ をサーバーにアップロードし、Quick Look を使用して Web ページに表示します。

2. AR家具配置アプリを作る

  • やるべきこと: ユーザーは自分の家具をスキャンし、AR で配置をプレビューします。
  • 実行する価値がある理由: LiDAR は、良好なモデル品質を得るために低質感の家具をサポートします
  • 開始方法: オブジェクト キャプチャ スキャン プロセスを統合し、RealityKit を使用してモデルを表示し、スケーリングと回転をサポートします。

3. 3D アセット管理システムを作成します

  • 作業内容: デザイナーと開発者向けの 3D モデル ライブラリを管理し、スキャン、注釈、分類、エクスポートをサポートします。
  • 実行する価値がある理由: スキャン + 再構築 + プレビューはすべてデバイス側で実行され、バックエンドは必要ありません
  • 開始方法: SwiftData を使用してモデルのメタデータを保存し、オブジェクト キャプチャを使用してスキャンし、Quick Look を使用してプレビューします

4.教育用 3D 博物館アプリケーションを作成する

  • やるべきこと: 学生は博物館の展示物をスキャンし、3D モデルを表示し、アプリでそれらについて学びます
  • 価値がある理由: Guided Capture のガイダンスにより、専門家以外のユーザーでも高品質のスキャンを取得できます。
  • 開始方法: オブジェクト キャプチャを単純なプロセスにカプセル化し、教育コンテンツをスキャンに関連付け、AR 表示をサポートします。

関連セッション

コメント

GitHub Issues · utterances