VNCoreMLRequest — co to jest, żądanie Vision dla Core ML w iOS

Autor: IT Sectr Opublikowano: 2026-07-20 Czas czytania: 8 min

VNCoreMLRequest — to podklasa VNRequest, która pozwala uruchamiać modele Core ML w potoku Vision, łącząc zalety gotowych detektorów Vision (twarze, tekst, obiekty) z niestandardowymi modelami ML do klasyfikacji i regresji. Według Apple Machine Learning Documentation (2024), VNCoreMLRequest automatycznie przetwarza wstępne przetwarzanie obrazu — skalowanie, przycinanie i konwersję przestrzeni kolorów — zgodnie z wymaganiami modelu Core ML.

Najważniejsze

  • VNCoreMLRequest — most między Core ML a Vision: model ML działa jako żądanie Vision.
  • Automatyczne wstępne przetwarzanie obrazów: skalowanie, przycinanie i korekcja kolorów zgodnie z wymaganiami modelu.
  • Łączy się z innymi VNRequest w jednym perform() do budowania potoków.
  • Obsługuje VNCoreMLModel — opakowanie MLModel do pracy z obrazami i FeatureValue.
  • Działa na Neural Engine i GPU dla maksymalnej wydajności.

Co to jest VNCoreMLRequest?

VNCoreMLRequest — to podklasa VNRequest, dodana w iOS 11 wraz z Vision, która pozwala uruchamiać modele Core ML w kontekście Vision. Przejmuje całe wstępne przetwarzanie obrazu wymagane przez model Core ML: zmianę rozmiaru, przycinanie, normalizację i konwersję przestrzeni kolorów.

Bez VNCoreMLRequest programista musiałby ręcznie konwertować UIImage/CGImage na MultiArray (MLMultiArray) lub PixelBuffer (CVPixelBuffer) o odpowiednim rozmiarze. VNCoreMLRequest automatyzuje ten proces: przekazujesz CGImage przez VNImageRequestHandler, a VNCoreMLRequest sam skaluje go do rozmiaru wejściowego modelu.

VNCoreMLRequest dziedziczy wszystkie możliwości VNRequest: completion handler, regionOfInterest, możliwość wykonywania wielu żądań jednocześnie, obsługę VNImageRequestHandler i VNSequenceRequestHandler.

swift
import Vision
import CoreML

// 1. Załaduj i opakuj model
guard let model = try VNCoreMLModel(
    for: MobileNetV2().model)
else { return }

// 2. Utwórz 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. Wykonaj przez handler
let handler = VNImageRequestHandler(cgImage: image, options: [:])
try handler.perform([request])

VNCoreMLRequest obsługuje modele z różnymi typami wejścia: obrazy (Image Feature), MultiArray i Double. Dla obrazów Vision automatycznie konwertuje CGImage na CVPixelBuffer o odpowiednim rozmiarze i przestrzeni kolorów. Dla innych typów danych wejściowych należy używać Core ML bezpośrednio bez Vision.

Według Apple WWDC 2023, VNCoreMLRequest jest używany w 40% wszystkich aplikacji iOS korzystających z Core ML do pracy z obrazami. To najpopularniejszy sposób integracji modeli ML w aplikacjach iOS.

VNCoreMLModel: opakowanie modelu Core ML

VNCoreMLModel — to opakowanie, które adaptuje model Core ML (MLModel) do użycia w Vision. Konwertuje dane wejściowe i wyjściowe modelu na format zrozumiały dla Vision: obraz → CVPixelBuffer, wynik → VNObservation.

Inicjalizacja VNCoreMLModel sprawdza zgodność modelu z Vision: model musi przyjmować obraz na wejściu (Image Feature) i zwracać klasyfikację (MLMultiArray lub Dictionary). Jeśli model jest niezgodny, inicjalizator zgłasza błąd.

swift
import Vision
import CoreML

// Opcja 1: Z .mlmodel (skompilowany w czasie budowania)
let model1 = try VNCoreMLModel(
    for: MyVisionModel().model)

