Za pomocą ML Kit możesz wykrywać twarze na zdjęciach i filmach.
Wypróbuj
- Przyjrzyj się przykładowej aplikacji, aby zobaczyć przykładowe użycie tego interfejsu API.
- Spróbuj samodzielnie wykonać kod podczas ćwiczenia z programowania.
Zanim zaczniesz
- W pliku Podfile uwzględnij te pody ML Kit:
pod 'GoogleMLKit/FaceDetection', '3.2.0'
- Po zainstalowaniu lub zaktualizowaniu podów w projekcie otwórz projekt Xcode, korzystając z jego polecenia
.xcworkspace
. ML Kit obsługuje Xcode w wersji 12.4 lub nowszej.
Zalecenia dotyczące obrazu wejściowego
Do rozpoznawania twarzy użyj obrazu o wymiarach co najmniej 480 x 360 pikseli. Aby narzędzie ML Kit mogło dokładnie wykrywać twarze, obrazy wejściowe muszą zawierać twarze reprezentowane przez wystarczającą ilość danych pikseli. Ogólnie każda twarz, którą chcesz wykryć na obrazie, powinna mieć rozmiar co najmniej 100 x 100 pikseli. Jeśli chcesz wykrywać kontury twarzy, ML Kit wymaga danych wejściowych o wyższej rozdzielczości: każda twarz powinna mieć co najmniej 200 x 200 pikseli.
W przypadku wykrywania twarzy w aplikacji rejestrującej dane w czasie rzeczywistym warto też wziąć pod uwagę ogólne wymiary obrazów wejściowych. Mniejsze obrazy mogą być przetwarzane szybciej, więc jeśli chcesz zmniejszyć opóźnienia, zrób zdjęcia w niższej rozdzielczości, pamiętając o powyższych wymaganiach dotyczących dokładności i upewnij się, że twarz osoby, która znajduje się na zdjęciu, będzie zajmować jak najwięcej miejsca. Zapoznaj się też ze wskazówkami dotyczącymi zwiększania skuteczności w czasie rzeczywistym.
Słaba ostrość obrazu również może wpływać na dokładność. Jeśli nie uzyskasz zadowalających wyników, poproś użytkownika o ponowne zdjęcie obrazu.
Orientacja twarzy względem kamery może też wpływać na to, jakie cechy twarzy wykryje ML Kit. Zobacz Pojęcia związane z wykrywaniem twarzy.
1. Skonfiguruj wykrywanie twarzy
Jeśli chcesz zmienić domyślne ustawienia funkcji wykrywania twarzy, określ je za pomocą obiektuFaceDetectorOptions
, zanim zastosujesz wykrywanie twarzy do zdjęcia. Możesz zmienić te ustawienia:
Ustawienia | |
---|---|
performanceMode |
fast (domyślnie) | accurate
Wykrywaj twarze z większą szybkością i dokładnością. |
landmarkMode |
none (domyślnie) | all
Określa, czy ma być podejmowana próba wykrycia „charakterystycznych” elementów twarzy – oczu, uszu, nosa, policzków i ust – wszystkich wykrytych twarzy. |
contourMode |
none (domyślnie) | all
Określa, czy ma wykrywać kontury twarzy. Wykrywanie konturów jest wykrywanych tylko w przypadku najbardziej rzucających się w oczy twarzy na zdjęciu. |
classificationMode |
none (domyślnie) | all
Określa, czy klasyfikować twarze w kategoriach takich jak „uśmiechnięta” i „otwarte oczy”. |
minFaceSize |
CGFloat (domyślnie: 0.1 )
Ustawia najmniejszy wymagany rozmiar twarzy wyrażony jako stosunek szerokości głowy do szerokości obrazu. |
isTrackingEnabled |
false (domyślnie) | true
Określa, czy przypisać twarzom identyfikator, który może służyć do śledzenia twarzy na obrazach. Pamiętaj, że gdy wykrywanie konturu jest włączone, wykrywana jest tylko 1 twarz, więc śledzenie twarzy nie dostarcza przydatnych wyników. Dlatego, aby zwiększyć szybkość wykrywania, nie włączaj jednocześnie wykrywania konturu i śledzenia twarzy. |
Utwórz na przykład obiekt FaceDetectorOptions
podobny do tych:
Swift
// High-accuracy landmark detection and face classification let options = FaceDetectorOptions() options.performanceMode = .accurate options.landmarkMode = .all options.classificationMode = .all // Real-time contour detection of multiple faces // options.contourMode = .all
Objective-C
// High-accuracy landmark detection and face classification MLKFaceDetectorOptions *options = [[MLKFaceDetectorOptions alloc] init]; options.performanceMode = MLKFaceDetectorPerformanceModeAccurate; options.landmarkMode = MLKFaceDetectorLandmarkModeAll; options.classificationMode = MLKFaceDetectorClassificationModeAll; // Real-time contour detection of multiple faces // options.contourMode = MLKFaceDetectorContourModeAll;
2. Przygotuj obraz wejściowy
Aby wykrywać twarze na obrazie, przekaż zdjęcie jakoUIImage
lub CMSampleBufferRef
do funkcji FaceDetector
, korzystając z metody process(_:completion:)
lub results(in:)
:
Utwórz obiekt VisionImage
za pomocą UIImage
lub CMSampleBuffer
.
Jeśli używasz urządzenia UIImage
, wykonaj te czynności:
- Utwórz obiekt
VisionImage
za pomocąUIImage
. Pamiętaj, aby podać prawidłową wartość.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jeśli używasz urządzenia CMSampleBuffer
, wykonaj te czynności:
-
Określ orientację danych obrazu w elemencie
CMSampleBuffer
.Aby pobrać orientację:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- Utwórz obiekt
VisionImage
, używając obiektu i orientacjiCMSampleBuffer
:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Pobieranie wystąpienia funkcji FaceDetector
Pobierz wystąpienie FaceDetector
:
Swift
let faceDetector = FaceDetector.faceDetector(options: options)
Objective-C
MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
4. Przetwarzanie obrazu
Następnie przekaż obraz do metodyprocess()
:
Swift
weak var weakSelf = self faceDetector.process(visionImage) { faces, error in guard let strongSelf = weakSelf else { print("Self is nil!") return } guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
Objective-C
[faceDetector processImage:image completion:^(NSArray<MLKFace *> *faces, NSError *error) { if (error != nil) { return; } if (faces.count > 0) { // Recognized faces } }];
5. Uzyskiwanie informacji o wykrytych twarzach
Jeśli operacja wykrywania twarzy zakończy się powodzeniem, wzorzec do wykrywania twarzy przekaże do modułu obsługi tablicy liczbę obiektówFace
. Każdy obiekt Face
reprezentuje twarz wykrytą na obrazie. W przypadku każdej twarzy współrzędne ograniczające są podane na zdjęciu wejściowym oraz wszelkie inne informacje, które zostały wyszukane przez czujnik. Na przykład:
Swift
for face in faces { let frame = face.frame if face.hasHeadEulerAngleX { let rotX = face.headEulerAngleX // Head is rotated to the uptoward rotX degrees } if face.hasHeadEulerAngleY { let rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees } if face.hasHeadEulerAngleZ { let rotZ = face.headEulerAngleZ // Head is tilted sideways 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 } }
Objective-C
for (MLKFace *face in faces) { // Boundaries of face in image CGRect frame = face.frame; if (face.hasHeadEulerAngleX) { CGFloat rotX = face.headEulerAngleX; // Head is rotated to the upward rotX degrees } 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): MLKFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar]; if (leftEar != nil) { MLKVisionPoint *leftEarPosition = leftEar.position; } // If contour detection was enabled: MLKFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom]; if (upperLipBottomContour != nil) { NSArray<MLKVisionPoint *> *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
Gdy wykrywanie konturów twarzy jest włączone, otrzymujesz listę punktów za każdą wykrytą cechę twarzy. Te punkty reprezentują kształt obiektu. Szczegółowe informacje o tym, jak są przedstawiane kontury, znajdziesz w artykule Pojęcia związane z wykrywaniem twarzy.
Poniższa ilustracja przedstawia sposób mapowania tych punktów na twarz. Kliknij obraz, aby go powiększyć:
Wykrywanie twarzy w czasie rzeczywistym
Jeśli chcesz używać wykrywania twarzy w aplikacji w czasie rzeczywistym, postępuj zgodnie z tymi wskazówkami, aby uzyskać najlepszą liczbę klatek:
Skonfiguruj wykrywacz twarzy tak, aby używał wykrywania konturów twarzy lub klasyfikacji i wykrywania punktów orientacyjnych, ale nie obu naraz:
Wykrywanie konturów
Wykrywanie punktów orientacyjnych
Klasyfikacja
Wykrywanie i klasyfikacja punktów orientacyjnych
Wykrywanie i klasyfikowanie konturów
Wykrywanie i klasyfikacja konturów
Wykrywanie i klasyfikacja konturu, wykrywanie i klasyfikacja punktów orientacyjnychWłącz tryb
fast
(domyślnie włączony).Rozważ robienie zdjęć w niższej rozdzielczości. Pamiętaj też o wymaganiach dotyczących wymiarów obrazu w tym interfejsie API.
- Do przetwarzania klatek wideo użyj synchronicznego interfejsu API
results(in:)
wzorca. Wywołaj tę metodę z funkcjicaptureOutput(_, didOutput:from:)
obiektuAVCaptureVideoDataOutputSampleBufferDelegate
, aby synchronicznie pobierać wyniki z danej klatki wideo. PozostawalwaysDiscardsLateVideoFrames
obiektuAVCaptureVideoDataOutput
jakotrue
, aby ograniczać wywołania do wzorca. Jeśli podczas działania wzorca pojawi się nowa ramka wideo, zostanie ona usunięta. - Jeśli używasz danych wyjściowych wzorca do nakładania grafiki na obraz wejściowy, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładkę w jednym kroku. Dzięki temu na każdą przetworzoną klatkę wejściową renderujesz się tylko raz. Przykład znajdziesz w sekcji updatePreviewOverlayViewWithLastFrame w przykładowym krótkim wprowadzeniu do ML Kit.