VNCoreMLRequest — cos’è, richiesta Vision per Core ML in iOS

Autore: IT Sectr Pubblicato: 2026-07-20 Tempo di lettura: 8 min

VNCoreMLRequest — è una sottoclasse di VNRequest che consente di eseguire modelli Core ML all’interno della pipeline Vision, combinando i vantaggi dei rilevatori già pronti di Vision (volti, testo, oggetti) con modelli ML personalizzati per classificazione e regressione. Secondo Apple Machine Learning Documentation (2024), VNCoreMLRequest gestisce automaticamente la preelaborazione delle immagini — ridimensionamento, ritaglio e conversione dello spazio colore — secondo i requisiti del modello Core ML.

Punti chiave

  • VNCoreMLRequest — ponte tra Core ML e Vision: il modello ML funge da richiesta Vision.
  • Preelaborazione automatica delle immagini: ridimensionamento, ritaglio e correzione del colore secondo i requisiti del modello.
  • Si combina con altri VNRequest in un unico perform() per costruire pipeline.
  • Supporta VNCoreMLModel — un wrapper su MLModel per lavorare con immagini e FeatureValue.
  • Funziona su Neural Engine e GPU per prestazioni massime.

Cos’è VNCoreMLRequest?

VNCoreMLRequest è una sottoclasse di VNRequest, aggiunta in iOS 11 insieme a Vision, che consente di eseguire modelli Core ML nel contesto di Vision. Gestisce tutta la preelaborazione delle immagini richiesta dal modello Core ML: ridimensionamento, ritaglio, normalizzazione e conversione dello spazio colore.

Senza VNCoreMLRequest, uno sviluppatore dovrebbe convertire manualmente UIImage/CGImage in MultiArray (MLMultiArray) o PixelBuffer (CVPixelBuffer) della dimensione richiesta. VNCoreMLRequest automatizza questo processo: si passa un CGImage tramite VNImageRequestHandler e VNCoreMLRequest lo ridimensiona per l’input del modello.

VNCoreMLRequest eredita tutte le capacità di VNRequest: completion handler, regionOfInterest, possibilità di eseguire più richieste contemporaneamente, supporto per VNImageRequestHandler e VNSequenceRequestHandler.

swift
import Vision
import CoreML

// 1. Caricare e incapsulare il modello
guard let model = try VNCoreMLModel(
    for: MobileNetV2().model)
else { return }

// 2. Creare 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. Eseguire tramite handler
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])

VNCoreMLRequest supporta modelli con diversi tipi di input: immagini (Image Feature), MultiArray e Double. Per le immagini, Vision converte automaticamente CGImage in CVPixelBuffer della dimensione e dello spazio colore necessari. Per altri tipi di dati di input, utilizzare Core ML direttamente senza Vision.

Secondo Apple WWDC 2023, VNCoreMLRequest è utilizzato nel 40% di tutte le app iOS che utilizzano Core ML per l’elaborazione delle immagini. Questo è il modo più popolare per integrare modelli ML nelle app iOS.

VNCoreMLModel: un wrapper sul modello Core ML

VNCoreMLModel è un wrapper che adatta il modello Core ML (MLModel) per l’uso in Vision. Converte i dati di input e output del modello in un formato comprensibile da Vision: immagine → CVPixelBuffer, risultato → VNObservation.

L’inizializzazione di VNCoreMLModel verifica la compatibilità del modello con Vision: il modello deve accettare un’immagine come input (Image Feature) e restituire una classificazione (MLMultiArray o Dictionary). Se il modello è incompatibile, l’inizializzatore genera un errore.

swift
import Vision
import CoreML

// Opzione 1: Da .mlmodel (compilato al momento della build)
let model1 = try VNCoreMLModel(
    for: MyVisionModel().model)

