Вы можете использовать ML Kit для обнаружения лиц на изображениях и видео.
Попробовать
- Попробуйте пример приложения, чтобы увидеть, как используется этот API.
- Попробуйте код самостоятельно, используя практическую работу.
Подготовка
- Добавьте в Podfile следующие поды ML Kit:
pod 'GoogleMLKit/FaceDetection', '8.0.0'
- После установки или обновления Pods проекта откройте проект Xcode, используя файл
.xcworkspace. ML Kit поддерживается в Xcode версии 12.4 и более поздних.
Требования к исходным изображениям
Для распознавания лиц следует использовать изображения с размером не менее 480 x 360 пикселей. Чтобы ML Kit мог точно распознавать лица, на входных изображениях они должны быть представлены достаточным количеством пикселей. В целом, каждое лицо, которое вы хотите обнаружить на изображении, должно быть не менее 100x100 пикселей. Если вы хотите обнаружить контуры лиц, ML Kit требует более высокого разрешения входных данных: каждое лицо должно быть не менее 200 x 200 пикселей.
Если вы обнаруживаете лица в приложении, работающем в реальном времени, вам также следует учитывать общие размеры входных изображений. Небольшие изображения обрабатываются быстрее, поэтому, чтобы уменьшить задержку, снимайте с более низким разрешением. Однако учитывайте требования к точности, указанные выше, и убедитесь, что лицо занимает как можно большую часть изображения. Также ознакомьтесь с советами по повышению эффективности в реальном времени.
Точность также может снизиться из-за плохого фокуса. Если результаты не соответствуют требованиям, попросите пользователя сделать снимок ещё раз.
Ориентация лица относительно камеры также может влиять на то, какие черты лица обнаруживает ML Kit. Подробнее о распознавании лиц…
1. Как настроить детектор лиц
Если вы хотите изменить настройки детектора лиц по умолчанию, укажите их в объектеFaceDetectorOptions до того, как применить к изображению функцию распознавания лиц. Вы можете изменить
следующие настройки:
| Настройки | |
|---|---|
performanceMode |
fast (по умолчанию) | accurate
При распознавании лиц отдавать предпочтение скорости или точности. |
landmarkMode |
none (по умолчанию) | all
Попытаться ли обнаружить "ориентиры" лица – глаза, уши, нос, щеки, рот – на всех обнаруженных лицах. |
contourMode |
none (по умолчанию) | all
Обнаруживать ли контуры черт лица. Контуры определяются только для самого заметного лица на изображении. |
classificationMode |
none (по умолчанию) | all
Определяет, нужно ли классифицировать лица по категориям, например "улыбается" и "глаза открыты". |
minFaceSize |
CGFloat (по умолчанию: 0.1)
Задает наименьший желаемый размер лица, выраженный как отношение ширины головы к ширине изображения. |
isTrackingEnabled |
false (по умолчанию) | true
Назначать ли лицам идентификатор, который можно использовать для отслеживания лиц на изображениях. Обратите внимание, что при включенном распознавании контуров обнаруживается только одно лицо, поэтому отслеживание лиц не дает полезных результатов. По этой причине, а также для повышения скорости обнаружения не включайте одновременно обнаружение контуров и отслеживание лиц. |
Например, создайте объект FaceDetectorOptions, как показано в одном из следующих примеров:
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. Как подготовить входное изображение
Чтобы обнаружить лица на изображении, передайте изображение в виде объектаUIImage или CMSampleBufferRef в FaceDetector, используя метод process(_:completion:) или results(in:):
Создайте объект VisionImage, используя UIImage или CMSampleBuffer.
Если вы используете UIImage, выполните следующие действия:
- Создайте объект
VisionImageсUIImage. Убедитесь, что вы указали правильный.orientation.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Если вы используете CMSampleBuffer, выполните следующие действия:
-
Укажите ориентацию данных изображения, содержащихся в элементе
CMSampleBuffer.Чтобы получить ориентацию изображения:
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; } }
- Создайте объект
VisionImage, используя объектCMSampleBufferи ориентацию: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. Получение экземпляра FaceDetector
Получите экземпляр FaceDetector:
Swift
let faceDetector = FaceDetector.faceDetector(options: options)
Objective-C
MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
4. Обработка изображения
Затем передайте изображение методуprocess():
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. Как получить информацию о распознанных лицах
Если операция распознавания лица выполнена успешно, детектор лиц передает массив объектовFace в обработчик завершения. Каждый объект Face представляет лицо, обнаруженное на изображении. Для каждого лица можно получить его ограничивающие координаты на входном изображении, а также любую другую информацию, которую вы настроили для поиска детектором лиц. Пример:
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; } }
Пример контуров лица
Если включено распознавание контуров лица, вы получите список точек для каждой распознанной черты лица. Эти точки представляют форму объекта. Подробнее о том, как представляются контуры, рассказывается в разделе Концепции обнаружения лиц.
На изображении ниже показано, как эти точки сопоставляются с лицом. Нажмите на изображение, чтобы увеличить его.
Распознавание лиц в реальном времени
Если вы хотите использовать распознавание лиц в приложении, работающем в реальном времени, следуйте этим рекомендациям, чтобы достичь оптимальной частоты кадров:
Настройте детектор лиц так, чтобы он использовал либо обнаружение контуров лица, либо классификацию и обнаружение ориентиров, но не оба варианта одновременно:
Обнаружение контуров
Обнаружение ориентиров
Классификация
Обнаружение и классификация ориентиров
Обнаружение контуров и ориентиров
Обнаружение контуров и классификация
Обнаружение контуров и ориентиров, а также классификацияВключите режим
fast(включен по умолчанию).Попробуйте снимать с более низким разрешением. Однако помните о требованиях к размеру изображений, которые предъявляются в этом API.
- Для обработки кадров видео используйте синхронный API детектора
results(in:). Вызовите этот метод из функцииcaptureOutput(_, didOutput:from:)объектаAVCaptureVideoDataOutputSampleBufferDelegate, чтобы синхронно получить результаты из заданного кадра видео. Оставьте для параметраalwaysDiscardsLateVideoFramesвAVCaptureVideoDataOutputзначениеtrue, чтобы ограничить количество вызовов детектора. Если во время работы детектора станет доступен новый кадр видео, он будет пропущен. - Если вы используете результаты работы детектора для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем отрисуйте изображение и наложите графику за один шаг. В этом случае отрисовка на поверхности экрана выполняется только один раз для каждого обработанного входного кадра. Пример можно найти в функции updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.