É possível usar o Kit de ML para detectar e rastrear objetos em frames de vídeo.
Quando você transmite imagens do Kit de ML, ele retorna, para cada imagem, uma lista de até cinco objetos detectados e a posição deles na imagem. Cada objeto que você detecta em streams de vídeo tem um ID que pode ser rastreado nas imagens. É possível também, como opção, ativar a classificação abrangente de objetos, que marca objetos com descrições de categorias amplas.
Antes de começar
- Se você ainda não adicionou o Firebase ao seu app, siga as etapas no guia de iniciação.
- Inclua as bibliotecas do kit de ML no seu Podfile:
  pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0' .xcworkspace.
- Importe o Firebase para seu app:
  Swiftimport Firebase Objective-C@import Firebase; 
1. Configurar o detector de objetos
Para começar a detectar e rastrear objetos, primeiro crie uma instância de
VisionObjectDetector, especificando opcionalmente 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 - VisionObjectDetectorOptions. É possível alterar as seguintes configurações:- Configurações do detector de objetos - Modo de detecção - .stream(padrão) |- .singleImage- No modo de streaming (padrão), o detector de objetos é executado com baixa latência, mas pode produzir resultados incompletos, como caixas delimitadoras ou categoria não especificadas, nas primeiras chamadas do detector. Além disso, no modo de streaming, 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 aguarda até que a caixa delimitadora e a categoria (se você tiver ativado a classificação) de um objeto detectado estejam disponíveis antes de retornar um resultado. Como resultado, 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 essencial e você não quiser lidar com resultados parciais. - Detectar e rastrear vários objetos - false(padrão) |- true- Se for preciso detectar e rastrear até cinco objetos ou apenas o objeto mais proeminente (padrão). - Classificar objetos - false(padrão) |- true- Se for preciso ou não classificar os objetos detectados em categorias abrangentes. Quando ativado, o detector de objetos os classifica nas seguintes categorias: artigos de moda, alimentos, artigos domésticos, locais, plantas e desconhecido. - A API de detecção e rastreamento de objetos é otimizada para os dois casos de uso principais a seguir: - Detecção ao vivo e rastreamento do objeto mais proeminente no visor da câmera
- Detecção de vários objetos em uma imagem estática
 - Para configurar a API para esses casos de uso: - Swift- // Live detection and tracking let options = VisionObjectDetectorOptions() options.detectorMode = .stream options.shouldEnableMultipleObjects = false options.shouldEnableClassification = true // Optional // Multiple object detection in static images let options = VisionObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true // Optional- Objective-C- // Live detection and tracking FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeStream; options.shouldEnableMultipleObjects = NO; options.shouldEnableClassification = YES; // Optional // Multiple object detection in static images FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init]; options.detectorMode = FIRVisionObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; // Optional
- Receba uma instância de - FirebaseVisionObjectDetector:- Swift- let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)- Objective-C- FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. Executar o detector de objetos
Para detectar e rastrear objetos, siga as etapas abaixo para cada imagem ou frame de vídeo.
Se você tiver ativado o modo de stream, precisará criar objetos VisionImage a partir de
CMSampleBufferRef.
- Crie um objeto - VisionImageusando um- UIImageou um- CMSampleBufferRef.- Para usar um - UIImage:- Se necessário, gire a imagem para que a propriedade imageOrientationseja.up.
- Crie um objeto VisionImageusando aUIImagecom a rotação correta. Não especifique metadados de rotação: o valor padrão,.topLeft, precisa ser usado.Swiftlet image = VisionImage(image: uiImage) Objective-CFIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage]; 
 - Para usar um - CMSampleBufferRef:- 
    Crie um objeto VisionImageMetadataque especifique a orientação dos dados da imagem contidos no bufferCMSampleBufferRef.Para ver a orientação da imagem: Swiftfunc 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 } } Objective-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: Swiftlet cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition ) Objective-CFIRVisionImageMetadata *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 VisionImageusando o objetoCMSampleBufferRefe os metadados de rotação:Swiftlet image = VisionImage(buffer: sampleBuffer) image.metadata = metadata Objective-CFIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata; 
 
- Se necessário, gire a imagem para que a propriedade 
- Passe o - VisionImagepara 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- results()síncrono.- Para detectar objetos de modo assíncrono: - Swift- objectDetector.process(image) { detectedObjects, error in guard error == nil else { // Error. return } guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }- Objective-C- [objectDetector processImage:image completion:^(NSArray<FIRVisionObject *> * _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ... }];- Para detectar objetos de modo síncrono: - Swift- var results: [VisionObject]? = nil do { results = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard let detectedObjects = results, !detectedObjects.isEmpty else { print("Object detector returned no results.") return } // ...- Objective-C- NSError *error; NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects == nil | objects.count == 0) { // No objects detected. return; } // Success. Get object info here. // ...
- Se a chamada para o processador de imagem for bem-sucedida, ela transmitirá uma lista de - VisionObjectpara o gerenciador de conclusão ou retornará a lista, caso você tenha chamado o método assíncrono ou síncrono.- Cada - VisionObjectcontém as seguintes propriedades:- frame- Um - CGRectque indica a posição do objeto na imagem.- trackingID- Um número inteiro que identifica o objeto nas imagens. Nulo no modo de imagem única. - classificationCategory- A categoria abrangente do objeto. Se o detector de objetos não tiver a classificação ativada, isso será sempre - .unknown.- confidence- O nível de confiança da classificação do objeto. Se o detector de objetos não tiver a classificação ativada ou o objeto for classificado como desconhecido, isso será - nil.- Swift- // detectedObjects contains one item if multiple object detection wasn't enabled. for obj in detectedObjects { let bounds = obj.frame let id = obj.trackingID // If classification was enabled: let category = obj.classificationCategory let confidence = obj.confidence }- Objective-C- // The list of detected objects contains one item if multiple // object detection wasn't enabled. for (FIRVisionObject *obj in objects) { CGRect bounds = obj.frame; if (obj.trackingID) { NSInteger id = obj.trackingID.integerValue; } // If classification was enabled: FIRVisionObjectCategory category = obj.classificationCategory; float confidence = obj.confidence.floatValue; }
Como melhorar a usabilidade e o desempenho
Para a melhor experiência do usuário, siga estas diretrizes no aplicativo:
- A detecção bem-sucedida de objetos depende da complexidade visual do objeto. Objetos com um pequeno número de recursos visuais podem precisar ocupar uma parte maior da imagem a ser detectada. 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 suportadas, implemente o tratamento especial para objetos desconhecidos.
Além disso, confira o conjunto de [app de demonstração do Material Design do Kit de ML][showcase-link]{: .external} e a coleção Padrões de recursos de machine learning do Material Design.
Ao usar o modo de streaming em um aplicativo em tempo real, siga estas diretrizes para alcançar 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. 
- Limite as chamadas ao detector. Se um novo frame de vídeo ficar disponível durante a execução do detector, descarte esse frame.
- Se você estiver usando a saída do detector para sobrepor elementos gráficos na imagem de entrada, primeiro acesse o resultado do Kit de ML. Em seguida, renderize a imagem e faça a sobreposição de uma só vez. Ao fazer isso, você renderiza a superfície de exibição apenas uma vez para cada frame de entrada. Consulte as classes previewOverlayView e FIRDetectionOverlayView no app de exemplo da demonstração.