mcpField
V
vision-framework

vision-framework

github.com/dpearson2699開発1.2k3.9k 回インストール13 週間前に更新
リポジトリ

vision-framework について

Apple プラットフォーム開発者向けに、画像や動画のオンデバイス画像認識を扱う Vision スキルです。最新の非同期リクエスト、旧 API へのフォールバック、VisionKit と Core ML の連携を解説します。

主な機能

  1. 01テキスト、顔、バーコードの認識
  2. 02構造化された文書内容の読み取り
  3. 03セグメンテーションマスク生成と物体追跡
  4. 04人体、手、動物のポーズ検出
  5. 05Vision による Core ML モデルの実行
  6. 06VisionKit によるライブテキスト・バーコードスキャン

活用シーン

  1. 01画像からテキストやバーコード内容を抽出
  2. 02文書をスキャンしてレイアウトを解析
  3. 03動画フレーム間で物体を追跡
  4. 04画像効果向けの人物マスクを生成
  5. 05カメラ映像内のテキストやバーコードをスキャン

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/dpearson2699/swift-ios-skills --skill vision-framework

インストール後、Claude Code で/vision-frameworkを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
vision-requests.md
visionkit-scanner.md

詳細

Vision Framework

デバイス上のコンピュータービジョンを使用して、画像や動画からテキスト、顔、バーコード、オブジェクト、身体の姿勢を検出します。最新の iOS 18 以降のリクエスト API を優先し、デプロイメントターゲットで必要な場合にのみレガシーリファレンスを読み込んでください。

完全なコードパターンについては、references/vision-requests.md を参照してください。また、DataScannerViewController との統合については、references/visionkit-scanner.md を参照してください。

Contents

2 世代の API

Vision には、異なる 2 つの API レイヤーがあります。新しいコードでは最新の API を優先してください。Swift ネイティブのリクエストタイプと try await request.perform(on:) を使用します。VN*、VNImageRequestHandler、VNSequenceRequestHandler、完了ハンドラー、レガシーの CGRect ヘルパーは、明示的なレガシー用フォールバックセクションまたはファイル内に限定してください。

観点最新(iOS 18+)レガシー
パターンlet result = try await request.perform(on: image)VNImageRequestHandler + 完了ハンドラー
リクエストタイプSwift の型 — 構造体とクラス(RecognizeTextRequest、DetectFaceRectanglesRequest)Objective-C のクラス(VNRecognizeTextRequest、VNDetectFaceRectanglesRequest)
並行処理ネイティブの async/await完了ハンドラーまたは同期的な perform
観測結果型付きの戻り値[Any] から results をキャスト
対応状況iOS 18+ / macOS 15+iOS 11+

最新の API は ImageProcessingRequest プロトコルを使用します。各リクエストタイプには、CGImage、CIImage、CVPixelBuffer、CMSampleBuffer、Data、URL を受け取る perform(on:orientation:) メソッドがあります。ほとんどのリクエストは構造体です。GeneratePersonSegmentationRequest、TrackObjectRequest、TrackRectangleRequest、DetectTrajectoriesRequest などの状態を持つリクエストは final クラスです。

リクエストのパターン(最新 API)

すべての最新の Vision リクエストは、同じパターンに従います。リクエストを作成し、perform(on:) を呼び出して、型付きの結果を処理します。

import Vision

func recognizeText(in image: CGImage) async throws -> [String] {
    var request = RecognizeTextRequest()
    request.recognitionLevel = .accurate
    request.recognitionLanguages = [Locale.Language(identifier: "en-US")]

    let observations = try await request.perform(on: image)
    return observations.compactMap { observation in
        observation.topCandidates(1).first?.string
    }
}
レガシーパターン(iOS 18 より前)

iOS 18 より前のターゲットでは、対応する VNRequest と VNImageRequestHandler または VNSequenceRequestHandler を使用してください。完全なレガシーのリクエストとハンドラーのパターンについては、references/vision-requests.md を読み込んでください。

テキスト認識(OCR)

最新:RecognizeTextRequest(iOS 18+)
var request = RecognizeTextRequest()
request.recognitionLevel = .accurate       // .fast for real-time
request.recognitionLanguages = [
    Locale.Language(identifier: "en-US"),
    Locale.Language(identifier: "fr-FR"),
]
request.usesLanguageCorrection = true
request.customWords = ["SwiftUI", "Xcode"] // domain-specific terms

let observations = try await request.perform(on: cgImage)
for observation in observations {
    guard let candidate = observation.topCandidates(1).first else { continue }
    let text = candidate.string
    let confidence = candidate.confidence  // 0.0 ... 1.0
    let bounds = observation.boundingBox   // NormalizedRect
}
レガシー:VNRecognizeTextRequest

