VNCoreMLRequest — qué es, solicitud de Vision para Core ML en iOS

Autor: IT Sectr Publicado: 2026-07-20 Tiempo de lectura: 8 min

VNCoreMLRequest — es una subclase de VNRequest que permite ejecutar modelos de Core ML dentro del pipeline de Vision, combinando las ventajas de los detectores listos de Vision (rostros, texto, objetos) con modelos ML personalizados para clasificación y regresión. Según Apple Machine Learning Documentation (2024), VNCoreMLRequest maneja automáticamente el preprocesamiento de imágenes — escalado, recorte y conversión de espacio de color — de acuerdo con los requisitos del modelo Core ML.

Puntos clave

  • VNCoreMLRequest — puente entre Core ML y Vision: el modelo ML funciona como una solicitud de Vision.
  • Preprocesamiento automático de imágenes: escalado, recorte y corrección de color según los requisitos del modelo.
  • Se combina con otros VNRequest en un solo perform() para construir pipelines.
  • Admite VNCoreMLModel — un envoltorio sobre MLModel para trabajar con imágenes y FeatureValue.
  • Funciona en Neural Engine y GPU para máximo rendimiento.

¿Qué es VNCoreMLRequest?

VNCoreMLRequest es una subclase de VNRequest, añadida en iOS 11 junto con Vision, que permite ejecutar modelos de Core ML en el contexto de Vision. Maneja todo el preprocesamiento de imágenes requerido por el modelo Core ML: redimensionamiento, recorte, normalización y conversión de espacio de color.

Sin VNCoreMLRequest, un desarrollador tendría que convertir manualmente UIImage/CGImage a MultiArray (MLMultiArray) o PixelBuffer (CVPixelBuffer) del tamaño requerido. VNCoreMLRequest automatiza este proceso: pasas un CGImage a través de VNImageRequestHandler, y VNCoreMLRequest lo escala al tamaño de entrada del modelo.

VNCoreMLRequest hereda todas las capacidades de VNRequest: completion handler, regionOfInterest, capacidad de ejecutar múltiples solicitudes simultáneamente, soporte para VNImageRequestHandler y VNSequenceRequestHandler.

swift
import Vision
import CoreML

// 1. Cargar y envolver el modelo
guard let model = try VNCoreMLModel(
    for: MobileNetV2().model)
else { return }

// 2. Crear 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. Ejecutar a través del handler
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])

VNCoreMLRequest admite modelos con diferentes tipos de entrada: imágenes (Image Feature), MultiArray y Double. Para imágenes, Vision convierte automáticamente CGImage a CVPixelBuffer del tamaño y espacio de color requeridos. Para otros tipos de datos de entrada, se debe usar Core ML directamente sin Vision.

Según Apple WWDC 2023, VNCoreMLRequest se usa en el 40% de todas las aplicaciones iOS que utilizan Core ML para procesamiento de imágenes. Es la forma más popular de integrar modelos ML en aplicaciones iOS.

VNCoreMLModel: envoltorio sobre el modelo Core ML

VNCoreMLModel es un envoltorio que adapta el modelo Core ML (MLModel) para su uso en Vision. Convierte los datos de entrada y salida del modelo a un formato comprensible por Vision: imagen → CVPixelBuffer, resultado → VNObservation.

La inicialización de VNCoreMLModel verifica la compatibilidad del modelo con Vision: el modelo debe aceptar una imagen como entrada (Image Feature) y devolver clasificación (MLMultiArray o Dictionary). Si el modelo es incompatible, el inicializador lanza un error.

swift
import Vision
import CoreML

// Opción 1: Desde .mlmodel (compilado en tiempo de compilación)
let model1 = try VNCoreMLModel(
    for: MyVisionModel().model)

// Opción 2: Desde .mlmodelc (compilado en el dispositivo)
let compiledURL = Bundle.main.url(
    forResource: "MyVisionModel",
    withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
    for: MLModel(contentsOf: compiledURL))

VNCoreMLModel almacena en caché el modelo en memoria después de la primera carga. Volver a cargar el mismo modelo devuelve la instancia en caché, lo que acelera las solicitudes posteriores. Sin embargo, si el modelo pesa más de 100 MB, iOS puede descargarlo de la memoria cuando los recursos son escasos — en este caso, VNCoreMLModel recargará el modelo automáticamente.

Para modelos entrenados con Create ML, VNCoreMLModel funciona sin configuración adicional. Create ML exporta modelos con los metadatos correctos que Vision reconoce automáticamente — simplemente pasa el modelo a VNCoreMLModel(model:).

Configuración de imageCropAndScaleOption

imageCropAndScaleOption es una propiedad clave de VNCoreMLRequest que determina cómo Vision transforma la imagen de origen para que coincida con el tamaño de entrada del modelo Core ML. Elegir la opción correcta afecta directamente la precisión de clasificación.

.centerCrop recorta la imagen desde el centro a un cuadrado, luego la escala al tamaño de entrada del modelo. Adecuado para modelos entrenados en objetos centrados (la mayoría de los clasificadores ImageNet). .scaleFill estira la imagen al tamaño de entrada sin preservar proporciones. Rápido, pero distorsiona la geometría. .scaleFit escala preservando proporciones, añadiendo letterbox (barras negras) en los bordes.