// Opzione 2: Da .mlmodelc (compilato sul dispositivo)
let compiledURL = Bundle.main.url(
    forResource: "MyVisionModel",
    withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
    for: MLModel(contentsOf: compiledURL))

VNCoreMLModel memorizza nella cache il modello in memoria dopo il primo caricamento. Ricaricare lo stesso modello restituisce l’istanza cache, accelerando le richieste successive. Tuttavia, se il modello pesa più di 100 MB, iOS potrebbe scaricarlo dalla memoria in caso di scarsità di risorse — in questo caso, VNCoreMLModel ricaricherà automaticamente il modello.

Per i modelli addestrati con Create ML, VNCoreMLModel funziona senza configurazione aggiuntiva. Create ML esporta i modelli con i metadati corretti che Vision riconosce automaticamente — basta passare il modello a VNCoreMLModel(model:).

Configurazione di imageCropAndScaleOption

imageCropAndScaleOption è una proprietà chiave di VNCoreMLRequest che determina come Vision trasforma l’immagine sorgente per adattarla alla dimensione di input del modello Core ML. La scelta dell’opzione corretta influisce direttamente sulla precisione della classificazione.

.centerCrop ritaglia l’immagine dal centro in un quadrato, quindi la ridimensiona alla dimensione di input del modello. Adatto per modelli addestrati su oggetti centrati (la maggior parte dei classificatori ImageNet). .scaleFill deforma l’immagine alla dimensione di input senza preservare le proporzioni. Veloce, ma distorce la geometria. .scaleFit ridimensiona preservando le proporzioni, aggiungendo letterbox (barre nere) ai bordi.

swift
import Vision

let request = VNCoreMLRequest(model: model)

// .centerCrop — per oggetti centrati (predefinito)
request.imageCropAndScaleOption = .centerCrop

// .scaleFill — per trame uniformi (senza distorsione)
request.imageCropAndScaleOption = .scaleFill

// .scaleFit — quando le proporzioni dell’oggetto contano
request.imageCropAndScaleOption = .scaleFit

Raccomandazioni: per la maggior parte dei modelli di classificazione, utilizzare .centerCrop — offre il miglior equilibrio tra precisione e prestazioni. Se il modello è stato addestrato su immagini con proporzioni preservate (ad esempio, rilevamento di anomalie su foto di documenti), scegliere .scaleFit con letterbox.

Secondo Apple Developer Documentation 2024, una scelta errata di imageCropAndScaleOption può ridurre la precisione del modello del 15–25%. Ad esempio, .scaleFill per un volto situato sul bordo dell’inquadratura potrebbe tagliarne una parte con .centerCrop o distorcere le proporzioni con .scaleFill.

Combinazione con altri VNRequest

Il punto di forza principale di VNCoreMLRequest è la possibilità di combinarlo con altri VNRequest in una singola chiamata perform(). Ciò consente di costruire pipeline: prima rilevare i volti (VNDetectFaceRectanglesRequest), poi classificare ogni volto tramite un modello Core ML personalizzato (VNCoreMLRequest).

VNCoreMLRequest supporta anche regionOfInterest — se si imposta quest’area, Vision ritaglierà l’immagine al rettangolo specificato prima di passarla al modello Core ML. Ciò è fondamentale per le pipeline: dopo il rilevamento del volto, si passa il suo bounding box come regionOfInterest per VNCoreMLRequest.

swift
import Vision

// 1. Rilevamento del volto
let faceRequest = VNDetectFaceRectanglesRequest()

// 2. Classificazione delle emozioni tramite Core ML
guard let emotionModel = try VNCoreMLModel(
    for: EmotionClassifier().model)
else { return }

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

// 3. Impostare regionOfInterest per ogni volto
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
    emotionRequest.regionOfInterest = face.boundingBox
    try handler.perform([emotionRequest])
    // Elaborare il risultato della classificazione delle emozioni
}