レガシーのリクエストでは、文字列による言語識別子と、リファレンスに記載されているハンドラーパターンを使用します。どちらの世代も、高精度と高速の認識レベルに対応しています。

顔検出

顔の矩形、ランドマーク(目、鼻、口)、撮影品質を検出します。

// Modern API
let faceRequest = DetectFaceRectanglesRequest()
let faces = try await faceRequest.perform(on: cgImage)

for face in faces {
    let boundingBox = face.boundingBox   // NormalizedRect
    let roll = face.roll                 // Measurement<UnitAngle>
    let yaw = face.yaw                  // Measurement<UnitAngle>
}

// Landmarks (eyes, nose, mouth contours)
var landmarkRequest = DetectFaceLandmarksRequest()
let landmarkFaces = try await landmarkRequest.perform(on: cgImage)
for face in landmarkFaces {
    let landmarks = face.landmarks
    let leftEye = landmarks?.leftEye.points
    let nose = landmarks?.nose.points
}
座標系

Vision は、原点が左下にある正規化座標系を使用します。表示する前に UIKit(原点が左上)用に変換してください。

import Vision

func imageRectForDisplay(_ rect: NormalizedRect, imageSize: CGSize) -> CGRect {
    rect.toImageCoordinates(imageSize, origin: .upperLeft)
}

バーコード検出

QR コードを含む 1D および 2D バーコードを検出します。

var request = DetectBarcodesRequest()
let symbologies: [BarcodeSymbology] = [.qr, .ean13, .code128, .pdf417]
request.symbologies = symbologies

let barcodes = try await request.perform(on: cgImage)
for barcode in barcodes {
    let payload = barcode.payloadString          // decoded content
    let symbology = barcode.symbology            // .qr, .ean13, etc.
    let bounds = barcode.boundingBox             // NormalizedRect
}

まずローカル値に型を指定してから、リクエストのプロパティを個別に設定してください。

ドキュメントスキャン(iOS 26+)

RecognizeDocumentsRequest は、基本的な OCR を超えたレイアウト理解を備えた、構造化ドキュメント読み取り機能を提供します。段落、表、リスト、バーコードを格納するネストされた Container 構造を持つ DocumentObservation オブジェクトを返します。現在、Vision は画像ごとに 1 つのドキュメント観測結果を返します。

var request = RecognizeDocumentsRequest()
let documents = try await request.perform(on: cgImage)

for observation in documents {
    let container = observation.document

    // Full text content
    let fullText = container.text

    // Structured access to paragraphs
    for paragraph in container.paragraphs {
        let paragraphText = paragraph.text
    }

    // Tables and lists
    for table in container.tables { /* structured table data */ }
    for list in container.lists { /* structured list data */ }

    // Embedded barcodes detected within the document
    for barcode in container.barcodes { /* barcode data */ }

    // Document title if detected
    if let title = container.title { print(title) }
}

よりシンプルなドキュメントカメラのスキャンには、自動撮影、パースペクティブ補正、複数ページのスキャンに対応した全画面カメラ UI を提供する VisionKit の VNDocumentCameraViewController を使用してください。

画像のセグメンテーション

最新:GeneratePersonSegmentationRequest(iOS 18+)
var request = GeneratePersonSegmentationRequest()
request.qualityLevel = .accurate  // .balanced, .fast

let mask = try await request.perform(on: cgImage)
// mask is a PixelBufferObservation with a pixelBuffer property
let maskBuffer = mask.pixelBuffer
// Apply mask using Core Image: CIFilter.blendWithMask()
レガシー:VNGeneratePersonSegmentationRequest

古いターゲットでは、VNGeneratePersonSegmentationRequest は最初のピクセルバッファ観測結果を通じてマスクを公開します。リファレンスのハンドラーとマスク合成の手順を使用してください。

品質レベル:

  • .accurate -- 最高品質、最も低速(約1秒)、フル解像度
  • .balanced -- 良好な品質、中程度の速度(約100ms)、960x540
  • .fast -- 最低品質、最速(約10ms)、256x144、リアルタイムに適しています
インスタンスセグメンテーション(iOS 18+)

個別のエフェクトを適用できるよう、人ごとにマスクを分離します。

// Modern API (iOS 18+)
let request = GeneratePersonInstanceMaskRequest()
let observation = try await request.perform(on: cgImage)
let indices = observation.allInstances

for index in indices {
    let mask = try observation.generateMask(for: IndexSet(integer: index))
    // mask is a CVPixelBuffer with only this person visible
}
// Legacy API (iOS 17+)
let request = VNGeneratePersonInstanceMaskRequest()
let handler = VNImageRequestHandler(cgImage: cgImage)
try handler.perform([request])

guard let result = request.results?.first else { return }
let indices = result.allInstances
for index in indices {
    let instanceMask = try result.generateMaskedImage(
        ofInstances: IndexSet(integer: index),
        from: handler,
        croppedToInstancesExtent: false
    )
}