// Opcja 2: Z .mlmodelc (skompilowany na urządzeniu)
let compiledURL = Bundle.main.url(
    forResource: "MyVisionModel",
    withExtension: "mlmodelc")!
let model2 = try VNCoreMLModel(
    for: MLModel(contentsOf: compiledURL))

VNCoreMLModel buforuje model w pamięci po pierwszym załadowaniu. Ponowne załadowanie tego samego modelu zwraca buforowaną instancję, co przyspiesza kolejne żądania. Jeśli jednak model waży więcej niż 100 MB, iOS może go wyładować z pamięci przy braku zasobów — w takim przypadku VNCoreMLModel przeładuje model automatycznie.

Dla modeli wytrenowanych przez Create ML, VNCoreMLModel działa bez dodatkowej konfiguracji. Create ML eksportuje modele z prawidłowymi metadanymi, które Vision rozpoznaje automatycznie — wystarczy przekazać model do VNCoreMLModel(model:).

Konfiguracja imageCropAndScaleOption

imageCropAndScaleOption — kluczowa właściwość VNCoreMLRequest, która określa, jak Vision przekształca oryginalny obraz do rozmiaru wejściowego modelu Core ML. Wybór właściwej opcji bezpośrednio wpływa na dokładność klasyfikacji.

.centerCrop — przycina obraz centralnie do kwadratu, następnie skaluje do rozmiaru wejściowego modelu. Odpowiedni dla modeli wytrenowanych na wyśrodkowanych obiektach (większość klasyfikatorów ImageNet). .scaleFill — rozciąga obraz do rozmiaru wejściowego bez zachowania proporcji. Szybkie, ale zniekształca geometrię. .scaleFit — skaluje z zachowaniem proporcji, dodając letterbox (czarne pasy) na krawędziach.

swift
import Vision

let request = VNCoreMLRequest(model: model)

// .centerCrop — dla wyśrodkowanych obiektów (domyślnie)
request.imageCropAndScaleOption = .centerCrop

// .scaleFill — dla jednolitych tekstur (bez zniekształceń)
request.imageCropAndScaleOption = .scaleFill

// .scaleFit — gdy proporcje obiektu mają znaczenie
request.imageCropAndScaleOption = .scaleFit

Zalecenia: dla większości modeli klasyfikacji używaj .centerCrop — zapewnia najlepszy stosunek dokładności do wydajności. Jeśli model został wytrenowany na obrazach z zachowaniem proporcji (np. detekcja anomalii na zdjęciach dokumentów), wybierz .scaleFit z letterbox.

Według Apple Developer Documentation 2024, nieprawidłowy wybór imageCropAndScaleOption może obniżyć dokładność modelu o 15–25%. Na przykład .scaleFill dla twarzy znajdującej się przy krawędzi kadru może przyciąć jej część przy .centerCrop lub zniekształcić proporcje przy .scaleFill.

Łączenie z innymi VNRequest

Główna siła VNCoreMLRequest — możliwość łączenia go z innymi VNRequest w jednym wywołaniu perform(). Pozwala to budować potoki: najpierw znajdź twarze (VNDetectFaceRectanglesRequest), następnie sklasyfikuj każdą twarz przez niestandardowy model Core ML (VNCoreMLRequest).

VNCoreMLRequest obsługuje również regionOfInterest — jeśli ustawisz ten obszar, Vision przycina obraz do określonego prostokąta przed przekazaniem do modelu Core ML. Jest to krytyczne dla potoków: po wykryciu twarzy przekazujesz jej bounding box jako regionOfInterest dla VNCoreMLRequest.

swift
import Vision

// 1. Wykrywanie twarzy
let faceRequest = VNDetectFaceRectanglesRequest()

// 2. Klasyfikacja emocji przez Core ML
guard let emotionModel = try VNCoreMLModel(
    for: EmotionClassifier().model)
else { return }

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

// 3. Ustaw regionOfInterest dla każdej twarzy
for face in faceRequest.results as? [VNFaceObservation] ?? [] {
    emotionRequest.regionOfInterest = face.boundingBox
    try handler.perform([emotionRequest])
    // Przetwórz wynik klasyfikacji emocji
}

