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. 05通过 Vision 运行 Core ML 模型
  6. 06使用 VisionKit 实时扫描文本和条码

适用场景

  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。

目录

两代 API

Vision 有两个截然不同的 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)ObjC 类(VNRecognizeTextRequest、VNDetectFaceRectanglesRequest)
并发原生 async/await完成处理程序或同步 perform
观察结果类型化返回值将 results 从 [Any] 转换为所需类型
可用性iOS 18+ / macOS 15+iOS 11+

现代 API 使用 ImageProcessingRequest 协议。每种请求类型都有一个 perform(on:orientation:) 方法,可接受 CGImage、CIImage、 CVPixelBuffer、CMSampleBuffer、Data 或 URL。大多数请求都是 结构体;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

旧版请求使用字符串形式的语言标识符,并采用参考资料中的处理程序模式;两代 API 均支持准确和快速识别级别。

人脸检测

检测人脸矩形、面部特征点(眼睛、鼻子、嘴巴)和拍摄质量。

// 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 码。

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 的版面理解能力。它会返回 DocumentObservation 对象,其中包含嵌套的 Container 结构,用于表示段落、表格、列表和条形码。目前,Vision 会为每张图像返回一个文档观察结果。

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

若要进行更简单的文档相机扫描,请使用 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 —— 质量较好、速度适中(约 100 毫秒),960x540
  • .fast —— 质量最低、速度最快(约 10 毫秒),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

对于较早的目标平台,请使用 VNTrackObjectRequest,并保留一个 VNSequenceRequestHandler,再将每次结果作为下一次输入观察结果。参考文档包含完整循环。

其他请求类型

Vision 还提供了其他请求,详见 references/vision-requests.md:

请求用途
ClassifyImageRequest对场景内容进行分类(户外、食物、动物等)
GenerateAttentionBasedSaliencyImageRequest返回单个 SaliencyImageObservation,表示观看者注意力集中的位置
GenerateObjectnessBasedSaliencyImageRequest返回单个 SaliencyImageObservation,表示类似对象的区域
GenerateForegroundInstanceMaskRequest前景对象分割(不限于人物)
DetectRectanglesRequest检测矩形形状(文档、卡片、屏幕)
DetectHorizonRequest检测地平线角度,以自动校平照片
DetectHumanBodyPoseRequest检测身体关节(肩部、肘部、膝部)
DetectHumanBodyPose3DRequest估算 3D 人体姿势
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 是 Vision 面向 iOS 18+ 的公开容器,供 CoreMLRequest 使用:加载 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。 应该: 使用现代 Swift 原生请求,通过 perform(on:) 和 async/await 执行。 原因: 现代 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 是否可用
  • 在 Info.plist 中为 VisionKit 配置摄像头使用说明(NSCameraUsageDescription)
  • 展示前请求 VisionKit 摄像头访问权限,并在展示后开始扫描
  • 人物分割质量级别符合使用场景
  • 在视频帧之间保留有状态跟踪请求或 VNSequenceRequestHandler
  • 错误处理涵盖请求失败和结果为空的情况

References

评论

支持 Markdown