マスク合成と Core Image フィルターの統合パターンについては、references/vision-requests.md を参照してください。

オブジェクトトラッキング

最新:TrackObjectRequest(iOS 18+)

TrackObjectRequest は、フレーム間でトラッキングのコンテキストを維持するステートフルなリクエストです。

// Initialize with a detected object's bounding box
let initialObservation = DetectedObjectObservation(boundingBox: detectedBox)
let request = TrackObjectRequest(detectedObject: initialObservation)

for pixelBuffer in framePixelBuffers {
    let results = try await request.perform(on: pixelBuffer)
    if let tracked = results.first {
        let updatedBounds = tracked.boundingBox  // NormalizedRect
    }
}

最新の TrackObjectRequest には trackingLevel や qualityLevel はありません。

レガシー:VNTrackObjectRequest

古いターゲットでは、保持した VNSequenceRequestHandler を 1 つ使用して VNTrackObjectRequest を実行し、各結果を次の入力観測結果として渡します。リファレンスにはループ全体が記載されています。

その他のリクエストタイプ

Vision が提供するその他のリクエストについては、references/vision-requests.md を参照してください。

リクエスト用途
ClassifyImageRequestシーンの内容(屋外、食べ物、動物など)を分類します
GenerateAttentionBasedSaliencyImageRequest視聴者の注意が集まる場所を示す、単一の SaliencyImageObservation を返します
GenerateObjectnessBasedSaliencyImageRequestオブジェクトらしい領域を示す、単一の SaliencyImageObservation を返します
GenerateForegroundInstanceMaskRequest前景オブジェクトをセグメンテーションします(人物に限定されません)
DetectRectanglesRequest長方形の形状(ドキュメント、カード、画面)を検出します
DetectHorizonRequest写真の自動水平補正用に地平線の角度を検出します
DetectHumanBodyPoseRequest身体の関節(肩、肘、膝)を検出します
DetectHumanBodyPose3DRequest3D 人体姿勢を推定します
DetectHumanHandPoseRequest手の関節と指の位置を検出します
DetectAnimalBodyPoseRequest動物の身体の関節位置を検出します
DetectFaceCaptureQualityRequest写真選択用に顔の撮影品質をスコア化します(0~1)
TrackRectangleRequest動画フレーム間で長方形のオブジェクトを追跡します
TrackOpticalFlowRequest動画フレーム間のオプティカルフローを検出します
DetectTrajectoriesRequest動画内のオブジェクトの軌跡を検出します

上記の最新のリクエストタイプはすべて、iOS 18+ / macOS 15+ に対応しています。

Core ML の統合

Vision を通じてカスタム Core ML モデルを実行し、画像を自動的に前処理します。

Vision は、すでに準備されたモデルを CoreMLRequest または VNCoreMLRequest で実行します。変換、プロファイリング、パッケージ化、ライフサイクルに関する判断は coreml に任せてください。

import CoreML
import Vision

// Modern API (iOS 18+): CoreMLRequest takes a CoreMLModelContainer.
let model = try MLModel(contentsOf: modelURL)
let container = try CoreMLModelContainer(model: model, featureProvider: nil)
let request = CoreMLRequest(model: container)
let results = try await request.perform(on: cgImage)

// Classification model
if let classification = results.first as? ClassificationObservation {
    let label = classification.identifier
    let confidence = classification.confidence
}

CoreMLModelContainer は、CoreMLRequest 用の iOS 18+ 向け公開 Vision コンテナーです。MLModel を読み込み、CoreMLModelContainer(model:featureProvider:) でラップしてから、そのコンテナーを CoreMLRequest(model:) に渡します。Vision を通じた Core ML の結果マッピングを確認する際は、分類器は ClassificationObservation を、画像出力は PixelBufferObservation を、汎用予測器は CoreMLFeatureValueObservation を生成することに注意してください。

// Legacy API
let vnModel = try VNCoreMLModel(for: model)
let request = VNCoreMLRequest(model: vnModel) { request, error in
    guard let results = request.results as? [VNClassificationObservation] else { return }
    let topResult = results.first
}
let handler = VNImageRequestHandler(cgImage: cgImage)
try handler.perform([request])

VisionKit:DataScannerViewController

DataScannerViewController は、テキストとバーコードをリアルタイムでスキャンするカメラ機能を提供します。references/visionkit-scanner.md を参照してください。VisionKit は VNBarcodeSymbology を使用します。最新の DetectBarcodesRequest は BarcodeSymbology を使用します。

クイックスタート
import AVFoundation
import Vision
import VisionKit

