VNCoreMLRequest — est une sous-classe de VNRequest qui permet d’exécuter des modèles Core ML dans le pipeline Vision, combinant les avantages des détecteurs prêts à l’emploi de Vision (visages, texte, objets) avec des modèles ML personnalisés pour la classification et la régression. Selon Apple Machine Learning Documentation (2024), VNCoreMLRequest gère automatiquement le prétraitement d’image — mise à l’échelle, recadrage et conversion d’espace colorimétrique — en fonction des exigences du modèle Core ML.
Points clés
VNCoreMLRequest est une sous-classe de VNRequest, ajoutée dans iOS 11 avec Vision, qui permet d’exécuter des modèles Core ML dans le contexte de Vision. Il gère tout le prétraitement d’image requis par le modèle Core ML : redimensionnement, recadrage, normalisation et conversion d’espace colorimétrique.
Sans VNCoreMLRequest, un développeur devrait convertir manuellement UIImage/CGImage en MultiArray (MLMultiArray) ou PixelBuffer (CVPixelBuffer) de la taille requise. VNCoreMLRequest automatise ce processus : vous passez un CGImage via VNImageRequestHandler, et VNCoreMLRequest le met à l’échelle pour l’entrée du modèle.
VNCoreMLRequest hérite de toutes les capacités de VNRequest : gestionnaire d’achèvement, regionOfInterest, possibilité d’exécuter plusieurs requêtes simultanément, prise en charge de VNImageRequestHandler et VNSequenceRequestHandler.
import Vision
import CoreML
// 1. Charger et encapsuler le modèle
guard let model = try VNCoreMLModel(
for: MobileNetV2().model)
else { return }
// 2. Créer 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. Exécuter via le gestionnaire
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])
VNCoreMLRequest prend en charge les modèles avec différents types d’entrée : images (Image Feature), MultiArray et Double. Pour les images, Vision convertit automatiquement CGImage en CVPixelBuffer de la taille et de l’espace colorimétrique nécessaires. Pour les autres types de données d’entrée, utilisez Core ML directement sans Vision.
Selon Apple WWDC 2023, VNCoreMLRequest est utilisé dans 40% de toutes les applications iOS qui utilisent Core ML pour le traitement d’images. C’est la méthode la plus populaire pour intégrer des modèles ML dans les applications iOS.
VNCoreMLModel est un wrapper qui adapte le modèle Core ML (MLModel) pour une utilisation dans Vision. Il convertit les données d’entrée et de sortie du modèle dans un format compréhensible par Vision : image → CVPixelBuffer, résultat → VNObservation.
L’initialisation de VNCoreMLModel vérifie la compatibilité du modèle avec Vision : le modèle doit accepter une image comme entrée (Image Feature) et retourner une classification (MLMultiArray ou Dictionary). Si le modèle est incompatible, l’initialisateur génère une erreur.
import Vision
import CoreML
// Option 1: Depuis .mlmodel (compilé au moment de la construction)
let model1 = try VNCoreMLModel(
for: MyVisionModel().model)
// Option 2: Depuis .mlmodelc (compilé sur l’appareil)
let compiledURL = Bundle.main.url(
forResource: "MyVisionModel",
withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
for: MLModel(contentsOf: compiledURL))
VNCoreMLModel met en cache le modèle en mémoire après le premier chargement. Recharger le même modèle renvoie l’instance mise en cache, ce qui accélère les requêtes ultérieures. Cependant, si le modèle pèse plus de 100 Mo, iOS peut le décharger de la mémoire en cas de pénurie de ressources — dans ce cas, VNCoreMLModel rechargera le modèle automatiquement.
Pour les modèles entraînés avec Create ML, VNCoreMLModel fonctionne sans configuration supplémentaire. Create ML exporte les modèles avec les métadonnées correctes que Vision reconnaît automatiquement — il suffit de passer le modèle à VNCoreMLModel(model:).
imageCropAndScaleOption est une propriété clé de VNCoreMLRequest qui détermine comment Vision transforme l’image source pour correspondre à la taille d’entrée du modèle Core ML. Le choix de la bonne option affecte directement la précision de la classification.
.centerCrop recadre l’image du centre en un carré, puis la met à l’échelle de la taille d’entrée du modèle. Convient aux modèles entraînés sur des objets centrés (la plupart des classifieurs ImageNet). .scaleFill étire l’image à la taille d’entrée sans conserver les proportions. Rapide, mais déforme la géométrie. .scaleFit met à l’échelle en conservant les proportions, ajoutant des letterbox (barres noires) sur les bords.
import Vision
let request = VNCoreMLRequest(model: model)
// .centerCrop — pour objets centrés (par défaut)
request.imageCropAndScaleOption = .centerCrop
// .scaleFill — pour textures uniformes (sans distorsion)
request.imageCropAndScaleOption = .scaleFill
// .scaleFit — quand les proportions de l’objet comptent
request.imageCropAndScaleOption = .scaleFit
Recommandations : pour la plupart des modèles de classification, utilisez .centerCrop — il offre le meilleur équilibre entre précision et performances. Si le modèle a été entraîné sur des images avec proportions conservées (par exemple, détection d’anomalies sur des photos de documents), choisissez .scaleFit avec letterbox.
Selon Apple Developer Documentation 2024, un mauvais choix de imageCropAndScaleOption peut réduire la précision du modèle de 15–25%. Par exemple, .scaleFill pour un visage situé au bord du cadre peut en couper une partie avec .centerCrop ou déformer les proportions avec .scaleFill.
La principale force de VNCoreMLRequest est la possibilité de le combiner avec d’autres VNRequest dans un seul appel perform(). Cela permet de construire des pipelines : d’abord détecter les visages (VNDetectFaceRectanglesRequest), puis classer chaque visage via un modèle Core ML personnalisé (VNCoreMLRequest).
VNCoreMLRequest prend également en charge regionOfInterest — si vous définissez cette zone, Vision recadrera l’image au rectangle spécifié avant de la transmettre au modèle Core ML. Ceci est crucial pour les pipelines : après la détection du visage, vous passez sa boîte englobante comme regionOfInterest pour VNCoreMLRequest.
import Vision
// 1. Détection de visage
let faceRequest = VNDetectFaceRectanglesRequest()
// 2. Classification des émotions via Core ML
guard let emotionModel = try VNCoreMLModel(
for: EmotionClassifier().model)
else { return }
let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])
// 3. Définir regionOfInterest pour chaque visage
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
emotionRequest.regionOfInterest = face.boundingBox
try handler.perform([emotionRequest])
// Traiter le résultat de classification des émotions
}
Limitation : regionOfInterest pour VNCoreMLRequest a un sens lorsque le modèle est entraîné sur des images de même taille et proportion. Si le modèle attend une entrée strictement carrée (224x224), .centerCrop avec regionOfInterest donnera le meilleur résultat.
Selon Apple ML Research, le pipeline «détection → classification» via regionOfInterest offre une amélioration de précision de 20–30% par rapport à la classification de l’image entière, car le modèle ML ne reçoit que la zone pertinente sans bruit de fond.
| Type de pipeline | Requête 1 (détection) | Requête 2 (ML) | Exemple |
|---|---|---|---|
| Visage → émotion | VNDetectFaceRectanglesRequest | VNCoreMLRequest | Détection d’humeur |
| Objet → marque | VNDetectObjectAtPointRequest | VNCoreMLRequest | Reconnaissance de logos |
| Texte → langue | VNRecognizeTextRequest | VNCoreMLRequest | Classification de langue du texte |
| Scène → description | VNClassifyImageRequest | VNCoreMLRequest | Génération de tags |
VNCoreMLRequest retourne les résultats sous forme de VNClassificationObservation (pour les modèles de classification) ou VNCoreMLFeatureValueObservation (pour la régression et autres types). Le type de résultat dépend des données de sortie du modèle Core ML.
VNClassificationObservation contient identifier (nom de la classe) et confidence. Les modèles avec sortie softmax retournent un tableau de ces observations triées par confidence décroissante. VNCoreMLFeatureValueObservation contient une valeur MLFeatureValue arbitraire — peut être MultiArray, Double, String ou Dictionary.
// Pour les modèles de classification
if let classificationResults = request.results
as? [VNClassificationObservation] {
for result in classificationResults
where result.confidence > 0.5 {
print("\\(result.identifier): \\(result.confidence)")
}
}
// Pour les modèles de régression (valeurs de caractéristiques)
if let featureResults = request.results
as? [VNCoreMLFeatureValueObservation] {
for result in featureResults {
let value = result.featureValue
print("\\(result.featureName): \\(value)")
}
}
Filtrage par confidence : Apple recommande de rejeter les résultats avec confidence < 0,3 pour les classifieurs généraux et < 0,7 pour les applications critiques. Pour les modèles entraînés sur des ensembles de données équilibrés, la confidence est corrélée avec la probabilité de réponse correcte mais ne la garantit pas.
VNCoreMLFeatureValueObservation.featureName correspond au nom de la couche de sortie du modèle (par exemple, « classLabel » ou « features »). Cela permet de gérer les modèles avec plusieurs sorties — chaque sortie est représentée par une observation séparée avec un featureName unique.
VNCoreMLRequest est optimisé pour fonctionner sur Neural Engine (A12+), GPU et CPU. Vision sélectionne automatiquement le meilleur périphérique pour l’exécution du modèle en fonction de son type et de sa taille. Cependant, les performances peuvent encore être améliorées avec une configuration appropriée.
Les modèles Core ML sont chargés en mémoire lors du premier VNCoreMLRequest et y restent jusqu’à ce que l’application soit déchargée. Pour les modèles de plus de 200 Mo, Apple recommande de les charger à la demande et de les décharger via MLModel.release(). VNCoreMLModel gère lui-même la mise en cache, mais vous pouvez la contrôler via autoreleasepool.
Pour le traitement par lots d’images, créez un VNCoreMLRequest et réutilisez-le avec différents VNImageRequestHandler. Ne créez pas un nouveau VNCoreMLRequest pour chaque image — cela ralentira le traitement en raison du chargement répété du modèle. La réutilisation de la requête offre un gain de performances allant jusqu’à 40% lors du traitement de 10+ images.
// Correct: requête unique pour toutes les 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 se met à jour à chaque appel
}
Sélection du périphérique : par défaut, Vision sélectionne Neural Engine pour les modèles compatibles sur les appareils A12+. Si le modèle ne prend pas en charge Neural Engine, Vision utilise GPU ou CPU. Vous pouvez forcer la spécification du périphérique via MLModelConfiguration.computeUnits, mais Apple recommande de laisser la sélection automatique.
Selon Apple Performance Benchmarks 2024, VNCoreMLRequest sur Neural Engine (iPhone 15 Pro) traite la classification MobileNetV2 en 3–5 ms, sur GPU en 8–12 ms, sur CPU en 20–30 ms. La différence devient critique pour les applications en temps réel traitant 30+ images par seconde.
Foire aux questions
Oui, Core ML peut être utilisé directement via MLModel.prediction() sans Vision. Cependant, VNCoreMLRequest automatise le prétraitement d’image (mise à l’échelle, recadrage, conversion en CVPixelBuffer). Si le modèle accepte non pas une image mais MultiArray ou Double — utilisez Core ML directement. VNCoreMLRequest est uniquement pour les modèles avec Image Feature en entrée.
Créez un nouveau VNCoreMLModel à partir du MLModel mis à jour et un nouveau VNCoreMLRequest. L’ancienne requête continuera d’utiliser l’ancienne version du modèle. Pour les mises à jour à distance des modèles, utilisez MLModel.compileModel(at:) pour compiler le modèle sur l’appareil à partir d’un fichier .mlmodelc téléchargé depuis le serveur.
VNCoreMLRequest ne prend en charge que les modèles avec une seule entrée Image Feature. Si le modèle a plusieurs entrées (par exemple, image + texte), utilisez Core ML directement via MLModel. Vision ne peut pas passer de paramètres supplémentaires en dehors de l’image.
La limite est de 8192 x 8192 pixels pour CGImage passé à VNImageRequestHandler. Cependant, les modèles Core ML attendent généralement une entrée de 224x224, 299x299 ou 512x512. Vision met automatiquement à l’échelle les grandes images à la taille d’entrée. Si l’image originale est trop grande, réduisez-la au préalable via CGImage pour économiser de la mémoire.
Oui, définissez preferBackgroundProcessing = true sur VNRequest. Cela permet à Vision de différer l’exécution de la requête si le système est dans un mode gourmand en ressources (par exemple, chargement de contenu). Assurez-vous également d’utiliser DispatchQueue.global(qos: .background) pour appeler handler.perform().
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi