VNCoreMLRequest — что это, Vision-запрос для Core ML в iOS

Автор: IT Sectr Опубликовано: 2026-07-20 Время чтения: 8 мин

VNCoreMLRequest — это подкласс VNRequest, который позволяет запускать Core ML модели внутри пайплайна Vision, объединяя преимущества готовых детекторов Vision (лица, текст, объекты) с кастомными ML-моделями для классификации и регрессии. По данным Apple Machine Learning Documentation (2024), VNCoreMLRequest автоматически обрабатывает предобработку изображения — масштабирование, обрезку и конвертацию цветового пространства — в соответствии с требованиями Core ML модели.

Главное

  • VNCoreMLRequest — мост между Core ML и Vision: ML-модель работает как запрос Vision.
  • Автоматическая предобработка изображений: масштабирование, crop и цветокоррекция под требования модели.
  • Комбинируется с другими VNRequest в одном perform() для построения пайплайнов.
  • Поддерживает VNCoreMLModel — обёртку над MLModel для работы с изображениями и FeatureValue.
  • Работает на Neural Engine и GPU для максимальной производительности.

Что такое VNCoreMLRequest?

VNCoreMLRequest — это подкласс VNRequest, добавленный в iOS 11 вместе с Vision, который позволяет запускать Core ML модели в контексте Vision. Он берёт на себя всю предобработку изображения, необходимую для Core ML модели: изменение размера, обрезку, нормализацию и конвертацию цветового пространства.

Без VNCoreMLRequest разработчику пришлось бы вручную преобразовывать UIImage/CGImage в MultiArray (MLMultiArray) или PixelBuffer (CVPixelBuffer) нужного размера. VNCoreMLRequest автоматизирует этот процесс: вы передаёте CGImage через VNImageRequestHandler, а VNCoreMLRequest сам масштабирует его под вход модели.

VNCoreMLRequest наследует все возможности VNRequest: completion handler, regionOfInterest, возможность выполнять несколько запросов одновременно, поддержку VNImageRequestHandler и VNSequenceRequestHandler.

swift
import Vision
import CoreML

// 1. Load and wrap model
guard let model = try VNCoreMLModel(
    for: MobileNetV2().model)
else { return }

// 2. Create 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. Execute via 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% всех iOS-приложений, применяющих Core ML для работы с изображениями. Это самый популярный способ интеграции ML-моделей в iOS-приложения.

VNCoreMLModel: обёртка над Core ML моделью

VNCoreMLModel — это обёртка, которая адаптирует Core ML модель (MLModel) для использования в Vision. Она конвертирует входные и выходные данные модели в формат, понятный Vision: изображение → CVPixelBuffer, результат → VNObservation.

Инициализация VNCoreMLModel проверяет совместимость модели с Vision: модель должна принимать изображение на вход (Image Feature) и возвращать классификацию (MLMultiArray или Dictionary). Если модель несовместима, инициализатор выбрасывает ошибку.

swift
import Vision
import CoreML

// Option 1: From .mlmodel (compiled at build time)
let model1 = try VNCoreMLModel(
    for: MyVisionModel().model)

// Option 2: From .mlmodelc (compiled on device)
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 — for centered objects (default)
request.imageCropAndScaleOption = .centerCrop

// .scaleFill — for uniform textures (no distortion)
request.imageCropAndScaleOption = .scaleFill

// .scaleFit — when object proportions matter
request.imageCropAndScaleOption = .scaleFit

Рекомендации: для большинства моделей классификации используйте .centerCrop — он даёт наилучшее соотношение точности и производительности. Если модель обучена на изображениях с сохранением пропорций (например, детекция аномалий на фотографиях документов), выбирайте .scaleFit с letterbox.

По данным Apple Developer Documentation 2024, неправильный выбор imageCropAndScaleOption может снизить точность модели на 15–25%. Например, .scaleFill для лица, расположенного у края кадра, может обрезать его часть при .centerCrop или исказить пропорции при .scaleFill.