Limitazione: regionOfInterest per VNCoreMLRequest ha senso quando il modello è addestrato su immagini della stessa dimensione e proporzione. Se il modello prevede un input strettamente quadrato (224x224), .centerCrop con regionOfInterest darà il miglior risultato.

Secondo Apple ML Research, la pipeline “rilevamento → classificazione” tramite regionOfInterest offre un miglioramento della precisione del 20–30% rispetto alla classificazione dell’intera immagine, poiché il modello ML riceve solo l’area rilevante senza rumore di fondo.

Tipo di pipelineRichiesta 1 (rilevamento)Richiesta 2 (ML)Esempio
Volto → emozioneVNDetectFaceRectanglesRequestVNCoreMLRequestRilevamento dell’umore
Oggetto → marcaVNDetectObjectAtPointRequestVNCoreMLRequestRiconoscimento logo
Testo → linguaVNRecognizeTextRequestVNCoreMLRequestClassificazione della lingua del testo
Scena → descrizioneVNClassifyImageRequestVNCoreMLRequestGenerazione di tag

Elaborazione dei risultati di VNCoreMLRequest

VNCoreMLRequest restituisce i risultati come VNClassificationObservation (per modelli di classificazione) o VNCoreMLFeatureValueObservation (per regressione e altri tipi). Il tipo di risultato dipende dai dati di output del modello Core ML.

VNClassificationObservation contiene identifier (nome della classe) e confidence. I modelli con output softmax restituiscono un array di queste osservazioni ordinate per confidence decrescente. VNCoreMLFeatureValueObservation contiene un MLFeatureValue arbitrario — può essere MultiArray, Double, String o Dictionary.

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

// Per modelli di regressione (valori delle caratteristiche)
if let featureResults = request.results
    as? [VNCoreMLFeatureValueObservation] {
    for result in featureResults {
        let value = result.featureValue
        print("\\(result.featureName): \\(value)")
    }
}

Filtraggio per confidence: Apple raccomanda di scartare i risultati con confidence < 0,3 per classificatori generali e < 0,7 per applicazioni critiche. Per i modelli addestrati su dataset bilanciati, la confidence è correlata alla probabilità di risposta corretta ma non la garantisce.

VNCoreMLFeatureValueObservation.featureName corrisponde al nome del layer di output del modello (ad esempio, “classLabel” o “features”). Ciò consente di gestire modelli con output multipli — ogni output è rappresentato da un’osservazione separata con un featureName univoco.

Best practice e prestazioni

VNCoreMLRequest è ottimizzato per funzionare su Neural Engine (A12+), GPU e CPU. Vision seleziona automaticamente il dispositivo migliore per l’esecuzione del modello in base al suo tipo e dimensione. Tuttavia, le prestazioni possono essere ulteriormente migliorate con una configurazione appropriata.

Gestione della memoria

I modelli Core ML vengono caricati in memoria al primo VNCoreMLRequest e rimangono lì fino allo scaricamento dell’app. Per modelli superiori a 200 MB, Apple raccomanda di caricarli su richiesta e scaricarli tramite MLModel.release(). VNCoreMLModel gestisce autonomamente la cache, ma è possibile controllarla tramite autoreleasepool.

Elaborazione batch

Per l’elaborazione batch di immagini, creare un VNCoreMLRequest e riutilizzarlo con diversi VNImageRequestHandler. Non creare un nuovo VNCoreMLRequest per ogni immagine — ciò rallenterà l’elaborazione a causa del caricamento ripetuto del modello. Il riutilizzo della richiesta offre un guadagno di prestazioni fino al 40% durante l’elaborazione di 10+ immagini.

swift
// Corretto: richiesta singola per tutte le immagini
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 si aggiorna ad ogni chiamata
}

Selezione del dispositivo: per impostazione predefinita, Vision seleziona Neural Engine per modelli compatibili su dispositivi A12+. Se il modello non supporta Neural Engine, Vision utilizza GPU o CPU. È possibile forzare la specifica del dispositivo tramite MLModelConfiguration.computeUnits, ma Apple raccomanda di lasciare la selezione automatica.