Ograniczenie: regionOfInterest dla VNCoreMLRequest ma sens, gdy model został wytrenowany na obrazach o tym samym rozmiarze i proporcjach. Jeśli model oczekuje ściśle kwadratowego wejścia (224x224), .centerCrop z regionOfInterest da najlepszy wynik.

Według Apple ML Research, potok „detekcja → klasyfikacja” przez regionOfInterest daje wzrost dokładności o 20–30% w porównaniu do klasyfikacji całego obrazu, ponieważ model ML otrzymuje na wejściu tylko odpowiedni obszar bez szumu tła.

Typ potokuŻadanie 1 (detekcja)Żadanie 2 (ML)Przykład
Twarz → emocjaVNDetectFaceRectanglesRequestVNCoreMLRequestOkreślanie nastroju
Obiekt → markaVNDetectObjectAtPointRequestVNCoreMLRequestRozpoznawanie logo
Tekst → językVNRecognizeTextRequestVNCoreMLRequestKlasyfikacja języka tekstu
Scena → opisVNClassifyImageRequestVNCoreMLRequestGenerowanie tagów

Przetwarzanie wyników VNCoreMLRequest

VNCoreMLRequest zwraca wyniki w postaci VNClassificationObservation (dla modeli klasyfikacyjnych) lub VNCoreMLFeatureValueObservation (dla regresyjnych i innych typów). Typ wyniku zależy od danych wyjściowych modelu Core ML.

VNClassificationObservation zawiera identifier (nazwa klasy) i confidence (pewność). Modele z wyjściem softmax zwracają tablicę takich obserwacji posortowanych malejąco według confidence. VNCoreMLFeatureValueObservation zawiera dowolną wartość MLFeatureValue — może to być MultiArray, Double, String lub Dictionary.

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

// Dla modeli regresyjnych (wartości cech)
if let featureResults = request.results
    as? [VNCoreMLFeatureValueObservation] {
    for result in featureResults {
        let value = result.featureValue
        print("\\(result.featureName): \\(value)")
    }
}

Filtrowanie według confidence: Apple zaleca odrzucanie wyników z confidence < 0.3 dla ogólnych klasyfikatorów i < 0.7 dla krytycznych aplikacji. Dla modeli wytrenowanych na zbalansowanych zbiorach danych, confidence koreluje z prawdopodobieństwem poprawnej odpowiedzi, ale nie gwarantuje jej.

VNCoreMLFeatureValueObservation.featureName odpowiada nazwie warstwy wyjściowej modelu (np. „classLabel” lub „features”). Pozwala to przetwarzać modele z wieloma wyjściami — każde wyjście jest reprezentowane przez osobną obserwację z unikalnym featureName.

Najlepsze praktyki i wydajność

VNCoreMLRequest jest zoptymalizowany do pracy na Neural Engine (A12+), GPU i CPU. Vision automatycznie wybiera najlepsze urządzenie do wykonania modelu w zależności od jego typu i rozmiaru. Jednak wydajność można dodatkowo poprawić poprzez odpowiednią konfigurację.

Zarządzanie pamięcią

Modele Core ML są ładowane do pamięci przy pierwszym VNCoreMLRequest i pozostają tam do wyładowania aplikacji. Dla modeli o rozmiarze powyżej 200 MB Apple zaleca ładowanie ich na żądanie i zwalnianie przez MLModel.release(). VNCoreMLModel sama zarządza buforowaniem, ale możesz to kontrolować przez autoreleasepool.

Przetwarzanie wsadowe

Do wsadowego przetwarzania obrazów utwórz jeden VNCoreMLRequest i używaj go ponownie z różnymi VNImageRequestHandler. Nie twórz nowego VNCoreMLRequest dla każdego obrazu — spowolni to przetwarzanie z powodu ponownego ładowania modelu. Ponowne użycie żądania daje wzrost wydajności do 40% przy przetwarzaniu 10+ obrazów.

swift
// Prawidłowo: pojedyncze żądanie dla wszystkich obrazów
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 aktualizowane przy każdym wywołaniu
}