@MainActor
func presentScanner() async {
    // Add NSCameraUsageDescription before requesting camera access.
    guard await AVCaptureDevice.requestAccess(for: .video) else { return }
    guard DataScannerViewController.isSupported,
          DataScannerViewController.isAvailable else { return }

    let scannerSymbologies: [VNBarcodeSymbology] = [.qr, .ean13]
    let scanner = DataScannerViewController(
        recognizedDataTypes: [
            .text(languages: ["en"]),
            .barcode(symbologies: scannerSymbologies)
        ],
        qualityLevel: .balanced,
        recognizesMultipleItems: true,
        isHighFrameRateTrackingEnabled: true,
        isHighlightingEnabled: true
    )
    scanner.delegate = self
    present(scanner, animated: true) {
        // Start scanning after presentation, on the main actor.
        try? scanner.startScanning()
    }
}
SwiftUI との統合

DataScannerViewController を UIViewControllerRepresentable でラップし、updateUIViewController で Task { @MainActor in try? controller.startScanning() } を使用して開始します。references/visionkit-scanner.md を参照してください。

よくある間違い

避けること: iOS 18 以降を対象とする新しいプロジェクトで、従来の VNImageRequestHandler API を使用すること。 推奨: perform(on:) と async/await を使う、最新の Swift ネイティブのリクエストを使用してください。 理由: 最新の API は型安全性が高く、Swift の並行処理をより適切にサポートし、エラー処理も簡潔です。

避けること: バウンディングボックスを描画する前に、正規化座標を変換し忘れること。 推奨: 最新のオブザベーションには NormalizedRect.toImageCoordinates(_:origin:) を、従来の CGRect オブザベーションには VNImageRectForNormalizedRect(_:_:_:) を使用してください。 理由: Vision は左下を原点とする正規化座標(0...1)を使用しますが、UIKit は左上を原点とするポイントを使用します。

避けること: Vision のリクエストをメインスレッドで実行すること。 推奨: バックグラウンドスレッドでリクエストを実行するか、デタッチされたタスクから async/await を使用してください。 理由: 画像解析は CPU/GPU を大量に使用する処理であり、メインアクターで実行すると UI がブロックされます。

避けること: リアルタイムのカメラ映像に .accurate 認識レベルを使用すること。 推奨: ライブ映像には .fast を、静止画像やオフライン処理には .accurate を使用してください。 理由: 高精度認識は 30fps の映像には遅すぎます。高速認識は品質と引き換えに速度を向上させます。

避けること: Vision のすべてのオブザベーションが同じプロパティを持つと想定すること。 推奨: 共通ヘルパーを作成する前に、各オブザベーション型のバウンディングボックス、信頼度、ペイロード、マスク、角度の各フィールドを確認してください。 理由: 最新の Vision は型付けされたオブザベーションを返し、結果の形状はリクエストによって異なります。

避けること: 各ビデオフレームで状態を保持するトラッキングリクエストを作り直すこと。 推奨: 同じ最新の TrackObjectRequest インスタンスを保持するか、従来のトラッキングリクエストでは VNSequenceRequestHandler を使用してください。 理由: トラッキングはフレーム間の時間的なコンテキストに依存します。

避けること: QR コードだけが必要なときに、すべてのバーコードシンボル体系をリクエストすること。 推奨: リクエストには必要なシンボル体系のみを指定してください。 理由: シンボル体系が少ないほど検出が速くなり、誤検出も減ります。

避けること: すべてのデバイスで DataScannerViewController が利用できると想定すること。 推奨: 表示する前に、isSupported(ハードウェア)と isAvailable(ユーザーの許可)の両方を確認してください。 理由: A12 以降のチップが必要です。isAvailable はカメラへのアクセス許可も確認します。

レビューチェックリスト

  • 古いデプロイ対象をサポートする場合を除き、最新の Vision API(iOS 18 以降)を使用している
  • Vision のリクエストがメインスレッド以外で実行されている(async/await またはバックグラウンドキュー)
  • UI に表示する前に正規化座標が変換されている
  • 品質の低いオブザベーションを除外するため、信頼度のしきい値が適用されている
  • 認識レベルが用途に適している(動画には .fast、静止画には .accurate)
  • 入力言語がわかっている場合、テキスト認識に言語ヒントが設定されている
  • バーコードのシンボル体系が必要なものだけに限定されている
  • 表示前に DataScannerViewController の利用可否が確認されている
  • VisionKit のために、Info.plist にカメラ使用の説明(NSCameraUsageDescription)が設定されている
  • 表示前に VisionKit のカメラアクセスがリクエストされ、表示後にスキャンが開始されている
  • 人物セグメンテーションの品質レベルが用途に適している
  • 状態を保持するトラッキングリクエストまたは VNSequenceRequestHandler がビデオフレーム間で保持されている
  • エラー処理でリクエストの失敗と結果が空の場合に対応している

References

コメント