VNCoreMLRequest — ist eine Unterklasse von VNRequest, die es ermöglicht, Core ML Modelle innerhalb der Vision-Pipeline auszuführen und dabei die Vorteile der vorgefertigten Vision-Detektoren (Gesichter, Text, Objekte) mit benutzerdefinierten ML-Modellen für Klassifikation und Regression zu kombinieren. Laut Apple Machine Learning Documentation (2024) verarbeitet VNCoreMLRequest automatisch die Bildvorverarbeitung — Skalierung, Zuschneiden und Farbraumkonvertierung — entsprechend den Anforderungen des Core ML Modells.
Wichtige Erkenntnisse
VNCoreMLRequest ist eine Unterklasse von VNRequest, die in iOS 11 zusammen mit Vision hinzugefügt wurde und es ermöglicht, Core ML Modelle im Kontext von Vision auszuführen. Es übernimmt die gesamte vom Core ML Modell benötigte Bildvorverarbeitung: Größenanpassung, Zuschneiden, Normalisierung und Farbraumkonvertierung.
Ohne VNCoreMLRequest müsste ein Entwickler UIImage/CGImage manuell in MultiArray (MLMultiArray) oder PixelBuffer (CVPixelBuffer) der erforderlichen Größe konvertieren. VNCoreMLRequest automatisiert diesen Prozess: Sie übergeben ein CGImage über VNImageRequestHandler, und VNCoreMLRequest skaliert es auf die Modelleingabe.
VNCoreMLRequest erbt alle Fähigkeiten von VNRequest: Completion Handler, regionOfInterest, die Möglichkeit, mehrere Anfragen gleichzeitig auszuführen, Unterstützung für VNImageRequestHandler und VNSequenceRequestHandler.
import Vision
import CoreML
// 1. Modell laden und kapseln
guard let model = try VNCoreMLModel(
for: MobileNetV2().model)
else { return }
// 2. VNCoreMLRequest erstellen
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. über Handler ausführen
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])
VNCoreMLRequest unterstützt Modelle mit verschiedenen Eingabetypen: Bilder (Image Feature), MultiArray und Double. Für Bilder konvertiert Vision automatisch CGImage in CVPixelBuffer der erforderlichen Größe und des erforderlichen Farbraums. Für andere Eingabedatentypen verwenden Sie Core ML direkt ohne Vision.
Laut Apple WWDC 2023 wird VNCoreMLRequest in 40% aller iOS-Apps verwendet, die Core ML für die Bildverarbeitung einsetzen. Dies ist die beliebteste Methode zur Integration von ML-Modellen in iOS-Apps.
VNCoreMLModel ist ein Wrapper, der das Core ML Modell (MLModel) für die Verwendung in Vision anpasst. Es konvertiert die Eingabe- und Ausgabedaten des Modells in ein für Vision verständliches Format: Bild → CVPixelBuffer, Ergebnis → VNObservation.
Die Initialisierung von VNCoreMLModel prüft die Kompatibilität des Modells mit Vision: Das Modell muss ein Bild als Eingabe (Image Feature) akzeptieren und eine Klassifikation (MLMultiArray oder Dictionary) zurückgeben. Wenn das Modell inkompatibel ist, wirft der Initialisierer einen Fehler.
import Vision
import CoreML
// Option 1: Von .mlmodel (zur Build-Zeit kompiliert)
let model1 = try VNCoreMLModel(
for: MyVisionModel().model)
// Option 2: Von .mlmodelc (auf Gerät kompiliert)
let compiledURL = Bundle.main.url(
forResource: "MyVisionModel",
withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
for: MLModel(contentsOf: compiledURL))
VNCoreMLModel cacht das Modell nach dem ersten Laden im Speicher. Das erneute Laden desselben Modells gibt die gecachte Instanz zurück, was nachfolgende Anfragen beschleunigt. Wenn das Modell jedoch mehr als 100 MB wiegt, kann iOS es bei Ressourcenknappheit aus dem Speicher entfernen — in diesem Fall lädt VNCoreMLModel das Modell automatisch neu.
Für Modelle, die mit Create ML trainiert wurden, funktioniert VNCoreMLModel ohne zusätzliche Konfiguration. Create ML exportiert Modelle mit den korrekten Metadaten, die Vision automatisch erkennt — übergeben Sie das Modell einfach an VNCoreMLModel(model:).
imageCropAndScaleOption ist eine Schlüsseleigenschaft von VNCoreMLRequest, die bestimmt, wie Vision das Quellbild an die Eingabegröße des Core ML Modells anpasst. Die Wahl der richtigen Option wirkt sich direkt auf die Klassifikationsgenauigkeit aus.
.centerCrop schneidet das Bild von der Mitte zu einem Quadrat zu und skaliert es dann auf die Modelleingabegröße. Geeignet für Modelle, die auf zentrierten Objekten trainiert wurden (die meisten ImageNet-Klassifikatoren). .scaleFill dehnt das Bild ohne Beibehaltung der Proportionen auf die Eingabegröße. Schnell, aber verzerrt die Geometrie. .scaleFit skaliert unter Beibehaltung der Proportionen und fügt an den Rändern Letterbox (schwarze Balken) hinzu.
import Vision
let request = VNCoreMLRequest(model: model)
// .centerCrop — für zentrierte Objekte (Standard)
request.imageCropAndScaleOption = .centerCrop
// .scaleFill — für gleichmäßige Texturen (keine Verzerrung)
request.imageCropAndScaleOption = .scaleFill
// .scaleFit — wenn Objektproportionen wichtig sind
request.imageCropAndScaleOption = .scaleFit
Empfehlungen: Verwenden Sie für die meisten Klassifikationsmodelle .centerCrop — er bietet das beste Gleichgewicht zwischen Genauigkeit und Leistung. Wenn das Modell auf Bildern mit beibehaltenen Proportionen trainiert wurde (z. B. Anomalieerkennung auf Dokumentenfotos), wählen Sie .scaleFit mit Letterbox.
Laut Apple Developer Documentation 2024 kann eine falsche Wahl von imageCropAndScaleOption die Modellgenauigkeit um 15–25% verringern. Beispielsweise kann .scaleFill bei einem Gesicht am Bildrand einen Teil davon mit .centerCrop abschneiden oder die Proportionen mit .scaleFill verzerren.
Die Hauptstärke von VNCoreMLRequest ist die Möglichkeit, es mit anderen VNRequest in einem einzigen perform()-Aufruf zu kombinieren. Dies ermöglicht den Aufbau von Pipelines: Zuerst Gesichter erkennen (VNDetectFaceRectanglesRequest), dann jedes Gesicht durch ein benutzerdefiniertes Core ML Modell (VNCoreMLRequest) klassifizieren.
VNCoreMLRequest unterstützt auch regionOfInterest — wenn Sie diesen Bereich festlegen, schneidet Vision das Bild vor der Übergabe an das Core ML Modell auf das angegebene Rechteck zu. Dies ist kritisch für Pipelines: Nach der Gesichtserkennung übergeben Sie dessen Begrenzungsrahmen als regionOfInterest für VNCoreMLRequest.
import Vision
// 1. Gesichtserkennung
let faceRequest = VNDetectFaceRectanglesRequest()
// 2. Emotionsklassifikation via Core ML
guard let emotionModel = try VNCoreMLModel(
for: EmotionClassifier().model)
else { return }
let emotionRequest = VNCoreMLRequest(model: emotionModel)
try handler.perform([faceRequest, emotionRequest])
// 3. regionOfInterest für jedes Gesicht setzen
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
emotionRequest.regionOfInterest = face.boundingBox
try handler.perform([emotionRequest])
// Emotionsklassifikationsergebnis verarbeiten
}
Einschränkung: regionOfInterest für VNCoreMLRequest ist sinnvoll, wenn das Modell auf Bildern derselben Größe und Proportion trainiert wurde. Wenn das Modell eine streng quadratische Eingabe (224x224) erwartet, liefert .centerCrop mit regionOfInterest das beste Ergebnis.
Laut Apple ML Research bietet die Pipeline „Erkennung → Klassifikation“ über regionOfInterest eine Genauigkeitsverbesserung von 20–30% im Vergleich zur Klassifikation des gesamten Bildes, da das ML-Modell nur den relevanten Bereich ohne Hintergrundrauschen erhält.
| Pipeline-Typ | Anfrage 1 (Erkennung) | Anfrage 2 (ML) | Beispiel |
|---|---|---|---|
| Gesicht → Emotion | VNDetectFaceRectanglesRequest | VNCoreMLRequest | Stimmungserkennung |
| Objekt → Marke | VNDetectObjectAtPointRequest | VNCoreMLRequest | Logoerkennung |
| Text → Sprache | VNRecognizeTextRequest | VNCoreMLRequest | Textsprachenklassifikation |
| Szene → Beschreibung | VNClassifyImageRequest | VNCoreMLRequest | Tag-Erzeugung |
VNCoreMLRequest gibt Ergebnisse als VNClassificationObservation (für Klassifikationsmodelle) oder VNCoreMLFeatureValueObservation (für Regression und andere Typen) zurück. Der Ergebnistyp hängt von den Ausgabedaten des Core ML Modells ab.
VNClassificationObservation enthält identifier (Klassenname) und confidence. Modelle mit Softmax-Ausgabe geben ein Array dieser Beobachtungen zurück, sortiert nach absteigendem confidence. VNCoreMLFeatureValueObservation enthält einen beliebigen MLFeatureValue — kann MultiArray, Double, String oder Dictionary sein.
// Für Klassifikationsmodelle
if let classificationResults = request.results
as? [VNClassificationObservation] {
for result in classificationResults
where result.confidence > 0.5 {
print("\\(result.identifier): \\(result.confidence)")
}
}
// Für Regressionsmodelle (Merkmalwerte)
if let featureResults = request.results
as? [VNCoreMLFeatureValueObservation] {
for result in featureResults {
let value = result.featureValue
print("\\(result.featureName): \\(value)")
}
}
Confidence-Filterung: Apple empfiehlt, Ergebnisse mit confidence < 0,3 für allgemeine Klassifikatoren und < 0,7 für kritische Anwendungen zu verwerfen. Bei Modellen, die auf ausgewogenen Datensätzen trainiert wurden, korreliert confidence mit der Wahrscheinlichkeit der richtigen Antwort, garantiert sie jedoch nicht.
VNCoreMLFeatureValueObservation.featureName entspricht dem Namen der Ausgabeschicht des Modells (z. B. „classLabel“ oder „features“). Dies ermöglicht die Handhabung von Modellen mit mehreren Ausgaben — jede Ausgabe wird durch eine separate Beobachtung mit einem eindeutigen featureName dargestellt.
VNCoreMLRequest ist für die Arbeit auf Neural Engine (A12+), GPU und CPU optimiert. Vision wählt automatisch das beste Gerät für die Modellausführung basierend auf Typ und Größe aus. Die Leistung kann jedoch durch geeignete Konfiguration weiter verbessert werden.
Core ML Modelle werden beim ersten VNCoreMLRequest in den Speicher geladen und bleiben dort, bis die App entladen wird. Für Modelle größer als 200 MB empfiehlt Apple, sie bei Bedarf zu laden und über MLModel.release() zu entladen. VNCoreMLModel verwaltet das Caching selbst, Sie können es jedoch über autoreleasepool steuern.
Für die Stapelverarbeitung von Bildern erstellen Sie einen VNCoreMLRequest und verwenden ihn mit verschiedenen VNImageRequestHandler wieder. Erstellen Sie keinen neuen VNCoreMLRequest für jedes Bild — dies verlangsamt die Verarbeitung aufgrund wiederholten Modellladens. Die Wiederverwendung der Anfrage bietet einen Leistungsgewinn von bis zu 40% bei der Verarbeitung von 10+ Bildern.
// Richtig: einzelne Anfrage für alle Bilder
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 aktualisiert bei jedem Aufruf
}
Geräteauswahl: Standardmäßig wählt Vision Neural Engine für kompatible Modelle auf A12+ Geräten. Wenn das Modell Neural Engine nicht unterstützt, verwendet Vision GPU oder CPU. Sie können das Gerät über MLModelConfiguration.computeUnits erzwingen, aber Apple empfiehlt, die automatische Auswahl zu belassen.
Laut Apple Performance Benchmarks 2024 verarbeitet VNCoreMLRequest auf Neural Engine (iPhone 15 Pro) die MobileNetV2-Klassifikation in 3–5 ms, auf GPU in 8–12 ms, auf CPU in 20–30 ms. Der Unterschied wird für Echtzeitanwendungen, die 30+ Bilder pro Sekunde verarbeiten, kritisch.
Häufig gestellte Fragen
Ja, Core ML kann direkt über MLModel.prediction() ohne Vision verwendet werden. Allerdings automatisiert VNCoreMLRequest die Bildvorverarbeitung (Skalierung, Zuschneiden, Konvertierung in CVPixelBuffer). Wenn das Modell kein Bild, sondern MultiArray oder Double akzeptiert — verwenden Sie Core ML direkt. VNCoreMLRequest ist nur für Modelle mit Image Feature als Eingabe.
Erstellen Sie ein neues VNCoreMLModel aus dem aktualisierten MLModel und einen neuen VNCoreMLRequest. Die alte Anfrage verwendet weiterhin die alte Modellversion. Für entfernte Modellaktualisierungen verwenden Sie MLModel.compileModel(at:) zum Kompilieren des Modells auf dem Gerät aus einer vom Server heruntergeladenen .mlmodelc-Datei.
VNCoreMLRequest unterstützt nur Modelle mit einer einzigen Image Feature Eingabe. Wenn das Modell mehrere Eingaben hat (z. B. Bild + Text), verwenden Sie Core ML direkt über MLModel. Vision kann außer dem Bild keine zusätzlichen Parameter übergeben.
Die Grenze liegt bei 8192 x 8192 Pixeln für CGImage, das an VNImageRequestHandler übergeben wird. Core ML Modelle erwarten jedoch normalerweise eine Eingabe von 224x224, 299x299 oder 512x512. Vision skaliert große Bilder automatisch auf die Eingabegröße. Wenn das Originalbild zu groß ist, verkleinern Sie es vorher über CGImage, um Speicher zu sparen.
Ja, setzen Sie preferBackgroundProcessing = true auf VNRequest. Dies ermöglicht Vision, die Anfrageausführung zu verschieben, wenn sich das System in einem ressourcenintensiven Modus befindet (z. B. Inhaltsladung). Verwenden Sie außerdem DispatchQueue.global(qos: .background) zum Aufrufen von handler.perform().
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch