WWDC Quick Look 💓 By SwiftGGTeam
Discover Swift enhancements in the Vision framework

Discover Swift enhancements in the Vision framework

元の動画を見る

ハイライト

Vision は Apple のコンピュータビジョンフレームワーク。顔検出、文字認識、人体ポーズ推定、バーコードスキャンなど 31 種類の画像分析リクエストを提供。今年 Apple は Swift ネイティブ API でフレームワークを再設計。async/await、throws、Swift 6 厳密並行性チェックをサポート(01:09)。


主要内容

Vision フレームワークは Apple プラットフォームでのコンピュータビジョンの定番ツール。顔と顔特徴点(目、鼻、口)を検出。18 言語の文字認識(韓国語、スウェーデン語、中国語を含む)。人体ポーズと手の軌跡を追跡(00:24)。

旧 API には明確な問題——Objective-C ベースの completion handler 設計が Swift の現代 async パターンと相容れない。コードはネストコールバックと NSError 処理で溢れ、Swift 6 並行安全性チェック非対応(11:13)。

今年 Apple は Vision の Swift API を完全書き換え。核心ルール 3 つ:VN プレフィックス除去、completion handler 除去、async/await でコールバック置換。結果——コード量 10 行から 6 行へ。型安全、並行安全(12:11)。

API 近代化に加え、2 つの長年の痛点を解決:正規化座標変換(新 toImageCoordinates() API)、複数リクエスト同時実行時のストリーミング結果処理(performAll が AsyncStream を返す)(05:3708:22)。

さらに 2 つの新機能:画像美学スコアリング(CalculateImageAestheticsScoresRequest、写真品質と memorable 度を評価)、holistic body pose(DetectHumanBodyPoseRequestdetectsHands = true を設定し、身体と手のポーズを同時検出)(14:5115:21)。


詳細

Vision の核心概念は単純:画像に質問(request)し、答え(observation)を得る。フレームワークは 31 種類のリクエストタイプを提供——画像分類、文字認識、バーコード検出、人体ポーズ推定など(02:59)。

基本用法:バーコードスキャン

新 API の極簡スタイル——3 行:

// ([04:06](https://developer.apple.com/videos/play/wwdc2024/10163/?time=246))
let request = DetectBarcodesRequest()
let barcodeObservations = try await request.perform(on: image)
// barcodeObservations には検出された各バーコードが含まれる
  • 1 行目:リクエスト作成。VN プレフィックス不要
  • 2 行目try await で実行。結果直接返却。completion handler 不要
  • 3 行目:observation 処理。各 observation が 1 つの検出バーコード

性能向上のためバーコードタイプ指定(EAN-13 のみなど):

// ([06:38](https://developer.apple.com/videos/play/wwdc2024/10163/?time=398))
request.symbologies = [.ean13]

座標変換

Vision の座標系は正規化(0〜1)。原点は左下。SwiftUI の原点は左上。新 API は toImageCoordinates() を提供:

// ([05:42](https://developer.apple.com/videos/play/wwdc2024/10163/?time=342))
let boundingBox = observation.boundingBox
let convertedBox = boundingBox.toImageCoordinates(
    imageSize: image.size,
    origin: .upperLeft
)
  • boundingBox:Vision が返す正規化座標ボックス
  • imageSize:元画像サイズ
  • origin:出力座標原点。upperLeft は SwiftUI 等に適合

バッチリクエスト:一括実行

複数リクエスト同時実行(バーコードと文字など)は ImageRequestHandler

// ([07:36](https://developer.apple.com/videos/play/wwdc2024/10163/?time=456))
let handler = ImageRequestHandler(image: image)
let (barcodeResults, textResults) = try await handler.perform(
    DetectBarcodesRequest(),
    RecognizeTextRequest()
)
  • ImageRequestHandler:画像コンテナ。バッチリクエスト実行
  • perform:parameter pack 構文。任意数のリクエストを渡せる
  • 戻り値:リクエストごとに 1 結果。tuple でアンパック

バッチリクエスト:ストリーミング

上記方法は全リクエスト完了を待つ。各完了時に即処理する場合は performAll

// ([08:44](https://developer.apple.com/videos/play/wwdc2024/10163/?time=524))
let handler = ImageRequestHandler(image: image)
for await result in try await handler.performAll(
    DetectBarcodesRequest(),
    RecognizeTextRequest()
) {
    switch result {
    case .barcode(let observations):
        // バーコード検出が完了したらすぐに処理
        handleBarcodes(observations)
    case .text(let observations):
        // テキスト認識が完了したらすぐに処理
        handleText(observations)
    }
}
  • performAll:AsyncStream を返す。各リクエスト完了時に結果をプッシュ
  • for await:Swift Concurrency 標準ストリーム処理構文
  • switch:結果タイプで分岐

並行最適化:複数画像処理

大量画像処理時は TaskGroup で並行実行。ただしメモリ制御のため並行数制限:

// ([10:18](https://developer.apple.com/videos/play/wwdc2024/10163/?time=618))
await withTaskGroup(of: Void.self) { group in
    var imageIterator = images.makeIterator()
    var activeTasks = 0
    let maxConcurrency = 5

    while activeTasks < maxConcurrency, let nextImage = imageIterator.next() {
        group.addTask {
            await generateThumbnail(from: nextImage)
            activeTasks -= 1
        }
        activeTasks += 1
    }
}
  • withTaskGroup:Swift Concurrency タスクグループ
  • maxConcurrency:同時実行タスク数制限。Vision は約 5 を推奨——メモリ使用量削減
  • addTask:並行タスク追加。各タスクが 1 画像を処理

旧コード移行

3 ステップ移行法:

// 古い API
// ([12:32](https://developer.apple.com/videos/play/wwdc2024/10163/?time=752))
let handler = VNImageRequestHandler(image: image)
let request = VNDetectBarcodesRequest()
request completionHandler = { request, error in
    guard let observations = request.results else { return }
    // 結果を処理
}
try handler.perform([request])

// 新しい API
let request = DetectBarcodesRequest()
let observations = try await request.perform(on: image)
// 結果を処理
  • ステップ 1:VN プレフィックス除去(VNDetectBarcodesRequestDetectBarcodesRequest
  • ステップ 2:completion handler 除去。async/await 使用
  • ステップ 3VNImageRequestHandler 除去。request.perform(on:) を直接使用

画像美学スコアリング

新 API で画像品質評価:

// ([14:54](https://developer.apple.com/videos/play/wwdc2024/10163/?time=894))
let request = CalculateImageAestheticsScoresRequest()
let observation = try await request.perform(on: image)
print(observation.overallScore) // -1 から 1、値が高いほど良い
print(observation.isUtility) // true はユーティリティ画像(スクリーンショット、領収書など)を示す
  • overallScore:総合品質スコア。-1 〜 1
  • isUtility:ユーティリティ画像か(技術的には問題ないが共有価値低い)

Holistic Body Pose

身体と手のポーズを同時検出:

// ([15:38](https://developer.apple.com/videos/play/wwdc2024/10163/?time=938))
let request = DetectHumanBodyPoseRequest()
request.detectsHands = true
let observation = try await request.perform(on: image)
print(observation.leftHandObservation)  // 左手のポーズ
print(observation.rightHandObservation) // 右手のポーズ
  • detectsHands:true で返却 observation に手データを含む
  • leftHandObservation / rightHandObservation:左右手ポーズ情報の新プロパティ

重要ポイント

  • 1. 新 API へ移行:新プロジェクトは新 API を直接使用。旧プロジェクトは段階的移行。最も一般的なリクエスト(DetectBarcodesRequestRecognizeTextRequest)から。3 ステップ——プレフィックス除去、handler 除去、async/await 追加。コード削減、型安全、Swift 6 厳密並行性チェック対応。

  • 2. toImageCoordinates() で手動計算を置換:Vision の正規化座標系(左下原点)は SwiftUI(左上原点)等と不一致が多い。新座標変換 API で手動計算エラーを排除。origin: .upperLeft で大部分 UI フレームワークに適合。

  • 3. 複数リクエストシナリオで performAll 使用:複数 Vision リクエスト同時実行(バーコードと文字など)時は performAll で AsyncStream。全完了を待たず各結果を即処理。UX 向上——バーコード検出即表示、文字認識完了を待たない。

  • 4. 並行数制限でメモリ制御:大量画像処理時は TaskGroup で並行実行。ただし並行数制限(約 5 推奨)。Vision リクエストはメモリ消費大——並行制限でメモリピークによるシステム負荷を防止。

  • 5. 画像美学スコアリングでアルバム最適化CalculateImageAestheticsScoresRequest でユーザーフォトライブラリを評価——低品質写真(ぼけ、露出問題)自動フィルタ、ユーティリティ画像(スクリーンショット、レシート)識別。「厳選集」機能で memorable な写真のみ表示。


関連セッション

コメント

GitHub Issues · utterances