É possível usar o Kit de ML para detectar e rastrear objetos em frames de vídeo sucessivos.
Quando você transmite uma imagem para o Kit de ML, ele detecta até cinco objetos junto com a posição de cada objeto na imagem. Ao detectar objetos em streams de vídeo, cada objeto tem um ID exclusivo que pode ser usado para rastreá-lo de frame a frame. Também é possível ativar a classificação aproximada de objetos, que rotula objetos com descrições de categorias amplas.
Testar
- Teste o app de exemplo para conferir um exemplo de uso dessa API.
- Consulte o app de demonstração do Material Design (em inglês) para uma implementação completa dessa API.
Antes de começar
- Inclua os seguintes pods do Kit de ML no seu Podfile:
pod 'GoogleMLKit/ObjectDetection', '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.
1. Configurar o detector de objetos
Para detectar e rastrear objetos, primeiro crie uma instância de
ObjectDetector
e, se quiser, especifique as configurações do detector que você quer
alterar do padrão.
Configure o detector de objetos para seu caso de uso com um objeto
ObjectDetectorOptions
. É possível alterar as seguintes configurações:Configurações do detector de objetos Modo de detecção .stream
(padrão) |.singleImage
No modo de stream (padrão), o detector de objetos é executado com latência muito baixa, mas pode produzir resultados incompletos (como caixas delimitadoras ou categorias não especificadas) nas primeiras invocações do detector. Além disso, no modo de stream, o detector atribui IDs de rastreamento a objetos, que podem ser usados para rastrear objetos em frames. Use esse modo quando quiser rastrear objetos ou quando a baixa latência for importante, como ao processar streams de vídeo em tempo real.
No modo de imagem única, o detector de objetos retorna o resultado depois que a caixa delimitadora do objeto é determinada. Se você também ativar a classificação, ela retornará o resultado depois que a caixa delimitadora e o rótulo da categoria estiverem disponíveis. Como consequência, a latência de detecção é potencialmente maior. Além disso, no modo de imagem única, os IDs de acompanhamento não são atribuídos. Use esse modo se a latência não for crítica e você não quiser lidar com resultados parciais.
Detectar e rastrear vários objetos false
(padrão) |true
Define se é preciso detectar e rastrear até cinco objetos ou apenas o objeto mais proeminente (padrão).
Classificar objetos false
(padrão) |true
Se os objetos detectados serão ou não classificados em categorias gerais. Quando ativado, o detector de objetos os classifica nas seguintes categorias: artigos de moda, alimentos, artigos domésticos, locais e plantas.
A API de detecção e rastreamento de objetos é otimizada para estes dois casos de uso principais:
- Detecção ao vivo e rastreamento do objeto mais proeminente no visor da câmera.
- A detecção de vários objetos em uma imagem estática.
Se quiser configurar a API para esses casos de uso:
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- Consiga uma instância de
ObjectDetector
:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. Preparar a imagem de entrada
Para detectar e rastrear objetos, faça o seguinte para cada imagem ou frame de vídeo.
Se você ativou o modo de stream, é necessário criar objetos VisionImage
a partir de CMSampleBuffer
s.
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. Processar a imagem
TransmitaVisionImage
para um dos métodos de processamento de imagem do detector de objetos. É possível usar o método process(image:)
assíncrono ou o
método síncrono results()
.
Para detectar objetos de forma assíncrona:
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
Para detectar objetos de forma síncrona:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. Receber informações sobre os objetos detectados
Se a chamada para o processador de imagem for bem-sucedida, ela transmite uma lista deObject
s para o gerenciador de conclusão ou retorna a lista, dependendo se
você chamou o método assíncrono ou síncrono.
Cada Object
contém as seguintes propriedades:
frame |
Um CGRect que indica a posição do objeto na imagem. |
trackingID |
Um número inteiro que identifica o objeto em imagens ou "nil" no modo de imagem única. |
labels |
Uma matriz de rótulos que descrevem o objeto retornado pelo detector.
A propriedade ficará vazia se a opção de detector shouldEnableClassification estiver definida como false .
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.joined(separator:"\n") }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; ... } }
Como melhorar a usabilidade e o desempenho
Para ter a melhor experiência do usuário, siga estas diretrizes no seu app:
- A detecção bem-sucedida de objetos depende da complexidade visual do objeto. Para serem detectados, objetos com um pequeno número de recursos visuais podem precisar ocupar uma parte maior da imagem. Forneça aos usuários orientações sobre como capturar entradas que funcionem bem com o tipo de objeto que você quer detectar.
- Ao usar a classificação, se você quiser detectar objetos que não se enquadrem nas categorias compatíveis, implemente o tratamento especial para objetos desconhecidos.
Além disso, confira a coleção de Padrões para recursos com tecnologia de machine learning do Material Design.
Ao usar o modo de streaming em um aplicativo em tempo real, siga estas diretrizes para ter as melhores taxas de frames:
- Não use a detecção de vários objetos no modo de streaming, porque a maioria dos dispositivos não será capaz de produzir taxas de frames adequadas.
- Desative a classificação se ela não for necessária.
- 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.