VNCoreMLRequest — 是什么,iOS中Core ML的Vision请求

作者: IT Sectr 发布日期: 2026-07-20 阅读时间: 8 分钟

VNCoreMLRequest 是 VNRequest 的子类,允许在 Vision pipeline 内运行 Core ML 模型,将现成的 Vision 检测器(人脸、文本、对象)的优势与用于分类和回归的自定义 ML 模型相结合。根据 Apple Machine Learning Documentation(2024),VNCoreMLRequest 自动处理图像预处理——缩放、裁剪和色彩空间转换——符合 Core ML 模型的要求。

要点

  • VNCoreMLRequest — Core ML 和 Vision 之间的桥梁:ML 模型作为 Vision 请求工作。
  • 自动图像预处理:根据模型要求进行缩放、裁剪和颜色校正。
  • 与其它 VNRequest 在一个 perform() 中组合以构建 pipeline。
  • 支持 VNCoreMLModel — 用于处理图像和 FeatureValue 的 MLModel 包装器。
  • Neural Engine 和 GPU 上运行以获得最大性能。

什么是 VNCoreMLRequest?

VNCoreMLRequest 是 VNRequest 的子类,随 iOS 11 中的 Vision 一起添加,允许在 Vision 上下文中运行 Core ML 模型。它负责 Core ML 模型所需的所有图像预处理:调整大小、裁剪、归一化和色彩空间转换。

没有 VNCoreMLRequest,开发人员必须手动将 UIImage/CGImage 转换为适当大小的 MultiArray(MLMultiArray)或 PixelBuffer(CVPixelBuffer)。VNCoreMLRequest 自动化了这个过程:您通过 VNImageRequestHandler 传递 CGImage,VNCoreMLRequest 自动将其缩放到模型的输入大小。

VNCoreMLRequest 继承了 VNRequest 的所有功能:completion handler、regionOfInterest、同时执行多个请求的能力、支持 VNImageRequestHandler 和 VNSequenceRequestHandler。

swift
import Vision
import CoreML

// 1. 加载并包装模型
guard let model = try VNCoreMLModel(
    for: MobileNetV2().model)
else { return }

// 2. 创建 VNCoreMLRequest
let request = VNCoreMLRequest(model: model) { req, _ in
    guard let results = req.results
        as? [VNClassificationObservation]
    else { return }
    for r in results.prefix(3) {
        print("\\(r.identifier): \\(r.confidence)")
    }
}

// 3. 通过 handler 执行
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])

VNCoreMLRequest 支持具有不同输入类型的模型:图像(Image Feature)、MultiArray 和 Double。对于图像,Vision 自动将 CGImage 转换为适当大小和色彩空间的 CVPixelBuffer。对于其他类型的输入数据,您需要直接使用 Core ML 而无需 Vision。

根据 Apple WWDC 2023,VNCoreMLRequest 用于 40% 的使用 Core ML 处理图像的 iOS 应用程序。这是将 ML 模型集成到 iOS 应用程序中最流行的方法。

VNCoreMLModel:Core ML 模型的包装器

VNCoreMLModel 是一个包装器,用于调整 Core ML 模型(MLModel)以在 Vision 中使用。它将模型的输入和输出数据转换为 Vision 可理解的格式:图像 → CVPixelBuffer,结果 → VNObservation。

VNCoreMLModel 的初始化检查模型与 Vision 的兼容性:模型必须接受图像作为输入(Image Feature)并返回分类结果(MLMultiArray 或 Dictionary)。如果模型不兼容,初始化器将抛出错误。

swift
import Vision
import CoreML

// 选项 1:从 .mlmodel(构建时编译)
let model1 = try VNCoreMLModel(
    for: MyVisionModel().model)

// 选项 2:从 .mlmodelc(在设备上编译)
let compiledURL = Bundle.main.url(
    forResource: "MyVisionModel",
    withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
    for: MLModel(contentsOf: compiledURL))

VNCoreMLModel 在首次加载后缓存模型到内存中。重新加载相同的模型返回缓存的实例,从而加速后续请求。然而,如果模型超过 100 MB,iOS 可能会在资源不足时将其从内存中卸载——在这种情况下,VNCoreMLModel 会自动重新加载模型。

对于通过 Create ML 训练的模型,VNCoreMLModel 无需额外配置即可工作。Create ML 导出具有正确元数据的模型,Vision 会自动识别——只需将模型传递给 VNCoreMLModel(model:) 即可。

配置 imageCropAndScaleOption

imageCropAndScaleOption 是 VNCoreMLRequest 的关键属性,决定 Vision 如何将原始图像转换为 Core ML 模型的输入大小。正确选择选项直接影响分类精度。

