É possível usar o Kit de ML para detectar rostos em imagens e vídeos.
Testar
- Teste o app de exemplo para conferir um exemplo de uso dessa API.
- Teste o código com o codelab.
Antes de começar
- Inclua os seguintes pods do Kit de ML no seu Podfile:
pod 'GoogleMLKit/FaceDetection', '3.2.0'
- Depois de instalar ou atualizar os pods do projeto, abra o projeto Xcode usando o
.xcworkspace
. O Kit de ML é compatível com a versão 12.4 ou mais recente do Xcode.
Diretrizes de imagens de entrada
Para reconhecimento facial, você deve usar uma imagem com dimensões de pelo menos 480 x 360 pixels. Para que o Kit de ML detecte rostos com precisão, as imagens de entrada precisam conter rostos representados por dados de pixel suficientes. Em geral, cada rosto que você quer detectar em uma imagem precisa ter pelo menos 100 x 100 pixels. Se você quiser detectar os contornos dos rostos, o Kit de ML precisará de uma entrada de resolução mais alta: cada rosto precisa ter pelo menos 200 x 200 pixels.
Se você detectar rostos em um aplicativo em tempo real, considere as dimensões gerais das imagens de entrada. Como imagens menores podem ser processadas mais rapidamente, para reduzir a latência, capture imagens em resoluções mais baixas, mas lembre-se dos requisitos de precisão acima e garanta que o rosto da pessoa ocupe o máximo possível da imagem. Consulte também as dicas para melhorar o desempenho em tempo real.
O foco inadequado da imagem também pode afetar a precisão. Se você não receber resultados aceitáveis, peça para o usuário recapturar a imagem.
A orientação de um rosto em relação à câmera também pode afetar os atributos faciais que o Kit de ML detecta. Consulte Conceitos de detecção facial.
1. Configurar o detector facial
Antes de aplicar a detecção facial a uma imagem, se você quiser mudar as configurações padrão do detector facial, especifique-as com um objetoFaceDetectorOptions
. É possível alterar
as seguintes configurações:
Configurações | |
---|---|
performanceMode |
fast (padrão) | accurate
Favoreça a velocidade ou a precisão ao detectar rostos. |
landmarkMode |
none (padrão) | all
Para tentar detectar "pontos de referência" faciais, como olhos, orelhas, nariz, bochechas ou boca, de todos os rostos detectados. |
contourMode |
none (padrão) | all
Para detectar os contornos dos traços faciais. São detectados contornos apenas para o rosto mais proeminente de uma imagem. |
classificationMode |
none (padrão) | all
Se é necessário classificar rostos em categorias como "sorrindo" e "olhos abertos". |
minFaceSize |
CGFloat (padrão: 0.1 )
Define o menor tamanho facial desejado, expresso como a proporção entre a largura da cabeça e a largura da imagem. |
isTrackingEnabled |
false (padrão) | true
Se é necessário atribuir um ID a rostos, que pode ser usado para rastrear rostos em imagens. Quando a detecção de contorno está ativada, apenas um rosto é detectado, portanto, o rastreamento facial não produz resultados úteis. Por esse motivo, e para melhorar a velocidade de detecção, não ative a detecção de contorno e o rastreamento facial. |
Por exemplo, crie um objeto FaceDetectorOptions
como um dos exemplos a seguir:
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. Preparar a imagem de entrada
Para detectar rostos em uma imagem, transmita a imagem comoUIImage
ou
CMSampleBufferRef
para a FaceDetector
usando o
método process(_:completion:)
ou results(in:)
:
Crie um objeto VisionImage
usando um UIImage
ou um CMSampleBuffer
.
Se você usa um UIImage
, siga estas etapas:
- Crie um objeto
VisionImage
com oUIImage
. Especifique o.orientation
correto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Se você usa um CMSampleBuffer
, siga estas etapas:
-
Especifique a orientação dos dados da imagem contidos em
CMSampleBuffer
.Para ver a orientação da imagem:
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; } }
- Crie um objeto
VisionImage
usando o objetoCMSampleBuffer
e a orientação: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. Acessar uma instância do FaceDetector
Receba uma instância de FaceDetector
:
Swift
let faceDetector = FaceDetector.faceDetector(options: options)
Objective-C
MLKFaceDetector *faceDetector = [MLKFaceDetector faceDetectorWithOptions:options];
4. Processar a imagem
Em seguida, transmita a imagem para o métodoprocess()
:
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. Receber informações sobre rostos detectados
Se a operação de detecção facial for bem-sucedida, o detector facial transmitirá uma matriz de objetosFace
para o gerenciador de conclusão. Cada objeto
Face
representa um rosto detectado na imagem. Para
cada rosto, é possível receber as coordenadas delimitadoras na imagem de entrada, bem como
qualquer outra informação configurada no detector facial a ser encontrada. Exemplo:
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; } }
Exemplo de contornos faciais
Quando a detecção de contorno facial está ativada, você recebe uma lista de pontos para cada característica facial detectada. Esses pontos representam a forma do elemento. Consulte Conceitos de detecção facial para detalhes sobre como os contornos são representados.
A imagem a seguir ilustra como esses pontos mapeiam um rosto. Clique na imagem para ampliá-la:
Detecção facial em tempo real
Se você quiser usar o reconhecimento facial em um aplicativo em tempo real, siga estas diretrizes para ter as melhores taxas de frames:
Configure o detector facial para usar a detecção de contorno facial ou a classificação e a detecção de pontos de referência, mas não ambos:
Detecção de contorno
Detecção de pontos de referência
Classificação
Detecção e classificação de pontos de referência
Detecção de contorno e detecção de pontos de referência
Detecção e classificação de contorno
Detecção de contorno, detecção e classificação de pontos de referênciaAtive o modo
fast
(ativado por padrão).Capture imagens com uma resolução mais baixa. No entanto, lembre-se também dos requisitos de dimensão de imagem dessa API.
- Para processar frames de vídeo, use a API síncrona
results(in:)
do detector. Chame esse método na funçãocaptureOutput(_, didOutput:from:)
deAVCaptureVideoDataOutputSampleBufferDelegate
para receber resultados de forma síncrona do frame de vídeo especificado. Mantenha oalwaysDiscardsLateVideoFrames
deAVCaptureVideoDataOutput
comotrue
para limitar as chamadas ao detector. Se um novo frame de vídeo ficar disponível enquanto o detector estiver em execução, ele será descartado. - Se você usar a saída do detector para sobrepor elementos gráficos na imagem de entrada, primeiro acesse o resultado do Kit de ML e, em seguida, renderize a imagem e a sobreposição em uma única etapa. Ao fazer isso, você renderiza a superfície de exibição apenas uma vez para cada frame de entrada processado. Consulte updatePreviewOverlayViewWithLastFrame no exemplo do guia de início rápido do Kit de ML.