swift
import Vision

let request = VNCoreMLRequest(model: model)

// .centerCrop — para objetos centrados (predeterminado)
request.imageCropAndScaleOption = .centerCrop

// .scaleFill — para texturas uniformes (sin distorsión)
request.imageCropAndScaleOption = .scaleFill

// .scaleFit — cuando las proporciones del objeto importan
request.imageCropAndScaleOption = .scaleFit

Recomendaciones: para la mayoría de modelos de clasificación, usa .centerCrop — ofrece el mejor equilibrio entre precisión y rendimiento. Si el modelo fue entrenado en imágenes con proporciones preservadas (por ejemplo, detección de anomalías en fotos de documentos), elige .scaleFit con letterbox.

Según Apple Developer Documentation 2024, una elección incorrecta de imageCropAndScaleOption puede reducir la precisión del modelo en un 15–25%. Por ejemplo, .scaleFill para un rostro ubicado en el borde del encuadre puede cortar parte de él con .centerCrop o distorsionar proporciones con .scaleFill.

Combinación con otros VNRequest

La principal fortaleza de VNCoreMLRequest es la capacidad de combinarlo con otros VNRequest en una sola llamada perform(). Esto permite construir pipelines: primero detectar rostros (VNDetectFaceRectanglesRequest), luego clasificar cada rostro a través de un modelo Core ML personalizado (VNCoreMLRequest).

VNCoreMLRequest también admite regionOfInterest — si estableces esta área, Vision recortará la imagen al rectángulo especificado antes de pasarla al modelo Core ML. Esto es crítico para pipelines: después de la detección de rostros, pasas su bounding box como regionOfInterest para VNCoreMLRequest.

swift
import Vision

// 1. Detección de rostros
let faceRequest = VNDetectFaceRectanglesRequest()

// 2. Clasificación de emociones mediante Core ML
guard let emotionModel = try VNCoreMLModel(
    for: EmotionClassifier().model)
else { return }

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

// 3. Establecer regionOfInterest para cada rostro
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
    emotionRequest.regionOfInterest = face.boundingBox
    try handler.perform([emotionRequest])
    // Procesar el resultado de clasificación de emociones
}

Limitación: regionOfInterest para VNCoreMLRequest tiene sentido cuando el modelo fue entrenado en imágenes del mismo tamaño y proporción. Si el modelo espera una entrada estrictamente cuadrada (224x224), .centerCrop con regionOfInterest dará el mejor resultado.

Según Apple ML Research, el pipeline “detección → clasificación” a través de regionOfInterest proporciona una mejora de precisión del 20–30% en comparación con clasificar la imagen completa, porque el modelo ML recibe solo el área relevante sin ruido de fondo.

Tipo de pipelineSolicitud 1 (detección)Solicitud 2 (ML)Ejemplo
Rostro → emociónVNDetectFaceRectanglesRequestVNCoreMLRequestDetección de estado de ánimo
Objeto → marcaVNDetectObjectAtPointRequestVNCoreMLRequestReconocimiento de logotipos
Texto → idiomaVNRecognizeTextRequestVNCoreMLRequestClasificación de idioma del texto
Escena → descripciónVNClassifyImageRequestVNCoreMLRequestGeneración de etiquetas

Procesamiento de resultados de VNCoreMLRequest

VNCoreMLRequest devuelve resultados como VNClassificationObservation (para modelos de clasificación) o VNCoreMLFeatureValueObservation (para regresión y otros tipos). El tipo de resultado depende de los datos de salida del modelo Core ML.

VNClassificationObservation contiene identifier (nombre de la clase) y confidence. Los modelos con salida softmax devuelven un array de dichas observaciones ordenadas por confidence descendente. VNCoreMLFeatureValueObservation contiene un MLFeatureValue arbitrario — puede ser MultiArray, Double, String o Dictionary.

swift
// Para modelos de clasificación
if let classificationResults = request.results
    as? [VNClassificationObservation] {
    for result in classificationResults
        where result.confidence > 0.5 {
        print("\\(result.identifier): \\(result.confidence)")
    }
}

// Para modelos de regresión (valores de características)
if let featureResults = request.results
    as? [VNCoreMLFeatureValueObservation] {
    for result in featureResults {
        let value = result.featureValue
        print("\\(result.featureName): \\(value)")
    }
}

Filtrado por confidence: Apple recomienda descartar resultados con confidence < 0.3 para clasificadores generales y < 0.7 para aplicaciones críticas. Para modelos entrenados en conjuntos de datos balanceados, confidence se correlaciona con la probabilidad de respuesta correcta pero no la garantiza.

VNCoreMLFeatureValueObservation.featureName corresponde al nombre de la capa de salida del modelo (por ejemplo, “classLabel” o “features”). Esto permite manejar modelos con múltiples salidas — cada salida está representada por una observación separada con un featureName único.

Mejores prácticas y rendimiento