.centerCrop — 从中心裁剪图像为正方形,然后缩放到模型输入大小。适用于在居中对象上训练的模型(大多数 ImageNet 分类器)。.scaleFill — 将图像拉伸到输入大小而不保持比例。速度快但会扭曲几何形状。.scaleFit — 保持比例缩放,在边缘添加 letterbox(黑条)。

swift
import Vision

let request = VNCoreMLRequest(model: model)

// .centerCrop — 用于居中对象(默认)
request.imageCropAndScaleOption = .centerCrop

// .scaleFill — 用于均匀纹理(无扭曲)
request.imageCropAndScaleOption = .scaleFill

// .scaleFit — 当对象比例重要时
request.imageCropAndScaleOption = .scaleFit

建议:对于大多数分类模型,使用 .centerCrop——它提供最佳的精度和性能比。如果模型在保持比例的图像上训练(例如,文档照片上的异常检测),选择带 letterbox 的 .scaleFit。

根据 Apple Developer Documentation 2024,错误选择 imageCropAndScaleOption 可能使模型精度降低 15–25%。例如,对于位于帧边缘的人脸,.scaleFill 在 .centerCrop 时可能裁剪其一部分,或在 .scaleFill 时扭曲比例。

与其它 VNRequest 组合

VNCoreMLRequest 的主要优势——能够与其它 VNRequest 在一个 perform() 调用中组合。这允许构建 pipeline:首先检测人脸(VNDetectFaceRectanglesRequest),然后通过自定义 Core ML 模型(VNCoreMLRequest)对每个人脸进行分类。

VNCoreMLRequest 还支持 regionOfInterest——如果设置了这个区域,Vision 会在将图像传递给 Core ML 模型之前将其裁剪到指定的矩形。这对于 pipeline 至关重要:检测到人脸后,将其边界框作为 regionOfInterest 传递给 VNCoreMLRequest。

swift
import Vision

// 1. 人脸检测
let faceRequest = VNDetectFaceRectanglesRequest()

// 2. 通过 Core ML 进行情绪分类
guard let emotionModel = try VNCoreMLModel(
    for: EmotionClassifier().model)
else { return }

let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])

// 3. 为每个人脸设置 regionOfInterest
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
    emotionRequest.regionOfInterest = face.boundingBox
    try handler.perform([emotionRequest])
    // 处理情绪分类结果
}

限制:VNCoreMLRequest 的 regionOfInterest 仅在模型在单一大小和比例的图像上训练时才有意义。如果模型期望严格的正方形输入(224x224),带 regionOfInterest 的 .centerCrop 将提供最佳结果。

根据 Apple ML Research,通过 regionOfInterest 的”检测→分类” pipeline 比整张图像分类精度提高 20–30%,因为 ML 模型只接收相关区域而无背景噪声。

Pipeline 类型请求 1(检测)请求 2(ML)示例
人脸→情绪VNDetectFaceRectanglesRequestVNCoreMLRequest确定情绪
对象→品牌VNDetectObjectAtPointRequestVNCoreMLRequest识别标志
文本→语言VNRecognizeTextRequestVNCoreMLRequest文本语言分类
场景→描述VNClassifyImageRequestVNCoreMLRequest生成标签

处理 VNCoreMLRequest 的结果

VNCoreMLRequest 以 VNClassificationObservation(用于分类模型)或 VNCoreMLFeatureValueObservation(用于回归和其他类型)的形式返回结果。结果类型取决于 Core ML 模型的输出数据。

VNClassificationObservation 包含 identifier(类名)和 confidence(置信度)。具有 softmax 输出的模型返回此类观察的数组,按置信度降序排序。VNCoreMLFeatureValueObservation 包含任意的 MLFeatureValue 值——可以是 MultiArray、Double、String 或 Dictionary。

swift
// 对于分类模型
if let classificationResults = request.results
    as? [VNClassificationObservation] {
    for result in classificationResults
        where result.confidence > 0.5 {
        print("\\(result.identifier): \\(result.confidence)")
    }
}

// 对于回归模型(特征值)
if let featureResults = request.results
    as? [VNCoreMLFeatureValueObservation] {
    for result in featureResults {
        let value = result.featureValue
        print("\\(result.featureName): \\(value)")
    }
}

按置信度过滤:Apple 建议对通用分类器丢弃置信度 < 0.3 的结果,对关键应用丢弃 < 0.7 的结果。对于在平衡数据集上训练的模型,置信度与正确答案的概率相关,但不能保证。

VNCoreMLFeatureValueObservation.featureName 对应于模型输出层的名称(例如 'classLabel' 或 'features')。这允许处理具有多个输出的模型——每个输出由具有唯一 featureName 的独立 observation 表示。

最佳实践和性能

