O Kit de ML oferece dois SDKs otimizados para detecção de pose.
Nome do SDK | PoseDetection | PoseDetectionAccurate |
---|---|---|
Implementação | Os recursos do detector de base são vinculados de forma estática ao app no momento da build. | Os recursos do detector preciso são vinculados de forma estática ao app no momento da criação. |
Tamanho do app | Até 29,6 MB | Até 33,2 MB |
Desempenho | iPhone X: ~45FPS | iPhone X: ~29FPS |
Faça um teste
- Teste o app de exemplo para conferir um exemplo de uso dessa API.
Antes de começar
Inclua os seguintes pods do Kit de ML no Podfile:
# If you want to use the base implementation: pod 'GoogleMLKit/PoseDetection', '7.0.0' # If you want to use the accurate implementation: pod 'GoogleMLKit/PoseDetectionAccurate', '7.0.0'
Depois de instalar ou atualizar os pods do projeto, abra o projeto do Xcode usando o
xcworkspace
. O Kit de ML é compatível com a versão 13.2.1 ou mais recente do Xcode.
1. Criar uma instância de PoseDetector
Para detectar uma pose em uma imagem, primeiro crie uma instância de PoseDetector
e
especifique as configurações do detector, se quiser.
PoseDetector
opções
Modo de detecção
O PoseDetector
opera em dois modos de detecção. Escolha a opção que corresponde
ao seu caso de uso.
stream
(padrão)- O detector de pose primeiro detecta a pessoa mais proeminente na imagem e depois executa a detecção de pose. Em frames subsequentes, a etapa de detecção de pessoas não será realizada, a menos que a pessoa fique obscura ou não seja mais detectada com alta confiança. O detector de pose vai tentar rastrear a pessoa mais proeminente e retornar a pose dela em cada inferência. Isso reduz a latência e agiliza a detecção. Use esse modo quando quiser detectar a pose em um stream de vídeo.
singleImage
- O detector de pose vai detectar uma pessoa e executar a detecção de pose. A etapa de detecção de pessoas será executada para cada imagem, portanto, a latência será maior e não haverá rastreamento de pessoas. Use esse modo ao usar a detecção de pose em imagens estáticas ou quando o rastreamento não for necessário.
Especifique as opções do detector de pose:
// Base pose detector with streaming, when depending on the PoseDetection SDK let options = PoseDetectorOptions() options.detectorMode = .stream // Accurate pose detector on static images, when depending on the // PoseDetectionAccurate SDK let options = AccuratePoseDetectorOptions() options.detectorMode = .singleImage
// Base pose detector with streaming, when depending on the PoseDetection SDK MLKPoseDetectorOptions *options = [[MLKPoseDetectorOptions alloc] init]; options.detectorMode = MLKPoseDetectorModeStream; // Accurate pose detector on static images, when depending on the // PoseDetectionAccurate SDK MLKAccuratePoseDetectorOptions *options = [[MLKAccuratePoseDetectorOptions alloc] init]; options.detectorMode = MLKPoseDetectorModeSingleImage;
Por fim, receba uma instância de PoseDetector
. Transmita as opções especificadas:
let poseDetector = PoseDetector.poseDetector(options: options)
MLKPoseDetector *poseDetector = [MLKPoseDetector poseDetectorWithOptions:options];
2. Preparar a imagem de entrada
Para detectar poses, siga as etapas abaixo para cada imagem ou frame de vídeo.
Se você tiver ativado o modo de stream, precisará criar objetos VisionImage
usando
CMSampleBuffer
.
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 a.orientation
correta.let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
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 no
CMSampleBuffer
.Para conferir a orientação da imagem:
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 } }
- (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:let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Processar a imagem
Transmita o VisionImage
para um dos métodos de processamento de imagem do detector de poses. É possível usar o método process(image:)
assíncrono ou o método results()
síncrono.
Para detectar objetos de modo síncrono:
var results: [Pose] do { results = try poseDetector.results(in: image) } catch let error { print("Failed to detect pose with error: \(error.localizedDescription).") return } guard let detectedPoses = results, !detectedPoses.isEmpty else { print("Pose detector returned no results.") return } // Success. Get pose landmarks here.
NSError *error; NSArray*poses = [poseDetector resultsInImage:image error:&error]; if (error != nil) { // Error. return; } if (poses.count == 0) { // No pose detected. return; } // Success. Get pose landmarks here.
Para detectar objetos de modo assíncrono:
poseDetector.process(image) { detectedPoses, error in guard error == nil else { // Error. return } guard !detectedPoses.isEmpty else { // No pose detected. return } // Success. Get pose landmarks here. }
[poseDetector processImage:image completion:^(NSArray* _Nullable poses, NSError * _Nullable error) { if (error != nil) { // Error. return; } if (poses.count == 0) { // No pose detected. return; } // Success. Get pose landmarks here. }];
4. Receber informações sobre a pose detectada
Se uma pessoa for detectada na imagem, a API de detecção de pose vai transmitir uma
matriz de objetos Pose
para o gerenciador de conclusão ou retornar a matriz,
dependendo se você chamou o método assíncrono ou síncrono.
Se a pessoa não estiver completamente dentro da imagem, o modelo vai atribuir as coordenadas dos pontos de referência ausentes fora do frame e vai atribuir a elas valores de InFrameConfidence baixos.
Se nenhuma pessoa for detectada, a matriz vai estar vazia.
for pose in detectedPoses { let leftAnkleLandmark = pose.landmark(ofType: .leftAnkle) if leftAnkleLandmark.inFrameLikelihood > 0.5 { let position = leftAnkleLandmark.position } }
for (MLKPose *pose in detectedPoses) { MLKPoseLandmark *leftAnkleLandmark = [pose landmarkOfType:MLKPoseLandmarkTypeLeftAnkle]; if (leftAnkleLandmark.inFrameLikelihood > 0.5) { MLKVision3DPoint *position = leftAnkleLandmark.position; } }
Dicas para melhorar a performance
A qualidade dos resultados depende da qualidade da imagem de entrada:
- Para que o Kit de ML detecte a pose com precisão, a pessoa na imagem precisa ser representada por dados de pixel suficientes. Para ter a melhor performance, o assunto precisa ter pelo menos 256 x 256 pixels.
- Se você detectar a pose em um aplicativo em tempo real, considere as dimensões gerais das imagens de entrada. Já que as imagens menores podem ser processadas mais rapidamente, reduza a latência capturando imagens em resoluções menores, mas lembre-se dos requisitos de resolução acima e faça o objeto ocupar o máximo possível da imagem.
- Uma imagem com foco inadequado também pode afetar a precisão. Se os resultados não forem aceitáveis, peça para o usuário recapturar a imagem.
Se você quiser usar a detecção de pose em um aplicativo em tempo real, siga estas diretrizes para conseguir as melhores taxas de frames:
- Use o SDK básico do PoseDetection e o modo de detecção
stream
. - Capture imagens em uma resolução menor. No entanto, lembre-se também dos requisitos de dimensão de imagem da API.
- Para processar frames de vídeo, use a API síncrona
results(in:)
do detector. Chame esse método da função captureOutput(_, didOutput:from:) da AVCaptureVideoDataOutputSampleBufferDelegate para receber resultados síncronos do frame de vídeo fornecido. Mantenha AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames como verdadeiro para limitar as chamadas ao detector. Se um novo frame de vídeo ficar disponível durante a execução do detector, 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 as classes previewOverlayView e MLKDetectionOverlayView no app de exemplo da demonstração para conferir um exemplo.
Próximas etapas
- Para saber como usar os pontos de referência de pose para classificar poses, consulte Dicas de classificação de poses.
- Consulte o guia de início rápido do Kit de ML no GitHub para conferir um exemplo de uso desta API.