VNRequest — to abstrakcyjna klasa bazowa frameworku Vision, która reprezentuje jednostkę analizy obrazu lub strumienia wideo. Każdy typ analizy — wykrywanie twarzy, rozpoznawanie tekstu, wyszukiwanie kodów kreskowych, klasyfikacja — jest zaimplementowany jako konkretna podklasa VNRequest. Według Apple Developer Documentation (2024), programista tworzy instancję żądania, konfiguruje jego parametry, przekazuje obraz przez VNImageRequestHandler i otrzymuje wyniki w postaci tablicy VNObservation.
Najważniejsze
VNRequest — to fundamentalny element architektury Vision, implementujący wzorzec Request-Response do analizy obrazów i wideo. Każda podklasa VNRequest odpowiada za konkretne zadanie wizji komputerowej: wyszukiwanie twarzy, rozpoznawanie tekstu, klasyfikację treści.
Architektura VNRequest oddziela „co analizować” (żądanie) od „jak przetwarzać” (handler). Programista konfiguruje żądanie (typ analizy, dodatkowe parametry) i przekazuje je do handlera wraz z obrazem. Handler wykonuje żądanie i zwraca wyniki, nie wymagając od programisty znajomości wewnętrznych algorytmów ML.
Wszystkie podklasy VNRequest mają jednolitą strukturę: inicjalizacja z opcjonalnym completion handler, konfiguracja właściwości (region analizy, poziom dokładności) i przekazanie do handlera. To sprawia, że API jest przewidywalne i łatwo rozszerzalne — dodanie nowego typu analizy oznacza utworzenie nowej podklasy VNRequest.
import Vision
// 1. Utwórz żądanie
let request = VNDetectFaceRectanglesRequest { req, _ in
// 3. Przetwarzaj wyniki
guard let faces = req.results as? [VNFaceObservation]
else { return }
print("Found \\(faces.count) faces")
}
// 2. Wykonaj przez handler
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([request])
Kluczowe właściwości VNRequest: regionOfInterest (obszar zainteresowania na obrazie w celu przyspieszenia analizy), preferBackgroundProcessing (tryb tła), revision (wersja algorytmu) i cancellationSupport. Prawidłowa konfiguracja tych właściwości pozwala zoptymalizować wydajność pod konkretne zadanie.
Według Apple WWDC 2024, przez 7 lat istnienia Vision liczba dostępnych podklas VNRequest wzrosła z 8 (iOS 11) do ponad 25 (iOS 18), pokrywając wszystkie główne zadania wizji komputerowej na urządzeniach mobilnych.
Vision zawiera ponad 25 podklas VNRequest, podzielonych na kategorie: detekcja, rozpoznawanie, śledzenie i klasyfikacja. Każda podklasa dziedziczy VNRequest i dodaje właściwości specyficzne dla zadania.
VNDetectFaceRectanglesRequest — wyszukiwanie twarzy na obrazie. Zwraca VNFaceObservation z współrzędnymi bounding box i confidence. VNDetectHumanRectanglesRequest — analogicznie dla ludzi. VNDetectHumanBodyPoseRequest — określanie pozy człowieka (punkty szkieletowe).
VNRecognizeTextRequest — rozpoznawanie tekstu z obsługą 13 języków i dwoma poziomami dokładności. VNReadCodeRequest — dla wyspecjalizowanych kodów. VNDetectTextRectanglesRequest — wyszukiwanie obszarów tekstu bez rozpoznawania (szybsze, ale tylko prostokąty).
VNClassifyImageRequest — klasyfikacja obrazu według 1000 kategorii ImageNet. VNGenerateImageFeaturePrintRequest — ekstrakcja wektora cech do porównywania obrazów. VNDetectContoursRequest — wykrywanie konturów obiektów.
| Kategoria | Przykład żądania | Wynik |
|---|---|---|
| Detekcja twarzy | VNDetectFaceRectanglesRequest | VNFaceObservation |
| Rozpoznawanie tekstu | VNRecognizeTextRequest | VNRecognizedTextObservation |
| Kody kreskowe | VNDetectBarcodesRequest | VNBarcodeObservation |
| Klasyfikacja | VNClassifyImageRequest | VNClassificationObservation |
| Śledzenie | VNTrackObjectRequest | VNDetectedObjectObservation |
| Kontury | VNDetectContoursRequest | VNContoursObservation |
VNImageRequestHandler — handler dla statycznych obrazów. Przyjmuje CGImage, CIImage lub Data (JPEG/PNG) i wykonuje jeden lub wiele VNRequest. Jest to podstawowy sposób korzystania z Vision dla zdjęć, zrzutów ekranu i przesłanych obrazów.
VNSequenceRequestHandler — handler dla sekwencji obrazów (klatek wideo). Przyjmuje ten sam zestaw typów obrazów, ale jest przeznaczony do przetwarzania klatka po klatce z zachowaniem stanu między klatkami (niezbędne do śledzenia obiektów).
// VNImageRequestHandler dla pojedynczego obrazu
let imageHandler = VNImageRequestHandler(
cgImage: cgImage,
orientation: orientation,
options: [:])
// VNSequenceRequestHandler dla wideo
let sequenceHandler = VNSequenceRequestHandler()
try sequenceHandler.perform([trackingRequest],
on: cgImage)
Ważna różnica: VNSequenceRequestHandler nie obsługuje równoległego wykonywania wielu żądań — każde wywołanie perform() przetwarza jeden zestaw żądań dla jednej klatki. Do wielowątkowego przetwarzania wideo twórz osobne instancje handlera dla różnych wątków.
VNImageRequestHandler może być wykonywany w kolejce tła. Apple zaleca DispatchQueue.global(qos: .userInitiated) dla scenariuszy interaktywnych (użytkownik czeka na wynik) i .background dla przetwarzania wsadowego (np. analiza całej biblioteki zdjęć).
VNObservation — klasa bazowa dla wszystkich wyników zapytań Vision. Każda podklasa VNObservation zawiera dane specyficzne dla typu analizy: współrzędne bounding box, rozpoznany tekst, pewność (confidence), unikalny identyfikator (uuid) i znacznik czasu (timeRange).
Kluczowe podklasy VNObservation: VNFaceObservation (wynik detekcji twarzy z bounding box i landmarks), VNRecognizedTextObservation (rozpoznany tekst z candidates), VNBarcodeObservation (zdekodowany kod kreskowy z payload i symbology), VNClassificationObservation (kategoria klasyfikacji z confidence).
func handleTextResults(request: VNRequest) {
guard let observations = request.results
as? [VNRecognizedTextObservation]
else { return }
for observation in observations {
let bbox = observation.boundingBox
let text = observation.topCandidates(1).first ?? ""
print("\\(text) at \\(bbox)")
}
}
Właściwość confidence (od 0.0 do 1.0) występuje we wszystkich VNObservation i pokazuje pewność modelu co do wyniku. Apple zaleca odrzucanie obserwacji z confidence < 0.5 dla większości zadań. Dla krytycznych aplikacji (medycyna, bezpieczeństwo) próg należy podnieść do 0.8–0.9.
VNObservation zawiera również timeRange (dla żądań wideo) i uuid (unikalny ID do dopasowywania między klatkami). Pozwala to śledzić ten sam obiekt (np. twarz) przez sekwencję klatek wideo.
Jedna z kluczowych zalet VNRequest — możliwość wykonywania kilku różnych żądań do jednego obrazu w jednym wywołaniu handler.perform(). Vision wewnętrznie optymalizuje kolejność wykonywania i współdzieli wspólne obliczenia (np. wstępne przetwarzanie obrazu).
Pozwala to uzyskać pełny zestaw danych o obrazie w jednym przebiegu: jednocześnie wykryć twarze, rozpoznać tekst, znaleźć kody kreskowe i sklasyfikować treść. Takie podejście jest znacznie wydajniejsze niż sekwencyjne wywoływanie każdego żądania osobno.
import Vision
// Wiele żądań w jednej tablicy
let faceRequest = VNDetectFaceRectanglesRequest()
let textRequest = VNRecognizeTextRequest()
let barcodeRequest = VNDetectBarcodesRequest()
let classifyRequest = VNClassifyImageRequest()
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([
faceRequest,
textRequest,
barcodeRequest,
classifyRequest
])
// Dostęp do wyników z każdego żądania
print("Faces: \\(faceRequest.results?.count ?? 0)")
print("Text blocks: \\(textRequest.results?.count ?? 0)")
Ograniczenia: nie wszystkie żądania można łączyć z innymi. Na przykład VNGenerateImageFeaturePrintRequest musi być wykonywany osobno. Apple zaleca grupowanie żądań według typu (detekcja, rozpoznawanie, klasyfikacja) i testowanie kombinacji na docelowych urządzeniach.
Wydajność: łączenie 3–4 żądań w jednym perform() jest o 30–40% szybsze niż sekwencyjne wykonanie, ponieważ Vision współdzieli wspólne obliczenia ML i wstępne przetwarzanie obrazu (skalowanie, korekcję kolorów).
VNCoreMLRequest — to most między Core ML a Vision, umożliwiający uruchamianie dowolnego modelu Core ML jako żądania Vision. Model jest opakowywany w VNCoreMLModel, przekazywany do VNCoreMLRequest, a Vision automatycznie przetwarza wstępnie obraz (skalowanie, crop do rozmiaru wejścia modelu).
VNCoreMLRequest dziedziczy VNRequest, więc obsługuje wszystkie standardowe funkcje: regionOfInterest, completion handler, wiele żądań. Pozwala to łączyć niestandardowy model ML z wbudowanymi detektorami Vision w jednym pipeline.
import Vision
import CoreML
// Opakuj model Core ML
guard let mlModel = try VNCoreMLModel(
for: MyCustomClassifier().model)
else { return }
// Utwórz VNCoreMLRequest
let coreMLRequest = VNCoreMLRequest(model: mlModel) { request, _ in
guard let results = request.results
as? [VNClassificationObservation]
else { return }
for result in results.prefix(5) {
print("\\(result.identifier): \\(result.confidence)"
}
}
coreMLRequest.imageCropAndScaleOption = .centerCrop
coreMLRequest.regionOfInterest = faceBoundingBox
imageCropAndScaleOption określa, jak Vision skaluje obraz do wejścia modelu: .centerCrop (przycięcie od środka), .scaleFill (rozciągnięcie) lub .scaleFit (skalowanie z zachowaniem proporcji). Wybór zależy od typu modelu i położenia obiektu na obrazie.
Praktyczny przykład: wykrywanie twarzy przez VNDetectFaceRectanglesRequest, następnie klasyfikacja każdej twarzy przez VNCoreMLRequest z niestandardowym modelem (np. określanie płci lub wieku). Łącząc dwa żądania w jednym perform(), otrzymujesz pełny pipeline analizy twarzy w jednym przebiegu.
Często zadawane pytania
Tak, każde VNRequest ma właściwość cancel(), która anuluje wykonanie żądania. Jednak anulowanie działa tylko do momentu rozpoczęcia przetwarzania — jeśli model ML został już uruchomiony, anulowanie nie przerwie obliczeń. Do niezawodnego anulowania używaj DispatchWorkItem.cancel() razem z VNRequest.cancel() w completion handler.
VNDetectFaceRectanglesRequest znajduje tylko prostokąty twarzy. VNDetectFaceLandmarksRequest dodatkowo określa 68 kluczowych punktów twarzy (oczy, brwi, nos, usta, kontur). VNDetectFaceLandmarksRequest jest wolniejszy, ale dostarcza więcej danych do animacji, masek i efektów AR. Do prostego liczenia twarzy wystarczy VNDetectFaceRectanglesRequest.
Tak, VNDetectBarcodesRequest — to właściwe żądanie dla wszystkich typów kodów kreskowych i QR. Obsługuje EAN, UPC, Code 39, Code 128, PDF417, Aztec, QR i inne formaty. Wynik jest zwracany w VNBarcodeObservation z payload i symbology. Dla strumienia wideo używaj AVCaptureMetadataOutput — jest szybszy do skanowania na żywo.
Tak, VNImageRequestHandler przyjmuje CIImage przez inicjalizator init(ciImage:options:). Obsługiwane są również Data (JPEG/PNG) i NSURL (ścieżka do pliku). CIImage jest wygodny, gdy obraz został już załadowany przez Core Image pipeline — pozwala to uniknąć niepotrzebnego kopiowania danych w pamięci.
Nie ma ograniczenia co do liczby, ale w praktyce 3–5 żądań to optymalna ilość. Więcej niż 5 żądań może spowodować wzrost zużycia pamięci, ponieważ każde żądanie ładuje swój model ML. Jeśli potrzebujesz wykonać 10+ różnych analiz, podziel je na 2–3 grupy i wykonuj sekwencyjnie.
Podsumowanie
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.
Przeczytaj również