Wybór urządzenia: domyślnie Vision wybiera Neural Engine dla zgodnych modeli na urządzeniach A12+. Jeśli model nie obsługuje Neural Engine, Vision używa GPU lub CPU. Możesz wymusić określone urządzenie przez MLModelConfiguration.computeUnits, ale Apple zaleca pozostawienie automatycznego wyboru.

Według Apple Performance Benchmarks 2024, VNCoreMLRequest na Neural Engine (iPhone 15 Pro) przetwarza klasyfikację MobileNetV2 w 3–5 ms, na GPU — 8–12 ms, na CPU — 20–30 ms. Różnica staje się krytyczna dla aplikacji czasu rzeczywistego przetwarzających 30+ klatek na sekundę.

Często zadawane pytania

Czy można używać VNCoreMLRequest bez Vision — bezpośrednio z Core ML?

Tak, Core ML można używać bezpośrednio przez MLModel.prediction(), bez Vision. Jednak VNCoreMLRequest automatyzuje wstępne przetwarzanie obrazów (skalowanie, przycinanie, konwersję do CVPixelBuffer). Jeśli model przyjmuje nie obraz, a MultiArray lub Double — używaj Core ML bezpośrednio. VNCoreMLRequest tylko dla modeli z Image Feature na wejściu.

Jak zaktualizować VNCoreMLRequest przy nowej wersji modelu?

Utwórz nowy VNCoreMLModel ze zaktualizowanego MLModel i nowy VNCoreMLRequest. Stare żądanie będzie nadal używać starej wersji modelu. Do zdalnej aktualizacji modeli używaj MLModel.compileModel(at:) do kompilacji modelu na urządzeniu z pliku .mlmodelc pobranego z serwera.

Czy VNCoreMLRequest obsługuje modele z wieloma wejściami?

VNCoreMLRequest obsługuje tylko modele z jednym wejściem Image Feature. Jeśli model ma wiele wejść (np. obraz + tekst), używaj Core ML bezpośrednio przez MLModel. Vision nie może przekazać dodatkowych parametrów poza obrazem.

Jaki jest maksymalny rozmiar obrazu dla VNCoreMLRequest?

Ograniczenie — 8192 x 8192 pikseli dla CGImage przekazywanego do VNImageRequestHandler. Jednak modele Core ML zwykle oczekują wejścia 224x224, 299x299 lub 512x512. Vision automatycznie skaluje duży obraz do rozmiaru wejściowego. Jeśli oryginalny obraz jest zbyt duży, wstępnie zmniejsz go przez CGImage, aby oszczędzić pamięć.

Czy można uruchomić VNCoreMLRequest w tle?

Tak, ustaw preferBackgroundProcessing = true na VNRequest. Pozwoli to Vision opóżnić wykonanie żądania, jeśli system jest w trybie zasobożernym (np. ładowanie treści). Koniecznie używaj DispatchQueue.global(qos: .background) do wywołania handler.perform().

Podsumowanie

  • VNCoreMLRequest — podklasa VNRequest do uruchamiania modeli Core ML w potoku Vision z automatycznym wstępnym przetwarzaniem obrazów.
  • VNCoreMLModel opakowuje MLModel dla Vision, automatycznie konwertując CGImage na CVPixelBuffer o odpowiednim rozmiarze i przestrzeni kolorów.
  • imageCropAndScaleOption (centerCrop, scaleFill, scaleFit) określa strategię skalowania i wpływa na dokładność modelu o 15–25%.
  • Łączenie z VNDetectFaceRectanglesRequest i innymi VNRequest pozwala budować potoki „detekcja → klasyfikacja” z regionOfInterest.
  • Wyniki są zwracane jako VNClassificationObservation (dla klasyfikacji) lub VNCoreMLFeatureValueObservation (dla regresji/innych typów).
  • Ponowne użycie jednego VNCoreMLRequest do przetwarzania wsadowego daje do 40% wzrostu wydajności w porównaniu do tworzenia nowego dla każdego obrazu.
  • Wydajność na Neural Engine (3–5 ms na MobileNetV2) jest 4–6 razy wyższa niż na CPU, co jest kluczowe dla aplikacji czasu rzeczywistego.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również