Secondo Apple Performance Benchmarks 2024, VNCoreMLRequest su Neural Engine (iPhone 15 Pro) elabora la classificazione MobileNetV2 in 3–5 ms, su GPU — 8–12 ms, su CPU — 20–30 ms. La differenza diventa critica per le applicazioni in tempo reale che elaborano 30+ fotogrammi al secondo.

Domande frequenti

Si può usare VNCoreMLRequest senza Vision — direttamente con Core ML?

Sì, Core ML può essere utilizzato direttamente tramite MLModel.prediction() senza Vision. Tuttavia, VNCoreMLRequest automatizza la preelaborazione delle immagini (ridimensionamento, ritaglio, conversione in CVPixelBuffer). Se il modello accetta non un’immagine ma MultiArray o Double — utilizzare Core ML direttamente. VNCoreMLRequest è solo per modelli con Image Feature come input.

Come aggiornare VNCoreMLRequest quando viene rilasciata una nuova versione del modello?

Creare un nuovo VNCoreMLModel dal MLModel aggiornato e un nuovo VNCoreMLRequest. La vecchia richiesta continuerà a utilizzare la vecchia versione del modello. Per gli aggiornamenti remoti dei modelli, utilizzare MLModel.compileModel(at:) per compilare il modello sul dispositivo da un file .mlmodelc scaricato dal server.

VNCoreMLRequest supporta modelli con input multipli?

VNCoreMLRequest supporta solo modelli con un singolo input Image Feature. Se il modello ha input multipli (ad esempio, immagine + testo), utilizzare Core ML direttamente tramite MLModel. Vision non può passare parametri aggiuntivi oltre all’immagine.

Qual è la dimensione massima dell’immagine per VNCoreMLRequest?

Il limite è di 8192 x 8192 pixel per CGImage passato a VNImageRequestHandler. Tuttavia, i modelli Core ML di solito prevedono un input di 224x224, 299x299 o 512x512. Vision ridimensiona automaticamente le immagini grandi alla dimensione di input. Se l’immagine originale è troppo grande, ridurla preventivamente tramite CGImage per risparmiare memoria.

Si può eseguire VNCoreMLRequest in background?

Sì, impostare preferBackgroundProcessing = true su VNRequest. Ciò consente a Vision di posticipare l’esecuzione della richiesta se il sistema si trova in una modalità ad alta intensità di risorse (ad esempio, caricamento di contenuti). Inoltre, utilizzare DispatchQueue.global(qos: .background) per chiamare handler.perform().

Riepilogo

  • VNCoreMLRequest — una sottoclasse di VNRequest per eseguire modelli Core ML nella pipeline Vision con preelaborazione automatica delle immagini.
  • VNCoreMLModel incapsula MLModel per Vision, convertendo automaticamente CGImage in CVPixelBuffer della dimensione e dello spazio colore richiesti.
  • imageCropAndScaleOption (centerCrop, scaleFill, scaleFit) determina la strategia di ridimensionamento e influisce sulla precisione del modello del 15–25%.
  • Combinazione con VNDetectFaceRectanglesRequest e altri VNRequest consente di costruire pipeline “rilevamento → classificazione” con regionOfInterest.
  • I risultati vengono restituiti come VNClassificationObservation (per classificazione) o VNCoreMLFeatureValueObservation (per regressione/altri tipi).
  • Riutilizzare un singolo VNCoreMLRequest per l’elaborazione batch offre un guadagno di prestazioni fino al 40% rispetto alla creazione di uno nuovo per ogni immagine.
  • Le prestazioni su Neural Engine (3–5 ms su MobileNetV2) sono 4–6 volte superiori rispetto alla CPU, il che è fondamentale per le applicazioni in tempo reale.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche