Você pode usar o ML Kit para detectar rostos em imagens e vídeos.
Antes de você começar
- Se você ainda não adicionou o Firebase ao seu aplicativo, faça isso seguindo as etapas do guia de primeiros passos .
- Inclua as bibliotecas do ML Kit em seu 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'
Depois de instalar ou atualizar os pods do seu projeto, certifique-se de abrir seu projeto Xcode usando seu.xcworkspace
. - No seu aplicativo, importe o Firebase:
Rápido
import Firebase
Objetivo-C
@import Firebase;
Diretrizes de imagem de entrada
Para que o ML Kit detecte rostos com precisão, as imagens de entrada devem conter rostos representados por dados de pixel suficientes. Em geral, cada rosto que você deseja detectar em uma imagem deve ter pelo menos 100x100 pixels. Se você deseja detectar os contornos dos rostos, o ML Kit requer entrada de resolução mais alta: cada rosto deve ter pelo menos 200x200 pixels.
Se você estiver detectando rostos em um aplicativo em tempo real, também poderá considerar as dimensões gerais das imagens de entrada. Imagens menores podem ser processadas mais rapidamente, portanto, para reduzir a latência, capture imagens em resoluções mais baixas (tendo em mente os requisitos de precisão acima) e garanta que o rosto do sujeito ocupe o máximo possível da imagem. Consulte também Dicas para melhorar o desempenho em tempo real .
O foco inadequado da imagem pode prejudicar a precisão. Se você não estiver obtendo resultados aceitáveis, tente pedir ao usuário para recapturar a imagem.
A orientação de um rosto em relação à câmera também pode afetar quais características faciais o ML Kit detecta. Consulte Conceitos de detecção de rosto .
1. Configure o detector facial
Antes de aplicar a detecção facial a uma imagem, se desejar alterar qualquer uma das configurações padrão do detector facial, especifique essas configurações com um objetoVisionFaceDetectorOptions
. Você pode 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 Seja para tentar detectar os "pontos de referência" faciais — olhos, orelhas, nariz, bochechas, boca — de todos os rostos detectados. |
contourMode | none (padrão) | all Seja para detectar os contornos das características faciais. Os contornos são detectados apenas para o rosto mais proeminente de uma imagem. |
classificationMode | none (padrão) | all Classificar ou não os rostos em categorias como "sorrindo" e "olhos abertos". |
minFaceSize | CGFloat (padrão: 0.1 )O tamanho mínimo, relativo à imagem, dos rostos a serem detectados. |
isTrackingEnabled | false (padrão) | true Se deve ou não atribuir um ID aos rostos, que pode ser usado para rastrear rostos nas imagens. Observe que quando a detecção de contorno está habilitada, apenas um rosto é detectado, portanto o rastreamento de rosto 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 VisionFaceDetectorOptions
como um dos exemplos a seguir:
Rápido
// 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
Objetivo-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. Execute o detector facial
Para detectar rostos em uma imagem, passe a imagem comoUIImage
ou CMSampleBufferRef
para o método detect(in:)
do VisionFaceDetector
:- Obtenha uma instância do
VisionFaceDetector
:Rápido
lazy var vision = Vision.vision() let faceDetector = vision.faceDetector(options: options)
Objetivo-C
FIRVision *vision = [FIRVision vision]; FIRVisionFaceDetector *faceDetector = [vision faceDetector]; // Or, to change the default settings: // FIRVisionFaceDetector *faceDetector = // [vision faceDetectorWithOptions:options];
Crie um objeto
VisionImage
usandoUIImage
ouCMSampleBufferRef
.Para usar uma
UIImage
:- Se necessário, gire a imagem para que sua propriedade
imageOrientation
seja.up
. - Crie um objeto
VisionImage
usando oUIImage
girado corretamente. Não especifique nenhum metadado de rotação — o valor padrão,.topLeft
, deve ser usado.Rápido
let image = VisionImage(image: uiImage)
Objetivo-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar um
CMSampleBufferRef
:Crie um objeto
VisionImageMetadata
que especifique a orientação dos dados de imagem contidos no bufferCMSampleBufferRef
.Para obter a orientação da imagem:
Rápido
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 } }
Objetivo-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; } }
Em seguida, crie o objeto de metadados:
Rápido
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objetivo-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];
- Crie um objeto
VisionImage
usando o objetoCMSampleBufferRef
e os metadados de rotação:Rápido
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objetivo-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Se necessário, gire a imagem para que sua propriedade
- Em seguida, passe a imagem para o método
detect(in:)
:Rápido
faceDetector.process(visionImage) { faces, error in guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
Objetivo-C
[faceDetector detectInImage:image completion:^(NSArray<FIRVisionFace *> *faces, NSError *error) { if (error != nil) { return; } else if (faces != nil) { // Recognized faces } }];
3. Obtenha informações sobre rostos detectados
Se a operação de detecção facial for bem-sucedida, o detector facial passará uma matriz de objetosVisionFace
para o manipulador de conclusão. Cada objeto VisionFace
representa um rosto que foi detectado na imagem. Para cada rosto, você pode obter suas coordenadas delimitadoras na imagem de entrada, bem como qualquer outra informação que você configurou para o detector de rosto encontrar. Por exemplo: Rápido
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 } }
Objetivo-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; } }
Exemplo de contornos faciais
Quando a detecção de contorno facial está ativada, você obtém uma lista de pontos para cada característica facial detectada. Esses pontos representam a forma do recurso. Consulte Visão geral dos conceitos de detecção de rosto para obter detalhes sobre como os contornos são representados.
A imagem a seguir ilustra como esses pontos são mapeados para uma face (clique na imagem para ampliar):
Detecção facial em tempo real
Se você quiser usar a detecção facial em um aplicativo em tempo real, siga estas diretrizes para obter as melhores taxas de quadros:
Configure o detector facial para usar detecção de contorno facial ou classificação e 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 de pontos de referência e classificaçãoAtive o modo
fast
(ativado por padrão).Considere capturar imagens com uma resolução mais baixa. No entanto, lembre-se também dos requisitos de dimensão de imagem desta API.
- Limite as chamadas para o detector. Se um novo quadro de vídeo ficar disponível enquanto o detector estiver em execução, elimine o quadro.
- Se você estiver usando a saída do detector para sobrepor gráficos na imagem de entrada, primeiro obtenha 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 na superfície de exibição apenas uma vez para cada quadro de entrada. Veja as classes previewOverlayView e FIRDetectionOverlayView no aplicativo de exemplo de demonstração para ver um exemplo.