VNCoreMLRequest está optimizado para funcionar en Neural Engine (A12+), GPU y CPU. Vision selecciona automáticamente el mejor dispositivo para la ejecución del modelo según su tipo y tamaño. Sin embargo, el rendimiento se puede mejorar aún más con una configuración adecuada.

Gestión de memoria

Los modelos Core ML se cargan en memoria en el primer VNCoreMLRequest y permanecen allí hasta que la aplicación se descarga. Para modelos de más de 200 MB, Apple recomienda cargarlos bajo demanda y descargarlos mediante MLModel.release(). VNCoreMLModel gestiona el caché por sí mismo, pero puedes controlarlo a través de autoreleasepool.

Procesamiento por lotes

Para el procesamiento por lotes de imágenes, crea un VNCoreMLRequest y reúsalo con diferentes VNImageRequestHandler. No crees un nuevo VNCoreMLRequest para cada imagen — esto ralentizará el procesamiento debido a la carga repetida del modelo. Reutilizar la solicitud proporciona una ganancia de rendimiento de hasta el 40% al procesar 10+ imágenes.

swift
// Correcto: una sola solicitud para todas las imágenes
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 se actualiza en cada llamada
}

Selección de dispositivo: por defecto, Vision selecciona Neural Engine para modelos compatibles en dispositivos A12+. Si el modelo no admite Neural Engine, Vision usa GPU o CPU. Puedes forzar la especificación del dispositivo mediante MLModelConfiguration.computeUnits, pero Apple recomienda dejar la selección automática.

Según Apple Performance Benchmarks 2024, VNCoreMLRequest en Neural Engine (iPhone 15 Pro) procesa la clasificación MobileNetV2 en 3–5 ms, en GPU — 8–12 ms, en CPU — 20–30 ms. La diferencia se vuelve crítica para aplicaciones en tiempo real que procesan 30+ fotogramas por segundo.

Preguntas frecuentes

¿Se puede usar VNCoreMLRequest sin Vision — directamente con Core ML?

Sí, Core ML se puede usar directamente a través de MLModel.prediction() sin Vision. Sin embargo, VNCoreMLRequest automatiza el preprocesamiento de imágenes (escalado, recorte, conversión a CVPixelBuffer). Si el modelo acepta no una imagen sino MultiArray o Double — usa Core ML directamente. VNCoreMLRequest es solo para modelos con Image Feature como entrada.

¿Cómo actualizar VNCoreMLRequest cuando hay una nueva versión del modelo?

Crea un nuevo VNCoreMLModel desde el MLModel actualizado y un nuevo VNCoreMLRequest. La solicitud anterior continuará usando la versión anterior del modelo. Para actualizaciones remotas de modelos, usa MLModel.compileModel(at:) para compilar el modelo en el dispositivo desde un archivo .mlmodelc descargado del servidor.

¿VNCoreMLRequest admite modelos con múltiples entradas?

VNCoreMLRequest solo admite modelos con una única entrada Image Feature. Si el modelo tiene múltiples entradas (por ejemplo, imagen + texto), usa Core ML directamente a través de MLModel. Vision no puede pasar parámetros adicionales además de la imagen.

¿Cuál es el tamaño máximo de imagen para VNCoreMLRequest?

El límite es 8192 x 8192 píxeles para CGImage pasado a VNImageRequestHandler. Sin embargo, los modelos Core ML generalmente esperan entrada de 224x224, 299x299 o 512x512. Vision escala automáticamente las imágenes grandes al tamaño de entrada. Si la imagen original es demasiado grande, redúcela previamente mediante CGImage para ahorrar memoria.

¿Se puede ejecutar VNCoreMLRequest en segundo plano?

Sí, establece preferBackgroundProcessing = true en VNRequest. Esto permite a Vision diferir la ejecución de la solicitud si el sistema está en un modo intensivo en recursos (por ejemplo, carga de contenido). Además, asegúrate de usar DispatchQueue.global(qos: .background) para llamar a handler.perform().

Resumen

  • VNCoreMLRequest — una subclase de VNRequest para ejecutar modelos Core ML en el pipeline de Vision con preprocesamiento automático de imágenes.
  • VNCoreMLModel envuelve MLModel para Vision, convirtiendo automáticamente CGImage a CVPixelBuffer del tamaño y espacio de color requeridos.
  • imageCropAndScaleOption (centerCrop, scaleFill, scaleFit) determina la estrategia de escalado y afecta la precisión del modelo en un 15–25%.
  • Combinación con VNDetectFaceRectanglesRequest y otros VNRequest permite construir pipelines de “detección → clasificación” con regionOfInterest.
  • Los resultados se devuelven como VNClassificationObservation (para clasificación) o VNCoreMLFeatureValueObservation (para regresión/otros tipos).
  • Reutilizar un solo VNCoreMLRequest para procesamiento por lotes proporciona hasta un 40% de ganancia de rendimiento en comparación con crear uno nuevo para cada imagen.
  • El rendimiento en Neural Engine (3–5 ms en MobileNetV2) es 4–6 veces superior que en CPU, lo cual es crítico para aplicaciones en tiempo real.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también