Za pomocą zestawu ML Kit możesz wykrywać twarze na zdjęciach i filmach.
Zanim zaczniesz
- Jeśli nie dodałeś jeszcze Firebase do swojej aplikacji, zrób to, wykonując czynności opisane w przewodniku wprowadzającym .
- Dołącz biblioteki ML Kit do swojego Podfile:
pod 'Firebase/MLVision', '6.25.0' # If you want to detect face contours (landmark detection and classification # don't require this additional model): pod 'Firebase/MLVisionFaceModel', '6.25.0'
Po zainstalowaniu lub zaktualizowaniu Podów swojego projektu pamiętaj o otwarciu projektu Xcode przy użyciu jego.xcworkspace
. - W swojej aplikacji zaimportuj Firebase:
Szybki
import Firebase
Cel C
@import Firebase;
Wytyczne dotyczące obrazu wejściowego
Aby zestaw ML Kit mógł dokładnie wykrywać twarze, obrazy wejściowe muszą zawierać twarze reprezentowane przez wystarczającą ilość danych w pikselach. Ogólnie rzecz biorąc, każda twarz, którą chcesz wykryć na obrazie, powinna mieć wymiary co najmniej 100 x 100 pikseli. Jeśli chcesz wykryć kontury twarzy, ML Kit wymaga wyższej rozdzielczości: każda twarz powinna mieć co najmniej 200x200 pikseli.
Jeśli wykrywasz twarze w aplikacji czasu rzeczywistego, możesz również rozważyć ogólne wymiary obrazów wejściowych. Mniejsze obrazy można przetwarzać szybciej, dlatego aby zmniejszyć opóźnienia, należy rejestrować obrazy w niższych rozdzielczościach (pamiętając o powyższych wymaganiach dotyczących dokładności) i upewnić się, że twarz obiektu zajmuje jak największą część obrazu. Zobacz także Wskazówki dotyczące poprawy wydajności w czasie rzeczywistym .
Słaba ostrość obrazu może zaszkodzić dokładności. Jeśli wyniki nie są akceptowalne, spróbuj poprosić użytkownika o ponowne wykonanie zdjęcia.
Orientacja twarzy względem aparatu może również mieć wpływ na to, jakie cechy twarzy wykrywa ML Kit. Zobacz Pojęcia dotyczące wykrywania twarzy .
1. Skonfiguruj detektor twarzy
Jeśli przed zastosowaniem wykrywania twarzy do obrazu chcesz zmienić dowolne ustawienia domyślne detektora twarzy, określ te ustawienia za pomocą obiektuVisionFaceDetectorOptions
. Możesz zmienić następujące ustawienia:Ustawienia | |
---|---|
performanceMode | fast (domyślny) | accurate Preferuj szybkość lub dokładność podczas wykrywania twarzy. |
landmarkMode | none (domyślnie) | all Czy podjąć próbę wykrycia „punktów orientacyjnych” twarzy — oczu, uszu, nosa, policzków i ust — wszystkich wykrytych twarzy. |
contourMode | none (domyślnie) | all Czy wykrywać kontury rysów twarzy. Kontury są wykrywane tylko dla najbardziej widocznej twarzy na obrazie. |
classificationMode | none (domyślnie) | all Określa, czy klasyfikować twarze w kategorie takie jak „uśmiechnięte” i „otwarte oczy”. |
minFaceSize | CGFloat (domyślnie: 0.1 )Minimalny rozmiar wykrywanych twarzy w stosunku do obrazu. |
isTrackingEnabled | false (domyślnie) | true Określa, czy przypisać twarzom identyfikator, którego można używać do śledzenia twarzy na obrazach. Należy pamiętać, że gdy włączone jest wykrywanie konturów, wykrywana jest tylko jedna twarz, więc śledzenie twarzy nie daje użytecznych wyników. Z tego powodu oraz w celu zwiększenia szybkości wykrywania nie włączaj jednocześnie wykrywania konturów i śledzenia twarzy. |
Na przykład utwórz obiekt VisionFaceDetectorOptions
, jak w jednym z poniższych przykładów:
Szybki
// High-accuracy landmark detection and face classification let options = VisionFaceDetectorOptions() options.performanceMode = .accurate options.landmarkMode = .all options.classificationMode = .all // Real-time contour detection of multiple faces let options = VisionFaceDetectorOptions() options.contourMode = .all
Cel C
// High-accuracy landmark detection and face classification FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate; options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll; options.classificationMode = FIRVisionFaceDetectorClassificationModeAll; // Real-time contour detection of multiple faces FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.contourMode = FIRVisionFaceDetectorContourModeAll;
2. Uruchom detektor twarzy
Aby wykryć twarze na obrazie, przekaż obraz jakoUIImage
lub CMSampleBufferRef
do metody detect(in:)
klasy VisionFaceDetector
:- Pobierz instancję
VisionFaceDetector
:Szybki
lazy var vision = Vision.vision() let faceDetector = vision.faceDetector(options: options)
Cel C
FIRVision *vision = [FIRVision vision]; FIRVisionFaceDetector *faceDetector = [vision faceDetector]; // Or, to change the default settings: // FIRVisionFaceDetector *faceDetector = // [vision faceDetectorWithOptions:options];
Utwórz obiekt
VisionImage
przy użyciuUIImage
lubCMSampleBufferRef
.Aby użyć
UIImage
:- W razie potrzeby obróć obraz tak, aby jego właściwość
imageOrientation
miała.up
. - Utwórz obiekt
VisionImage
, używając poprawnie obróconegoUIImage
. Nie określaj żadnych metadanych rotacji — należy użyć wartości domyślnej.topLeft
.Szybki
let image = VisionImage(image: uiImage)
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Aby użyć
CMSampleBufferRef
:Utwórz obiekt
VisionImageMetadata
, który określa orientację danych obrazu zawartych w buforzeCMSampleBufferRef
.Aby uzyskać orientację obrazu:
Szybki
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Cel C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Następnie utwórz obiekt metadanych:
Szybki
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Cel C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Utwórz obiekt
VisionImage
przy użyciu obiektuCMSampleBufferRef
i metadanych rotacji:Szybki
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Cel C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- W razie potrzeby obróć obraz tak, aby jego właściwość
- Następnie przekaż obraz do metody
detect(in:)
:Szybki
faceDetector.process(visionImage) { faces, error in guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
Cel C
[faceDetector detectInImage:image completion:^(NSArray<FIRVisionFace *> *faces, NSError *error) { if (error != nil) { return; } else if (faces != nil) { // Recognized faces } }];
3. Uzyskaj informacje o wykrytych twarzach
Jeśli operacja wykrywania twarzy powiedzie się, detektor twarzy przekazuje tablicę obiektówVisionFace
do procedury obsługi zakończenia. Każdy obiekt VisionFace
reprezentuje twarz wykrytą na obrazie. Dla każdej twarzy możesz uzyskać współrzędne ograniczające na obrazie wejściowym, a także wszelkie inne informacje, które skonfigurowałeś do wyszukiwania przez wykrywacz twarzy. Na przykład: Szybki
for face in faces { let frame = face.frame if face.hasHeadEulerAngleY { let rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees } if face.hasHeadEulerAngleZ { let rotZ = face.headEulerAngleZ // Head is rotated upward rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): if let leftEye = face.landmark(ofType: .leftEye) { let leftEyePosition = leftEye.position } // If contour detection was enabled: if let leftEyeContour = face.contour(ofType: .leftEye) { let leftEyePoints = leftEyeContour.points } if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) { let upperLipBottomPoints = upperLipBottomContour.points } // If classification was enabled: if face.hasSmilingProbability { let smileProb = face.smilingProbability } if face.hasRightEyeOpenProbability { let rightEyeOpenProb = face.rightEyeOpenProbability } // If face tracking was enabled: if face.hasTrackingID { let trackingId = face.trackingID } }
Cel C
for (FIRVisionFace *face in faces) { // Boundaries of face in image CGRect frame = face.frame; if (face.hasHeadEulerAngleY) { CGFloat rotY = face.headEulerAngleY; // Head is rotated to the right rotY degrees } if (face.hasHeadEulerAngleZ) { CGFloat rotZ = face.headEulerAngleZ; // Head is tilted sideways rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): FIRVisionFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar]; if (leftEar != nil) { FIRVisionPoint *leftEarPosition = leftEar.position; } // If contour detection was enabled: FIRVisionFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom]; if (upperLipBottomContour != nil) { NSArray<FIRVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points; if (upperLipBottomPoints.count > 0) { NSLog("Detected the bottom contour of the subject's upper lip.") } } // If classification was enabled: if (face.hasSmilingProbability) { CGFloat smileProb = face.smilingProbability; } if (face.hasRightEyeOpenProbability) { CGFloat rightEyeOpenProb = face.rightEyeOpenProbability; } // If face tracking was enabled: if (face.hasTrackingID) { NSInteger trackingID = face.trackingID; } }
Przykład konturów twarzy
Jeśli masz włączone wykrywanie konturu twarzy, otrzymasz listę punktów za każdą wykrytą cechę twarzy. Punkty te reprezentują kształt obiektu. Aby uzyskać szczegółowe informacje na temat sposobu przedstawiania konturów, zobacz Przegląd koncepcji wykrywania twarzy .
Poniższy obraz ilustruje sposób, w jaki te punkty są przypisane do twarzy (kliknij obraz, aby powiększyć):
Wykrywanie twarzy w czasie rzeczywistym
Jeśli chcesz używać wykrywania twarzy w aplikacji czasu rzeczywistego, postępuj zgodnie z poniższymi wskazówkami, aby uzyskać najlepszą liczbę klatek na sekundę:
Skonfiguruj wykrywacz twarzy tak, aby korzystał z wykrywania konturu twarzy lub wykrywania klasyfikacji i punktów orientacyjnych, ale nie obu jednocześnie:
Wykrywanie konturu
Wykrywanie punktów orientacyjnych
Klasyfikacja
Wykrywanie i klasyfikacja zabytków
Wykrywanie konturów i wykrywanie punktów orientacyjnych
Wykrywanie i klasyfikacja konturów
Wykrywanie konturów, wykrywanie punktów orientacyjnych i klasyfikacjaWłącz tryb
fast
(domyślnie włączony).Rozważ przechwytywanie obrazów w niższej rozdzielczości. Należy jednak pamiętać o wymaganiach dotyczących wymiarów obrazu tego interfejsu API.
- Przepustnica wzywa do detektora. Jeżeli w trakcie działania detektora pojawi się nowa klatka wideo, usuń ją.
- Jeśli używasz wyjścia detektora do nakładania grafiki na obraz wejściowy, najpierw uzyskaj wynik z ML Kit, a następnie wyrenderuj obraz i nakładkę w jednym kroku. W ten sposób renderujesz na powierzchnię wyświetlacza tylko raz dla każdej klatki wejściowej. Zobacz przykładowe klasy PreviewOverlayView i FIRDetectionOverlayView w przykładowej aplikacji prezentacyjnej.