Комбинирование с другими VNRequest

Главная сила VNCoreMLRequest — возможность комбинировать его с другими VNRequest в одном вызове perform(). Это позволяет строить пайплайны: сначала найти лица (VNDetectFaceRectanglesRequest), затем классифицировать каждое лицо через кастомную Core ML модель (VNCoreMLRequest).

VNCoreMLRequest также поддерживает regionOfInterest — если установить эту область, Vision обрежет изображение до указанного прямоугольника перед передачей в Core ML модель. Это критически важно для пайплайнов: после детекции лица вы передаёте его bounding box как regionOfInterest для VNCoreMLRequest.

swift
import Vision

// 1. Face detection
let faceRequest = VNDetectFaceRectanglesRequest()

// 2. Emotion classification via Core ML
guard let emotionModel = try VNCoreMLModel(
    for: EmotionClassifier().model)
else { return }

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

// 3. Set regionOfInterest for each face
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
    emotionRequest.regionOfInterest = face.boundingBox
    try handler.perform([emotionRequest])
    // Process emotion classification result
}

Ограничение: regionOfInterest для VNCoreMLRequest имеет смысл, когда модель обучена на изображениях одного размера и пропорции. Если модель ожидает строго квадратный вход (224x224), .centerCrop с regionOfInterest даст наилучший результат.

По данным Apple ML Research, пайплайн «детекция → классификация» через regionOfInterest даёт прирост точности на 20–30% по сравнению с классификацией целого изображения, так как ML-модель получает на вход только релевантную область без фонового шума.

Тип пайплайнаЗапрос 1 (детекция)Запрос 2 (ML)Пример
Лицо → эмоцияVNDetectFaceRectanglesRequestVNCoreMLRequestОпределение настроения
Объект → брендVNDetectObjectAtPointRequestVNCoreMLRequestРаспознавание логотипов
Текст → языкVNRecognizeTextRequestVNCoreMLRequestКлассификация языка текста
Сцена → описаниеVNClassifyImageRequestVNCoreMLRequestГенерация тегов

Обработка результатов VNCoreMLRequest

VNCoreMLRequest возвращает результаты в виде VNClassificationObservation (для классификационных моделей) или VNCoreMLFeatureValueObservation (для регрессионных и других типов). Тип результата зависит от выходных данных Core ML модели.

VNClassificationObservation содержит identifier (название класса) и confidence (уверенность). Модели с softmax-выходом возвращают массив таких наблюдений, отсортированных по убыванию confidence. VNCoreMLFeatureValueObservation содержит произвольное значение MLFeatureValue — может быть MultiArray, Double, String или Dictionary.

swift
// For classification models
if let classificationResults = request.results
    as? [VNClassificationObservation] {
    for result in classificationResults
        where result.confidence > 0.5 {
        print("\\(result.identifier): \\(result.confidence)")
    }
}

// For regression models (feature values)
if let featureResults = request.results
    as? [VNCoreMLFeatureValueObservation] {
    for result in featureResults {
        let value = result.featureValue
        print("\\(result.featureName): \\(value)")
    }
}

Фильтрация по confidence: Apple рекомендует отбрасывать результаты с confidence < 0.3 для общих классификаторов и < 0.7 для критичных приложений. Для моделей, обученных на сбалансированных датасетах, confidence коррелирует с вероятностью правильного ответа, но не гарантирует её.

VNCoreMLFeatureValueObservation.featureName соответствует имени выходного слоя модели (например, "classLabel" или "features"). Это позволяет обрабатывать модели с несколькими выходами — каждый выход представлен отдельным observation с уникальным featureName.

Лучшие практики и производительность

VNCoreMLRequest оптимизирован для работы на Neural Engine (A12+), GPU и CPU. Vision автоматически выбирает лучшее устройство для выполнения модели в зависимости от её типа и размера. Однако производительность можно дополнительно улучшить правильной настройкой.

Управление памятью

Модели Core ML загружаются в память при первом VNCoreMLRequest и остаются там до выгрузки приложения. Для моделей размером более 200 MB Apple рекомендует загружать их по требованию и выгружать через MLModel.release(). VNCoreMLModel сама управляет кэшированием, но вы можете контролировать это через autoreleasepool.

Батчевая обработка

Для пакетной обработки изображений создавайте один VNCoreMLRequest и переиспользуйте его с разными VNImageRequestHandler. Не создавайте новый VNCoreMLRequest на каждое изображение — это замедлит обработку из-за повторной загрузки модели. Переиспользование запроса даёт прирост производительности до 40% при обработке 10+ изображений.

swift
// Correct: single request for all images
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 update on each call
}

Выбор устройства: по умолчанию Vision выбирает Neural Engine для совместимых моделей на устройствах A12+. Если модель не поддерживает 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 мс. Разница становится критичной для real-time приложений, обрабатывающих 30+ кадров в секунду.

Часто задаваемые вопросы

Можно ли использовать VNCoreMLRequest без Vision — напрямую с Core ML?

Да, Core ML можно использовать напрямую через MLModel.prediction(), без Vision. Однако VNCoreMLRequest автоматизирует предобработку изображений (масштабирование, crop, конвертацию в CVPixelBuffer). Если модель принимает не изображение, а MultiArray или Double — используйте Core ML напрямую. VNCoreMLRequest только для моделей с Image Feature на входе.

Как обновить VNCoreMLRequest при новой версии модели?

Создайте новый VNCoreMLModel из обновлённого MLModel и новый VNCoreMLRequest. Старый запрос продолжит использовать старую версию модели. Для удалённого обновления моделей используйте MLModel.compileModel(at:) для компиляции модели на устройстве из .mlmodelc файла, загруженного с сервера.

VNCoreMLRequest поддерживает модели с несколькими входами?

VNCoreMLRequest поддерживает только модели с одним Image Feature входом. Если у модели несколько входов (например, изображение + текст), используйте Core ML напрямую через MLModel. Vision не может передать дополнительные параметры помимо изображения.

Какой максимальный размер изображения для VNCoreMLRequest?

Ограничение — 8192 x 8192 пикселей для CGImage, передаваемого в VNImageRequestHandler. Однако Core ML модели обычно ожидают вход 224x224, 299x299 или 512x512. Vision автоматически масштабирует большое изображение под размер входа. Если исходное изображение слишком велико, предварительно уменьшите его через CGImage для экономии памяти.

Можно ли запустить VNCoreMLRequest в фоновом режиме?

Да, установите preferBackgroundProcessing = true на VNRequest. Это позволит Vision отложить выполнение запроса, если система находится в ресурсоёмком режиме (например, загрузка контента). Также обязательно используйте DispatchQueue.global(qos: .background) для вызова handler.perform().

Итоги

  • VNCoreMLRequest — подкласс VNRequest для запуска Core ML моделей в пайплайне Vision с автоматической предобработкой изображений.
  • VNCoreMLModel оборачивает MLModel для Vision, автоматически конвертируя CGImage в CVPixelBuffer нужного размера и цветового пространства.
  • imageCropAndScaleOption (centerCrop, scaleFill, scaleFit) определяет стратегию масштабирования и влияет на точность модели на 15–25%.
  • Комбинирование с VNDetectFaceRectanglesRequest и другими VNRequest позволяет строить пайплайны «детекция → классификация» с regionOfInterest.
  • Результаты возвращаются как VNClassificationObservation (для классификации) или VNCoreMLFeatureValueObservation (для регрессии/других типов).
  • Переиспользование одного VNCoreMLRequest для пакетной обработки даёт до 40% прироста производительности по сравнению с созданием нового на каждое изображение.
  • Производительность на Neural Engine (3–5 мс на MobileNetV2) в 4–6 раз выше, чем на CPU, что критично для real-time приложений.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также