VNCoreMLRequest 针对在 Neural Engine(A12+)、GPU 和 CPU 上运行进行了优化。Vision 会根据模型的类型和大小自动选择最佳的运行设备。然而,通过正确配置可以进一步提高性能。

内存管理

Core ML 模型 在第一次 VNCoreMLRequest 时加载到内存中,并一直保留到应用程序卸载。对于超过 200 MB 的模型,Apple 建议按需加载并通过 MLModel.release() 卸载。VNCoreMLModel 自行管理缓存,但您可以通过 autoreleasepool 进行控制。

批处理

对于图像批处理,创建一个 VNCoreMLRequest 并使用不同的 VNImageRequestHandler 重复使用它。不要为每个图像创建新的 VNCoreMLRequest——这会因模型重新加载而减慢处理速度。重复使用请求在处理 10 张以上图像时性能最多可提高 40%。

swift
// 正确:所有图像使用一个请求
let batchSize = 20
let batchRequest = VNCoreMLRequest(model: model)

for i in 0..<batchSize {
    let handler = VNImageRequestHandler(
        cgImage: images[i],
        options: [:])
    try handler.perform([batchRequest])
    // 每次调用时 batchRequest.results 都会更新
}

设备选择:默认情况下,Vision 在 A12+ 设备上为兼容模型选择 Neural Engine。如果模型不支持 Neural Engine,Vision 使用 GPU 或 CPU。您可以通过 MLModelConfiguration.computeUnits 强制指定设备,但 Apple 建议保留自动选择。

根据 Apple Performance Benchmarks 2024,VNCoreMLRequest 在 Neural Engine(iPhone 15 Pro)上处理 MobileNetV2 分类需要 3–5 毫秒,在 GPU 上——8–12 毫秒,在 CPU 上——20–30 毫秒。对于处理每秒 30 帧以上的实时应用程序,这一差异至关重要。

常见问题

可以在没有 Vision 的情况下直接使用 VNCoreMLRequest 与 Core ML 吗?

是的,Core ML 可以直接通过 MLModel.prediction() 使用,无需 Vision。然而,VNCoreMLRequest 自动处理图像预处理(缩放、裁剪、转换为 CVPixelBuffer)。如果模型接受的是 MultiArray 或 Double 而不是图像——请直接使用 Core ML。VNCoreMLRequest 仅适用于输入为 Image Feature 的模型。

模型有新版本时如何更新 VNCoreMLRequest?

从更新的 MLModel 创建新的 VNCoreMLModel 和新的 VNCoreMLRequest。旧的请求将继续使用旧版本的模型。对于远程更新模型,使用 MLModel.compileModel(at:) 从从服务器下载的 .mlmodelc 文件在设备上编译模型。

VNCoreMLRequest 是否支持多输入模型?

VNCoreMLRequest 仅支持具有单个 Image Feature 输入的模型。如果模型有多个输入(例如,图像 + 文本),请直接通过 MLModel 使用 Core ML。Vision 无法传递除图像以外的额外参数。

VNCoreMLRequest 的最大图像尺寸是多少?

限制是传递给 VNImageRequestHandler 的 CGImage 的 8192 x 8192 像素。然而,Core ML 模型通常期望输入为 224x224、299x299 或 512x512。Vision 会自动将大图像缩放到输入大小。如果原始图像太大,请先通过 CGImage 减小图像以节省内存。

可以在后台运行 VNCoreMLRequest 吗?

是的,在 VNRequest 上设置 preferBackgroundProcessing = true。这将允许 Vision 在系统处于资源密集型模式(例如,加载内容)时延迟执行请求。同时还必须使用 DispatchQueue.global(qos: .background) 调用 handler.perform()。

总结

  • VNCoreMLRequest — VNRequest 的子类,用于在 Vision pipeline 中运行 Core ML 模型,具有自动图像预处理功能。
  • VNCoreMLModel 为 Vision 包装 MLModel,自动将 CGImage 转换为适当大小和色彩空间的 CVPixelBuffer。
  • imageCropAndScaleOption(centerCrop、scaleFill、scaleFit)决定了缩放策略,影响模型精度 15–25%。
  • VNDetectFaceRectanglesRequest 和其他 VNRequest 组合 允许构建带 regionOfInterest 的”检测→分类”pipeline。
  • 结果以 VNClassificationObservation(用于分类)或 VNCoreMLFeatureValueObservation(用于回归/其他类型)形式返回。
  • 批处理时重复使用一个 VNCoreMLRequest 与为每个图像创建新请求相比,性能提高最多 40%。
  • Neural Engine 上的性能(MobileNetV2 为 3–5 毫秒)比 CPU 高 4–6 倍,这对实时应用程序至关重要。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读